IdentityServer4 源码分析

1.首先再github 上下载源代码

(这里我下载的是:3.1.x):https://github.com/IdentityServer/IdentityServer4/blob/master/docs/index.rst 

2.打开源代码,

适当的编译下,重新配置下nuget,这里就不展开了

3.打开示例项目:

IdentityServer4\samples\Quickstarts\3_AspNetCoreAndApis\src\IdentityServer

这里以这个示例为准,也可以是别的

4.准备:

把identityserver4的源代码引用到示例里,把nuget上的包删掉,引用IdentityServer4源代码为依赖向,编译:

 备注:可能会出问题,反正我是碰到了一堆的问题,有的依赖不行,有的包不行,源代码netcore的版本是3.1 把IdentityServer 改成3.1..(此处自己解决,有问题留言)

5.正式开始:

5.1   internal class IdentityServerAuthenticationService : IAuthenticationService

这个类继承 IAuthenticationService ,包认证服务封装了。

        public IdentityServerAuthenticationService(
            Decorator<IAuthenticationService> decorator,
            IAuthenticationSchemeProvider schemes,
            ISystemClock clock,
            IUserSession session,
            IdentityServerOptions options,
            ILogger<IdentityServerAuthenticationService> logger)
        {
            _inner = decorator.Instance;//这里又把认证服务给传了进来,很多默认的调用时用这个里面
            
            _schemes = schemes;
            _clock = clock;
            _session = session;
            _options = options;
            _logger = logger;
        }

 5.2    internal class FederatedSignoutAuthenticationHandlerProvider : IAuthenticationHandlerProvider

(为authenticationScheme和请求提供适当的IAuthenticationHandler实例)

 IAuthenticationHandler 根据请求创建,以处理针对特定方案的身份验证。

这里也有一个,在这里故技重施

5.3 他们是怎么个逻辑呢,看看这里

      public static IIdentityServerBuilder AddCookieAuthentication(this IIdentityServerBuilder builder)
        {
            builder.Services.AddAuthentication(IdentityServerConstants.DefaultCookieAuthenticationScheme)
                .AddCookie(IdentityServerConstants.DefaultCookieAuthenticationScheme)
                .AddCookie(IdentityServerConstants.ExternalCookieAuthenticationScheme);

            builder.Services.AddSingleton<IConfigureOptions<CookieAuthenticationOptions>, ConfigureInternalCookieOptions>();
            builder.Services.AddSingleton<IPostConfigureOptions<CookieAuthenticationOptions>, PostConfigureInternalCookieOptions>();
            builder.Services.AddTransientDecorator<IAuthenticationService, IdentityServerAuthenticationService>();
            builder.Services.AddTransientDecorator<IAuthenticationHandlerProvider, FederatedSignoutAuthenticationHandlerProvider>();
        //这个函数,是identity自己封装的,里面做了不少操作,主要是把系统的对象加了个壳Decorator,和上面的逻辑对应,然后用自己把系统的给顶了
            return builder;
        }
        internal static void AddDecorator<TService>(this IServiceCollection services)
        {
            var registration = services.LastOrDefault(x => x.ServiceType == typeof(TService));
            if (registration == null)
            {
                throw new InvalidOperationException("Service type: " + typeof(TService).Name + " not registered.");
            }
            if (services.Any(x => x.ServiceType == typeof(Decorator<TService>)))
            {
                throw new InvalidOperationException("Decorator already registered for type: " + typeof(TService).Name + ".");
            }

            services.Remove(registration);

            if (registration.ImplementationInstance != null)
            {
                var type = registration.ImplementationInstance.GetType();
                var innerType = typeof(Decorator<,>).MakeGenericType(typeof(TService), type);
                services.Add(new ServiceDescriptor(typeof(Decorator<TService>), innerType, ServiceLifetime.Transient));
                services.Add(new ServiceDescriptor(type, registration.ImplementationInstance));
            }
            else if (registration.ImplementationFactory != null)
            {
                services.Add(new ServiceDescriptor(typeof(Decorator<TService>), provider =>
                {
                    return new DisposableDecorator<TService>((TService)registration.ImplementationFactory(provider));
                }, registration.Lifetime));
            }
            else
            {
                var type = registration.ImplementationType;
                var innerType = typeof(Decorator<,>).MakeGenericType(typeof(TService), registration.ImplementationType);
                services.Add(new ServiceDescriptor(typeof(Decorator<TService>), innerType, ServiceLifetime.Transient));
                services.Add(new ServiceDescriptor(type, type, registration.Lifetime));
            }
        }
    }

5.4   internal class PostConfigureInternalCookieOptions : IPostConfigureOptions<CookieAuthenticationOptions>

这个是验证用的参数,执行函数: GetHandlerAsync   获取IAuthenticationHandler时创建的参数,

这里面有几个比较有意思的地方:

 public void PostConfigure(string name, CookieAuthenticationOptions options)
        {
            var scheme = _idsrv.Authentication.CookieAuthenticationScheme ??
                _authOptions.Value.DefaultAuthenticateScheme ??
                _authOptions.Value.DefaultScheme;

            if (name == scheme)
            {
                _idsrv.UserInteraction.LoginUrl = _idsrv.UserInteraction.LoginUrl ?? options.LoginPath;//这里LoginPath有一个默认的地址
                _idsrv.UserInteraction.LoginReturnUrlParameter = _idsrv.UserInteraction.LoginReturnUrlParameter ?? options.ReturnUrlParameter;//还记着返回的url
                _idsrv.UserInteraction.LogoutUrl = _idsrv.UserInteraction.LogoutUrl ?? options.LogoutPath;//这里也有个默认的地址

                _logger.LogDebug("Login Url: {url}", _idsrv.UserInteraction.LoginUrl);
                _logger.LogDebug("Login Return Url Parameter: {param}", _idsrv.UserInteraction.LoginReturnUrlParameter);
                _logger.LogDebug("Logout Url: {url}", _idsrv.UserInteraction.LogoutUrl);

                _logger.LogDebug("ConsentUrl Url: {url}", _idsrv.UserInteraction.ConsentUrl);
                _logger.LogDebug("Consent Return Url Parameter: {param}", _idsrv.UserInteraction.ConsentReturnUrlParameter);

                _logger.LogDebug("Error Url: {url}", _idsrv.UserInteraction.ErrorUrl);
                _logger.LogDebug("Error Id Parameter: {param}", _idsrv.UserInteraction.ErrorIdParameter);
            }
        }

看下cookie的参数:

 5.5 来看看 UseIdentityServer 干了些啥

        public static IApplicationBuilder UseIdentityServer(this IApplicationBuilder app, IdentityServerMiddlewareOptions options = null)
        {
            app.Validate();

            app.UseMiddleware<BaseUrlMiddleware>();

            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();//这里竟然解决了一个bug,!!!!具体是啥我也没看懂
            options.AuthenticationMiddleware(app);

            app.UseMiddleware<MutualTlsTokenEndpointMiddleware>();
            app.UseMiddleware<IdentityServerMiddleware>();

            return app;
        }

可以看到这里有初始化执行的 ,也有3个中间件:BaseUrlMiddleware MutualTlsTokenEndpointMiddleware  IdentityServerMiddleware

a.  app.Validate(); 这个函数就是启动时检测的,里面一堆的控制台输出。有个比较有意思的函数,下面:

 

      internal static void Validate(this IApplicationBuilder app)
        {
            var loggerFactory = app.ApplicationServices.GetService(typeof(ILoggerFactory)) as ILoggerFactory;
            if (loggerFactory == null) throw new ArgumentNullException(nameof(loggerFactory));

            var logger = loggerFactory.CreateLogger("IdentityServer4.Startup");
            logger.LogInformation("Starting IdentityServer4 version {version}", typeof(IdentityServerApplicationBuilderExtensions).Assembly.GetName().Version.ToString());

            var scopeFactory = app.ApplicationServices.GetService<IServiceScopeFactory>();

            using (var scope = scopeFactory.CreateScope())
            {
                var serviceProvider = scope.ServiceProvider;
          //下面这个函数,检查对应的服务是否注册,也是很有意思
                TestService(serviceProvider, typeof(IPersistedGrantStore), logger, "No storage mechanism for grants specified. Use the 'AddInMemoryPersistedGrants' extension method to register a development version.");
                TestService(serviceProvider, typeof(IClientStore), logger, "No storage mechanism for clients specified. Use the 'AddInMemoryClients' extension method to register a development version.");
                TestService(serviceProvider, typeof(IResourceStore), logger, "No storage mechanism for resources specified. Use the 'AddInMemoryIdentityResources' or 'AddInMemoryApiResources' extension method to register a development version.");

                var persistedGrants = serviceProvider.GetService(typeof(IPersistedGrantStore));
                if (persistedGrants.GetType().FullName == typeof(InMemoryPersistedGrantStore).FullName)
                {
                    logger.LogInformation("You are using the in-memory version of the persisted grant store. This will store consent decisions, authorization codes, refresh and reference tokens in memory only. If you are using any of those features in production, you want to switch to a different store implementation.");
                }

                var options = serviceProvider.GetRequiredService<IdentityServerOptions>();
                ValidateOptions(options, logger);

                ValidateAsync(serviceProvider, logger).GetAwaiter().GetResult();
            }
        }

 

 

 

b.看看 BaseUrlMiddleware,下面时核心代码:

 

public async Task Invoke(HttpContext context)
        {
            var request = context.Request;

            if (_options.PublicOrigin.IsPresent())
            {
                context.SetIdentityServerOrigin(_options.PublicOrigin);
            }

            context.SetIdentityServerBasePath(request.PathBase.Value.RemoveTrailingSlash());

            await _next(context);
        }

 

posted @ 2020-03-09 19:30  leolzi  阅读(1350)  评论(0编辑  收藏  举报