IdentityServer4源码解析_1_项目结构
2012 年 1 月 3 日
目录
- identityserver4源码解析_1_项目结构
- identityserver4源码解析_2_元数据接口
- identityserver4源码解析_3_认证接口
- identityserver4源码解析_4_令牌发放接口
- identityserver4源码解析_5_查询用户信息接口
- identityserver4源码解析_6_结束会话接口
- identityserver4源码解析_7_查询令牌信息接口
- identityserver4源码解析_8_撤销令牌接口
简介
Security源码解析系列介绍了微软提供的各种认证架构,其中OAuth2.0,OpenIdConnect属于远程认证架构,所谓远程认证,是指token的颁发是由另外的站点实现的。
IdentityServer4是基于OpenIdConnect协议的认证中心框架,能够帮助我们搭建中心化的认证服务。
可以将OpenIdConnect协议立即理解成需求文档,idsv4基于需求提供了一系列的api。
对于idsv还不太了解的可以看下面的资料,本系列主要学习梳理idsv的源码,结合协议加深理解。
晓晨姐姐系列文章
https://www.cnblogs.com/stulzq/p/8119928.html
官方文档
https://identityserver4.readthedocs.io/en/latest/
项目结构
项目地址如下
https://github.com/IdentityServer/IdentityServer4
克隆到本地,项目结构如图
核心项目是IdentityServer4,其余的都是与微软框架集成、以及处理持久化的项目。 项目结构如图。Endpoints文件夹就是接口文件,我们先看下依赖注入、中间件的代码,然后看下每个接口。
依赖注入
public static IIdentityServerBuilder AddIdentityServer(this IServiceCollection services) { var builder = services.AddIdentityServerBuilder(); builder .AddRequiredPlatformServices() .AddCookieAuthentication() .AddCoreServices() .AddDefaultEndpoints() .AddPluggableServices() .AddValidators() .AddResponseGenerators() .AddDefaultSecretParsers() .AddDefaultSecretValidators(); // provide default in-memory implementation, not suitable for most production scenarios builder.AddInMemoryPersistedGrants(); return builder; }
- AddRequiredPlatformServices – 注入平台服务
- IHttpContextAccessor:HttpContext访问器
- IdentityServerOptions:配置类
public static IIdentityServerBuilder AddRequiredPlatformServices(this IIdentityServerBuilder builder) { builder.Services.TryAddSingleton(); builder.Services.AddOptions(); builder.Services.AddSingleton( resolver => resolver.GetRequiredService >().Value); builder.Services.AddHttpClient(); return builder; }
- AddCookieAuthentication – 注入cookie服务
- 注入名称为idsrv的cookie认证架构
- 注入IAuthenticationService的实现IdentityServerAuthenticationService
- 注入IAuthenticationHandlerProvider的实现FederatedSignoutAuthenticationHandlerProvider
public static IIdentityServerBuilder AddCookieAuthentication(this IIdentityServerBuilder builder) { builder.Services.AddAuthentication(IdentityServerConstants.DefaultCookieAuthenticationScheme) .AddCookie(IdentityServerConstants.DefaultCookieAuthenticationScheme) .AddCookie(IdentityServerConstants.ExternalCookieAuthenticationScheme); builder.Services.AddSingleton, ConfigureInternalCookieOptions>(); builder.Services.AddSingleton , PostConfigureInternalCookieOptions>(); builder.Services.AddTransientDecorator (); builder.Services.AddTransientDecorator (); return builder; }
- AddCoreServices – 注入核心服务
////// Adds the core services. /// /// The builder. ///public static IIdentityServerBuilder AddCoreServices(this IIdentityServerBuilder builder) { builder.Services.AddTransient (); builder.Services.AddTransient (); builder.Services.AddTransient (); builder.Services.AddTransient (); builder.Services.AddTransient (); builder.Services.AddTransient (); // todo: remove in 3.0 #pragma warning disable CS0618 // Type or member is obsolete builder.Services.AddTransient (); #pragma warning restore CS0618 // Type or member is obsolete builder.Services.AddTransient (); builder.Services.AddTransient (); builder.Services.AddTransient (); builder.Services.AddScoped (); builder.Services.AddTransient(typeof(MessageCookie<>)); builder.Services.AddCors(); builder.Services.AddTransientDecorator (); return builder; }
- AddDefaultEndpoints – 注入接口
- AuthorizeCallbackEndpoint:认证回调接口
- AuthorizeEndpoint:认证接口
- CheckSessionEndpoint:检查会话接口
- DeviceAuthorizationEndpoint:设备认证接口
- DiscoveryEndpoint:元数据键接口
- DiscoveryEndpoint:元数据接口
- EndSessionCallbackEndpoint:结束会话回调接口
- EndSessionEndpoint:结束会话接口
- IntrospectionEndpoint:查询令牌信息接口
- TokenRevocationEndpoint:撤销令牌接口
- TokenEndpoint:发放令牌接口
- UserInfoEndpoint:查询用户信息接口
public static IIdentityServerBuilder AddDefaultEndpoints(this IIdentityServerBuilder builder) { builder.Services.AddTransient(); builder.AddEndpoint (EndpointNames.Authorize, ProtocolRoutePaths.AuthorizeCallback.EnsureLeadingSlash()); builder.AddEndpoint (EndpointNames.Authorize, ProtocolRoutePaths.Authorize.EnsureLeadingSlash()); builder.AddEndpoint (EndpointNames.CheckSession, ProtocolRoutePaths.CheckSession.EnsureLeadingSlash()); builder.AddEndpoint (EndpointNames.DeviceAuthorization, ProtocolRoutePaths.DeviceAuthorization.EnsureLeadingSlash()); builder.AddEndpoint (EndpointNames.Discovery, ProtocolRoutePaths.DiscoveryWebKeys.EnsureLeadingSlash()); builder.AddEndpoint (EndpointNames.Discovery, ProtocolRoutePaths.DiscoveryConfiguration.EnsureLeadingSlash()); builder.AddEndpoint (EndpointNames.EndSession, ProtocolRoutePaths.EndSessionCallback.EnsureLeadingSlash()); builder.AddEndpoint (EndpointNames.EndSession, ProtocolRoutePaths.EndSession.EnsureLeadingSlash()); builder.AddEndpoint (EndpointNames.Introspection, ProtocolRoutePaths.Introspection.EnsureLeadingSlash()); builder.AddEndpoint (EndpointNames.Revocation, ProtocolRoutePaths.Revocation.EnsureLeadingSlash()); builder.AddEndpoint (EndpointNames.Token, ProtocolRoutePaths.Token.EnsureLeadingSlash()); builder.AddEndpoint (EndpointNames.UserInfo, ProtocolRoutePaths.UserInfo.EnsureLeadingSlash()); return builder; }
- AddPluggableServices – 注入可插拔服务
public static IIdentityServerBuilder AddPluggableServices(this IIdentityServerBuilder builder) { builder.Services.TryAddTransient(); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient , ProtectedDataMessageStore >(); builder.Services.TryAddTransient , ProtectedDataMessageStore >(); builder.Services.TryAddTransient , ProtectedDataMessageStore >(); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.AddJwtRequestUriHttpClient(); builder.AddBackChannelLogoutHttpClient(); //builder.Services.AddHttpClient (); //builder.Services.AddHttpClient (); builder.Services.AddTransient (); builder.Services.AddTransient (); builder.Services.TryAddTransient (); builder.Services.AddDistributedMemoryCache(); return builder; }
- AddValidators – 注入校验类
public static IIdentityServerBuilder AddValidators(this IIdentityServerBuilder builder) { // core builder.Services.TryAddTransient(); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); // optional builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); return builder; }
- AddResponseGenerators – 注入响应生成类
public static IIdentityServerBuilder AddResponseGenerators(this IIdentityServerBuilder builder) { builder.Services.TryAddTransient(); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); builder.Services.TryAddTransient (); return builder; }
- AddDefaultSecretParsers & AddDefaultSecretValidators
////// Adds the default secret parsers. /// /// The builder. ///public static IIdentityServerBuilder AddDefaultSecretParsers(this IIdentityServerBuilder builder) { builder.Services.AddTransient (); builder.Services.AddTransient (); return builder; } /// /// Adds the default secret validators. /// /// The builder. ///public static IIdentityServerBuilder AddDefaultSecretValidators(this IIdentityServerBuilder builder) { builder.Services.AddTransient (); return builder; }
IdentityServerOptions – 配置类
////// The IdentityServerOptions class is the top level container for all configuration settings of IdentityServer. /// public class IdentityServerOptions { ////// Gets or sets the unique name of this server instance, e.g. https://myissuer.com. /// If not set, the issuer name is inferred from the request /// ////// Unique name of this server instance, e.g. https://myissuer.com /// public string IssuerUri { get; set; } ////// Gets or sets the origin of this server instance, e.g. https://myorigin.com. /// If not set, the origin name is inferred from the request /// Note: Do not set a URL or include a path. /// ////// Origin of this server instance, e.g. https://myorigin.com /// public string PublicOrigin { get; set; } ////// Gets or sets the value for the JWT typ header for access tokens. /// ////// The JWT typ value. /// public string AccessTokenJwtType { get; set; } = "at+jwt"; ////// Emits an aud claim with the format issuer/resources. That's needed for some older access token validation plumbing. Defaults to false. /// public bool EmitLegacyResourceAudienceClaim { get; set; } = false; ////// Gets or sets the endpoint configuration. /// ////// The endpoints configuration. /// public EndpointsOptions Endpoints { get; set; } = new EndpointsOptions(); ////// Gets or sets the discovery endpoint configuration. /// ////// The discovery endpoint configuration. /// public DiscoveryOptions Discovery { get; set; } = new DiscoveryOptions(); ////// Gets or sets the authentication options. /// ////// The authentication options. /// public AuthenticationOptions Authentication { get; set; } = new AuthenticationOptions(); ////// Gets or sets the events options. /// ////// The events options. /// public EventsOptions Events { get; set; } = new EventsOptions(); ////// Gets or sets the max input length restrictions. /// ////// The length restrictions. /// public InputLengthRestrictions InputLengthRestrictions { get; set; } = new InputLengthRestrictions(); ////// Gets or sets the options for the user interaction. /// ////// The user interaction options. /// public UserInteractionOptions UserInteraction { get; set; } = new UserInteractionOptions(); ////// Gets or sets the caching options. /// ////// The caching options. /// public CachingOptions Caching { get; set; } = new CachingOptions(); ////// Gets or sets the cors options. /// ////// The cors options. /// public CorsOptions Cors { get; set; } = new CorsOptions(); ////// Gets or sets the Content Security Policy options. /// public CspOptions Csp { get; set; } = new CspOptions(); ////// Gets or sets the validation options. /// public ValidationOptions Validation { get; set; } = new ValidationOptions(); ////// Gets or sets the device flow options. /// public DeviceFlowOptions DeviceFlow { get; set; } = new DeviceFlowOptions(); ////// Gets or sets the mutual TLS options. /// public MutualTlsOptions MutualTls { get; set; } = new MutualTlsOptions(); }
UserIdentityServer – 中间件逻辑
- 执行校验
- BaseUrlMiddleware中间件:设置BaseUrl
- 配置CORS跨域:CorsPolicyProvider根据client信息生成动态策略
- IdentityServerMiddlewareOptions默认调用了UseAuthentication,所以如果使用IdentityServer不用重复注册Authentication中间件
- 使用MutualTlsTokenEndpointMiddleware中间件:要求客户端、服务端都使用https,默认不开启
- 使用IdentityServerMiddleware中间件:IEndpointRouter根据请求寻找匹配的IEndpointHandler,如果找到的话则由EndPointHandler处理请求。
public static IApplicationBuilder UseIdentityServer(this IApplicationBuilder app, IdentityServerMiddlewareOptions options = null) { app.Validate(); app.UseMiddleware(); app.ConfigureCors(); // it seems ok if we have UseAuthentication more than once in the pipeline -- // this will just re-run the various callback handlers and the default authN // handler, which just re-assigns the user on the context. claims transformation // will run twice, since that's not cached (whereas the authN handler result is) // related: https://github.com/aspnet/Security/issues/1399 if (options == null) options = new IdentityServerMiddlewareOptions(); options.AuthenticationMiddleware(app); app.UseMiddleware (); app.UseMiddleware (); return app; }
结语
idsv的代码量还是比较大的,注入了大量的类。但是代码风格比较规范,脉络还是很清晰的。