第32章 事件
日志记录是更低级别的“printf”样式 - 事件代表有关IdentityServer中某些操作的更高级别信息。事件是结构化数据,包括事件ID,成功/失败信息,类别和详细信息。这使得查询和分析它们变得容易,并提取可用于进一步处理的有用信息。
活动适用于ELK,Seq或Splunk等活动商店。
32.1 发出事件
默认情况下不会启用事件 - 但可以在ConfigureServices
方法中进行全局配置,例如:
services.AddIdentityServer(options =>
{
options.Events.RaiseSuccessEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseErrorEvents = true;
});
要发出事件,请使用IEventService
DI容器并调用RaiseAsync
方法,例如:
public async Task Login(LoginInputModel model)
{
if (_users.ValidateCredentials(model.Username, model.Password))
{
// issue authentication cookie with subject ID and username
var user = _users.FindByUsername(model.Username);
await _events.RaiseAsync(new UserLoginSuccessEvent(user.Username, user.SubjectId, user.Username));
}
else
{
await _events.RaiseAsync(new UserLoginFailureEvent(model.Username, "invalid credentials"));
}
}
32.2 自定义接收器
我们的默认事件接收器只是将事件类序列化为JSON并将其转发到ASP.NET Core日志系统。如果要连接到自定义事件存储,请实现该IEventSink
接口并将其注册到DI。
以下示例使用Seq发出事件:
public class SeqEventSink : IEventSink
{
private readonly Logger _log;
public SeqEventSink()
{
_log = new LoggerConfiguration()
.WriteTo.Seq("http://localhost:5341")
.CreateLogger();
}
public Task PersistAsync(Event evt)
{
if (evt.EventType == EventTypes.Success ||
evt.EventType == EventTypes.Information)
{
_log.Information("{Name} ({Id}), Details: {@details}",
evt.Name,
evt.Id,
evt);
}
else
{
_log.Error("{Name} ({Id}), Details: {@details}",
evt.Name,
evt.Id,
evt);
}
return Task.CompletedTask;
}
}
将Serilog.Sinks.Seq
包添加到主机以使上述代码有效。
32.3 内置事件
IdentityServer中定义了以下事件:
ApiAuthenticationFailureEvent
&ApiAuthenticationSuccessEvent
获取内省端点上的成功/失败API身份验证。ClientAuthenticationSuccessEvent
&ClientAuthenticationFailureEvent
获取在令牌端点处成功/失败的客户端身份验证。TokenIssuedSuccessEvent
&TokenIssuedFailureEvent
获取成功/失败尝试请求身份令牌,访问令牌,刷新令牌和授权码。TokenIntrospectionSuccessEvent
&TokenIntrospectionFailureEvent
获取成功的令牌内省请求。TokenRevokedSuccessEvent
获取成功的令牌吊销请求。UserLoginSuccessEvent & UserLoginFailureEvent
成功/失败用户登录的快速入门UI引发。UserLogoutSuccessEvent
获取成功的注销请求。ConsentGrantedEvent
&ConsentDeniedEvent
在同意UI中引发。UnhandledExceptionEvent
获取未处理的异常。DeviceAuthorizationFailureEvent
&DeviceAuthorizationSuccessEvent
获取成功/失败的设备授权请求。
32.4 自定义事件
您可以创建自己的事件并通过我们的基础架构发出它们。
您需要从我们的基Event
类派生,该基类注入活动ID,时间戳等上下文信息。您的派生类可以添加特定于事件上下文的任意数据字段:
public class UserLoginFailureEvent : Event
{
public UserLoginFailureEvent(string username, string error)
: base(EventCategories.Authentication,
"User Login Failure",
EventTypes.Failure,
EventIds.UserLoginFailure,
error)
{
Username = username;
}
public string Username { get; set; }
}