zoukankan      html  css  js  c++  java
  • IdentityServer4授权和认证

    IdentityServer4 简称ids4

    oidc了解:http://www.jessetalk.cn/2018/04/04/oidc-asp-net-core/

    是一个去中心化的网上身份认证系统,集成了认证和授权

    博客园已经有很多大佬写过了。我也是跟着学,记录下学习成果

    授权服务器代码:

    var oidc = new Client
                {
                    ClientId = "oidc",
                    ClientName = "name",
                    ClientSecrets = { new Secret("secret".Sha256()) },
                    ClientUri = "http://www.cnblogs.com", //客户端
                    LogoUri = "https://www.cnblogs.com/images/logo_small.gif",
                    //AllowedGrantTypes={GrantType.AuthorizationCode }
    
                    /*
                     如果客户端使用的认证是
                     */
                    AllowedGrantTypes = GrantTypes.Hybrid,
                    AllowedScopes ={
                            IdentityServerConstants.StandardScopes.OpenId,
                            IdentityServerConstants.StandardScopes.Profile,
                            IdentityServerConstants.StandardScopes.Email,
                        },
                    RedirectUris = { "http://localhost:5001/signin-oidc" },
                    PostLogoutRedirectUris = { "http://localhost:5001/signout-callback-oidc" }
                };

    AllowedScopes 中的

    IdentityServerConstants.StandardScopes.OpenId,
                            IdentityServerConstants.StandardScopes.Profile必须的

    也可以不用枚举类型。直接写:“openid”,"profile"

    为什么说是必须定义的呢。因为ids4代码的封装。默认就添加了“openid”,"profile"两个scope

    因为只有openid才能确定唯一性

    而profile是用户资料信息

    github地址:

    https://github.com/aspnet/AspNetCore/blob/master/src/Security/Authentication/OpenIdConnect/src/OpenIdConnectOptions.cs

     可以看到其他的默认配置,比如回调地址,登出地址

    如果之前了解过授权和认证,对这个不陌生

    //使用ids中间件
    app.UseIdentityServer();

    认证代码,我自己写了挺多注释,可以忽略

      services.AddAuthentication(options =>
                {
                    /*
                     要想使用认证系统,必要先注册Scheme
                     而每一个Scheme必须指定一个Handler
                     AuthenticationHandler 负责对用户凭证的验证
                     这里指定的默认认证是cookie认证
                     Scheme可以翻译为方案,即默认的认证方案
    
                    因为这里用到了多个中间件,(AddAuthentication,AddCookie,AddOpenIdConnect)
                    OpenIdConnectDefaults.DisplayName 的默认值是oidc
                    指定AddOpenIdConnect是默认中间件,在AddOpenIdConnect配置了很多选项
    
                    如果只用了一个中间件,则可以不写,是否还记得cookie认证
                    //     services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
                    //     .AddCookie(option =>
                    //     {
                    //         ///Account/Login?ReturnUrl=%2Fadmin
                    //         option.LoginPath = "/login/index";
                    //         //option.ReturnUrlParameter = "params"; //指定参数名称
                    //         //option.Cookie.Domain
                    //         option.AccessDeniedPath = "/login/noAccess";
                    //         option.Cookie.Expiration = TimeSpan.FromSeconds(4);
                    //         option.Events = new CookieAuthenticationEvents
                    //         {
                    //             OnValidatePrincipal = LastChangedValidator.ValidateAsync
                    //         };
                    //     });
    
                     */
    
                    //options.DefaultScheme = "Cookies";
    
                    //默认的认证方案:cookie认证,信息是保存在cookie中的
                    options.DefaultAuthenticateScheme = "Cookies";
                    //oidc 就是openidConnect
    
    
                    //名字随便取,只要AddOpenIdConnect中的的oidc名字一样即可,
                    //这样才能找到
                    options.DefaultChallengeScheme = "oidc";
    
                    //默认使用oidc中间件
                    //options.DefaultChallengeScheme = OpenIdConnectDefaults.DisplayName;
    
    
                }).AddCookie("Cookies")
                .AddOpenIdConnect("oidc", options =>
                {
                    options.SignInScheme = "Cookies";
                    options.Authority = "http://localhost:5003";
                    options.RequireHttpsMetadata = false;
                    options.ClientId = "oidc";
                    options.ClientSecret = "secret";
                    options.SaveTokens = true;
                    //options.Scope.Add("openid");
                    /*
                     默认值是:id_token
                     */
                    //options.ResponseType = OpenIdConnectResponseType.CodeIdToken;
                    options.Events = new OpenIdConnectEvents
                    {
                        /*
                         远程异常触发
                         在授权服务器取消登陆或者取消授权      
                         */
                        OnRemoteFailure = OAuthFailureHandler =>
                        {
                            //跳转首页
                            OAuthFailureHandler.Response.Redirect("/");
                            OAuthFailureHandler.HandleResponse();
                            return Task.FromResult(0);
                        }
                    };
                });
    View Code

    配置其实跟OAuth2认证差不多,运行是没有问题的

    我这里主要讲解ids4的授权和认证类型ResponseType

    默认是 id_token ,源码是个好东西,我们看看

    客户端端id_token对应服务端,会返回id_token

    AllowedGrantTypes = GrantTypes.Implicit, 隐式模式

    它返回id_token信息,包含了用户信息的SubjectId,是TestUser配置的

    参考:https://www.cnblogs.com/jesse2013/p/oidc-in-aspnetcore-with-identity-server.html

    客户端端code id_token对应服务端,会返回id_token和access_token

    AllowedGrantTypes = GrantTypes.Hybrid, 混合模式

     可以用access_token 去userinfo endpoint获取用户信息

    access toke管的是权限,里面保存的是一些认证信息

    ,id token是身份信息

     

     http://localhost:5003/.well-known/openid-configuration 

    可以查看userinfo endpoint配置

    有人可能会注意到,在这里我们拿到的idtoken没有派上用场,我们的用户资料还是通过access_token从userinfo endpoint里拿的。这里有两个区别:

    1. userinfo endpoint是属于认证服务器实现的,并非资源服务器,有归属的区别
    2. id_token 是一个jwt,里面带有用户的唯一标识,我们在判断该用户已经存在的时候不需要再请求userinfo endpoint

    下图是对id_token进行解析得到的信息:sub即subject_id(用户唯一标识 )

     看网上很多例子都在Controller上打个Authorize标签

    当未授权就跳转到授权服务器,这样,这个网站那就必须使用授权服务器才能登陆

    比如:我这个网站可以有自己的密码登陆,也可以用第三方登陆。所以在没有授权的时候是跳转到登陆页面,

    让用户自己选择是密码登陆还是第三方授权登陆

     如果是这样,我没有授权登陆。只有访问这个Admin页面就会跳转到授权服务器,

    那如果我们添加多个第三方认证,比如QQ,微博,微信等等,那起步乱套了

    显然这不是我想要的,应该像简书这样,集成第三方登陆

    所以我们可以设置使用那个中间件options.DefaultChallengeScheme=“myCookies

    当没有登陆的是,会走AddCookie,跳转到到登陆页面

    比如我们这里注入了oidc授权,google授权

     services.AddAuthentication(options =>
                {
    
                    //默认的认证方案:cookie认证,信息是保存在cookie中的
                    options.DefaultAuthenticateScheme = "Cookies";
                  
                   
                    options.DefaultChallengeScheme = "myCookies";
    
    
                }).AddCookie("myCookies",options=> {
                    options.LoginPath = "/Account/Login";
                })
                .AddGoogle("googole", options => {
                   
                })
                .AddOpenIdConnect("oidc", options =>
                {
                }

    当用户单击,使用微博登陆则:通过Challenge方法指定使用那个schemes

     这样就会跳转到登陆页面,用户自己选择了

    可以用User.Identity.IsAuthenticated判断是否验证授权
    没有则手动触发: Challenge("oidc")
    oidc 为你想使用的第三方
    比如:我设置了,cookie,微博,QQ,google,oidc等等
    .AddCookie("cookie")
    .AddGoogole("google")
    .AddQQ("qq")
    当你想用google授权,则Challenge(”google")

    这样做的好处是:我网站只是接入别第三方登陆。至于使用第三方登陆还是使用我网站注册用户登陆
    都是由用户选择

    网络收集,没有一一验证:

    /***********************************相关事件***********************************/
        // 未授权时,重定向到OIDC服务器时触发
        //o.Events.OnRedirectToIdentityProvider = context => Task.CompletedTask;
    
        // 获取到授权码时触发
        //o.Events.OnAuthorizationCodeReceived = context => Task.CompletedTask;
        // 接收到OIDC服务器返回的认证信息(包含Code, ID Token等)时触发
        //o.Events.OnMessageReceived = context => Task.CompletedTask;
        // 接收到TokenEndpoint返回的信息时触发
        //o.Events.OnTokenResponseReceived = context => Task.CompletedTask;
        // 验证Token时触发
        //o.Events.OnTokenValidated = context => Task.CompletedTask;
        // 接收到UserInfoEndpoint返回的信息时触发
        //o.Events.OnUserInformationReceived = context => Task.CompletedTask;
        // 出现异常时触发
        //o.Events.OnAuthenticationFailed = context => Task.CompletedTask;
    
        // 退出时,重定向到OIDC服务器时触发
        //o.Events.OnRedirectToIdentityProviderForSignOut = context => Task.CompletedTask;
        // OIDC服务器退出后,服务端回调时触发
        //o.Events.OnRemoteSignOut = context => Task.CompletedTask;
        // OIDC服务器退出后,客户端重定向时触发
        //o.Events.OnSignedOutCallbackRedirect = context => Task.CompletedTask;
    View Code

    当用户没有授权,跳转到授权服务器的登陆地址,同意授权地址,都是默认值

    https://github.com/IdentityServer/IdentityServer4/blob/63a50d7838af25896fbf836ea4e4f37b5e179cd8/src/Constants.cs

    我们可以修改自己想要的地址

     

     然后添加Route

     这样就成功了

    大佬文章:

    https://www.cnblogs.com/jesse2013/p/oidc-in-aspnetcore-with-identity-server.html

    https://www.cnblogs.com/RainingNight/p/7635534.html

    https://www.cnblogs.com/xishuai/p/6274036.html

    https://www.cnblogs.com/cgzl/p/9253667.html

    https://cloud.tencent.com/developer/article/1048128

    https://www.cnblogs.com/stulzq/p/7879101.html

  • 相关阅读:
    kafka 官方 Quickstart
    oracle11.2 安装
    Perl参考函数/教程
    Mysql参见SHOW命令总结
    MySQL的Innodb缓存相关优化
    Oracle、Mysql和SQL Server数据库连接的URL写法
    jredis 客户端 使用
    sql基本命令-存储过程
    NoSql系列目录ElasticSearch-mongodb
    loadrunner 运行场景-Controller及Load Generators宿主主机优化
  • 原文地址:https://www.cnblogs.com/nsky/p/10350733.html
Copyright © 2011-2022 走看看