zoukankan      html  css  js  c++  java
  • 第五节:IdentityServer4的Pkce机制、令牌刷新机制、混合授权模式

    一. PKCE机制

    1. 准备

    (1). IDS4_Server1:认证授权服务器

    (2). MvcClient1:web客户端

     然后将上述两个项目配置成授权码模式(如何配置见上一节 IdentityServer4授权码模式介绍和代码实操演练

    PS: PKCE机制是在授权码模式的基础上,增加了几个验证参数,使其更加安全。

    2. 代码配置

    (1).IDS4_Server1中的Config1,新增 RequirePkce = true, 开启Pkce授权校验。

    (2).MvcClient1中的ConfigureServices中, 新增options.UsePkce = true;开启Pkce. (默认就是true,所以可以省略)

    PS:实际上在上一节的授权码模式中已经开启了pkce,只是没有单独点明增加的参数的含义。

    3. 剖析测试

    (1).在导向认证服务器的请求和确认授权页面的请求中,新增两个参数:code_challenge 和 code_challenge_method.

    (2).客户端携带授权码请求认证服务器的时候,携带的参数中新增: code_verifier

     

    二. 令牌刷新机制

    1. 准备

    (1). IDS4_Server1:认证授权服务器

    (2). MvcClient1:web客户端

     然后将上述两个项目配置成授权码模式(如何配置见上一节 IdentityServer4授权码模式介绍和代码实操演练

    2.代码配置

    (1).IDS4_Server1中的Config1,新增如下代码:

    (2).MvcClient1中的ConfigureServices中,新增如下代码:

    options.Scope.Add(OpenIdConnectScope.OfflineAccess);
    options.TokenValidationParameters.ClockSkew = TimeSpan.FromMinutes(1);
    options.TokenValidationParameters.RequireExpirationTime = true;

    3.运行结果

    页面显示多了个:  refresh_token

    注意过期时间:Token.expires_at

    三. 混合授权模式

    1. 背景

      access token 不含有任何关于身份认证的信息(用户声明信息),access token 的生命期可能会非常的长,即使用户离开了它仍有可能有效,它还有可能被用于无最终用户参与的情况,还有一种情况就是 access token 可能会被其它的客户端应用借用。所以,无论客户端是如何得到的 access token, 它都无法从 access token 里得到最终用户的信息以及最终用户的身份认证状态(用户声明信息)。

      在 OAuth2.0 里,access token 不是为客户端准备的,它对于客户端应该是不透明的, 但是客户端也需要从 access token 得到一些用户信息,实际上客户端应用只是 access token 的展示者, access token

    真正的目标观众是被保护的资源.

      在 OpenID Connect 里,加了一个 ID Token 令牌,它会和 access token 一同发送给客户端用,用于识别当前用户是他声称的的用户.

    2. 核心代码

    IDS4服务器:AllowedGrantTypes = GrantTypes.Hybrid

    代码分享:

     /// <summary>
        /// 混合模式
        /// </summary>
        public class Config2
        {
            /// <summary>
            /// IDS资源
            /// </summary>
            /// <returns></returns>
            public static IEnumerable<IdentityResource> GetIds()
            {
                return new List<IdentityResource>
                {
                    new IdentityResources.OpenId(),
                    new IdentityResources.Profile(),
                };
            }
    
            /// <summary>
            /// 可以使用ID4 Server 客户端资源
            /// </summary>
            /// <returns></returns>
            public static IEnumerable<Client> GetClients()
            {
                List<Client> clients = new List<Client>() {
                    new Client
                    {
                        ClientId = "client1",
                        ClientSecrets = { new Secret("123456".Sha256()) },
                        //混合模式
                        AllowedGrantTypes = GrantTypes.Hybrid,
                        //需要确认授权
                        RequireConsent = true,
                        
                        //关闭PKCE校验(默认是true)
                        RequirePkce = false,
    
                        //允许token通过浏览器
                        AllowAccessTokensViaBrowser=true,               
                        // where to redirect to after login(登录)
                        RedirectUris = { "http://127.0.0.1:7072/signin-oidc" },
                        // where to redirect to after logout(退出)
                        PostLogoutRedirectUris = { "http://127.0.0.1:7072/signout-callback-oidc" },
                        //允许的范围
                        AllowedScopes = new List<string>
                        {
                            IdentityServerConstants.StandardScopes.OpenId,
                            IdentityServerConstants.StandardScopes.Profile
                        },
                        AlwaysIncludeUserClaimsInIdToken=true,
                          //允许脱机访问
                        AllowOfflineAccess=true,
                        //accessToken有效期,默认事3600秒,即1小时 (单位:秒)
                        AccessTokenLifetime = 600
    
                    }
                };
                return clients;
            }
    
            /// <summary>
            /// 定义可以使用ID4的用户资源
            /// </summary>
            /// <returns></returns>
            public static List<TestUser> GetUsers()
            {
                var address = new
                {
                    street_address = "One Hacker Way",
                    locality = "Heidelberg",
                    postal_code = 69118,
                    country = "Germany"
                };
                return new List<TestUser>()
                {
                    new TestUser
                    {
                            SubjectId = "001",
                            Username = "ypf1",    //账号
                            Password = "123456",  //密码
                            Claims =
                            {
                                new Claim(JwtClaimTypes.Name, "Alice Smith"),
                                new Claim(JwtClaimTypes.GivenName, "Alice"),
                                new Claim(JwtClaimTypes.FamilyName, "Smith"),
                                new Claim(JwtClaimTypes.Email, "AliceSmith@email.com"),
                                new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean),
                                new Claim(JwtClaimTypes.WebSite, "http://alice.com"),
                                new Claim(JwtClaimTypes.Address, JsonSerializer.Serialize(address), IdentityServerConstants.ClaimValueTypes.Json)
                            }
                     },
                     new TestUser
                     {
                            SubjectId = "002",
                            Username = "ypf2",
                            Password = "123456",
                            Claims =
                            {
                                new Claim(JwtClaimTypes.Name, "Bob Smith"),
                                new Claim(JwtClaimTypes.GivenName, "Bob"),
                                new Claim(JwtClaimTypes.FamilyName, "Smith"),
                                new Claim(JwtClaimTypes.Email, "BobSmith@email.com"),
                                new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean),
                                new Claim(JwtClaimTypes.WebSite, "http://bob.com"),
                                //这是新的序列化模式哦
                                new Claim(JwtClaimTypes.Address, JsonSerializer.Serialize(address), IdentityServerConstants.ClaimValueTypes.Json)
                            }
                      }
                };
            }
    
    
        }
    View Code

    Mvc客户端:options.ResponseType = OpenIdConnectResponseType.CodeIdToken

    代码分享:

                {
                    JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
                    //添加Cookie认证
                    services.AddAuthentication(options =>
                    {
                        options.DefaultScheme = "Cookies";
                        options.DefaultChallengeScheme = "oidc";
                    })
                    .AddCookie("Cookies")
                    //通过OIDC协议远程请求认证
                    .AddOpenIdConnect("oidc", options =>
                    {
                        options.Authority = "http://127.0.0.1:7070";   //认证授权服务器地址
                        options.RequireHttpsMetadata = false;
                        options.ClientId = "client1";    //客户端ID
                        options.ClientSecret = "123456"; //客户端秘钥
    
                        //混合模式
                        options.ResponseType = OpenIdConnectResponseType.CodeIdToken;
                        options.ResponseMode = OpenIdConnectResponseMode.FormPost;
    
                        options.SaveTokens = true;
                        //开启token时间的校验
                        options.Scope.Add(OpenIdConnectScope.OfflineAccess);
                        options.TokenValidationParameters.ClockSkew = TimeSpan.FromMinutes(1);
                        options.TokenValidationParameters.RequireExpirationTime = true;
    
                    });
                }
    View Code

    特别注意:要关闭pkce的验证,否则会报错 code challenge required. 代码:RequirePkce = false

    !

    • 作       者 : Yaopengfei(姚鹏飞)
    • 博客地址 : http://www.cnblogs.com/yaopengfei/
    • 声     明1 : 如有错误,欢迎讨论,请勿谩骂^_^。
    • 声     明2 : 原创博客请在转载时保留原文链接或在文章开头加上本人博客地址,否则保留追究法律责任的权利。
     
  • 相关阅读:
    程序员转型架构师,推荐你读这几本书
    Dubbo服务发现源码解析
    高可用架构之限流降级
    为什么Kafka速度那么快
    从分布式一致性到共识机制(三)拜占庭问题
    从分布式一致性到共识机制(二)Raft算法
    三分钟看完京东区块链白皮书
    轻松理解零知识证明
    三大去中心化交易协议对比
    从分布式一致性到共识机制(一)Paxos算法
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/13220349.html
Copyright © 2011-2022 走看看