zoukankan      html  css  js  c++  java
  • asp.net core 使用identityServer4的密码模式来进行身份认证(一)

    IdentityServer4是ASP.NET Core的一个包含OpenID和OAuth 2.0协议的框架。具体Oauth 2.0和openId请百度。

    前言本博文适用于前后端分离或者为移动产品来后端api的身份认证功能。

    一 首先第一步使用Nuge包管理器下载IdentityServer4的包。

    第二部,添加一个名叫Config的类。

    这个类的作用是对一些api和client进行配置的。

      public static IEnumerable<IdentityResource> GetIdentityResource()
            {
                return new List<IdentityResource>
                 {
                     new IdentityResources.OpenId(),
                     new IdentityResources.Profile(),
                     new IdentityResources.Email()
                 };
            }
            public static IEnumerable<ApiResource> GetApiResource()
            {
                return new List<ApiResource>
                {
                    new ApiResource("gateway_api","gateway service"),
    
                    new ApiResource("user_api","user_api service"),
                    //并且要把contactapi加入到apiResource,并加入到 client的allowedScopes中 
                   // new ApiResource("contact_api","contact_api service")
                };
            }
            public static IEnumerable<Client> GetClients()
            {
                return new List<Client>()
              {
                  new Client
                  {
                        ClientId="pc",
                        AllowedGrantTypes = GrantTypes.ResourceOwnerPassword, //这里是指定授权的模式,选择密码模式,
                        ClientSecrets = { new Secret("yemobai".Sha256()) },
                         RefreshTokenUsage=TokenUsage.ReUse,
                         AlwaysIncludeUserClaimsInIdToken = true,
                         AllowOfflineAccess = true,
                        AllowedScopes=new List<string>
                        {
                            "user_api",
                        IdentityServerConstants.StandardScopes.Profile,
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.OfflineAccess
                        }
    
                  }
              };
            }

    第三步 添加start up的配置

      services.AddIdentityServer()
                     .AddDeveloperSigningCredential()
                    .AddInMemoryApiResources(Config.GetApiResource())
                    .AddInMemoryIdentityResources(Config.GetIdentityResource())
                    .AddInMemoryClients(Config.GetClients())
                    .AddResourceOwnerValidator<ResourceOwnerPasswordValidator>()
                    .AddProfileService<ProfileService>()
                    .AddCorsPolicyService<CorsPolicyService>() //这是IdentityServer跨域的,我尝试开启asp.net core 的跨域,但是identityServer不接受请求。
                    ;
     public void Configure(IApplicationBuilder app, IHostingEnvironment env,ILoggerFactory loggerFactory)
            {
                if (env.IsDevelopment())
                {
                    app.UseDeveloperExceptionPage();
                }
                loggerFactory.AddConsole(Configuration.GetSection("Logging"));
                loggerFactory.AddDebug();
                app.UseIdentityServer(); //启用identityServer中间件
                app.UseCors(buider =>
                {
                    buider.WithOrigins("http://localhost:8080")
                    .AllowAnyHeader();
                });
                app.UseMvc();
            }

    第四步 用户验证

    其实identityServier4也提供了一些测试用户来进行身份认证的实验,这些东西都在identityServer4的官网上都有介绍。

    新建一个类ResourceOwnerPasswordValidator继承与IResourceOwnerPasswordValidator接口(IResourceOwnerPasswordValidator是Identityserver4提供的一个接口其主要工作就是验证我们的用户名和密码)。

    这个接口只有一个方法

       public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)

    怎么获取我们传过来的用户名和密码呢?

    答:在方法的参数context中,按F12进入到ResourceOwnerPasswordValidationContext这个类的定义中,具体定义的属性如下

        //
        // 摘要:
        //     Class describing the resource owner password validation context
        public class ResourceOwnerPasswordValidationContext
        {
            public ResourceOwnerPasswordValidationContext();
    
            //
            // 摘要:
            //     Gets or sets the name of the user.
            public string UserName { get; set; }
            //
            // 摘要:
            //     Gets or sets the password.
            public string Password { get; set; }
            //
            // 摘要:
            //     Gets or sets the request.
            public ValidatedTokenRequest Request { get; set; }
            //
            // 摘要:
            //     Gets or sets the result.
            public GrantValidationResult Result { get; set; }
        }

    可以看到 userName和passWord都已经定义好了,我们只管用就行了。

    context.UserName, context.Password

    就算用户名和密码和我的数据库的数据对上了,该怎么返回我对用户名和密码的认证结果呢?

    答:

    如果你是一个细心的人,你会发现上面 ValidateAsync这个方法返回一个Task,可以基本上认为无返回值了。不要着急,看看ResourceOwnerPasswordValidationContext这个类的定义。

    GrantValidationResult Result { get; set; }

    里面有这么一个属性。看名字都知道是验证结果了。不出意外,我们对用户名和密码的验证接口应该放在这个里面。

    那下面就很简单了。

     if (accountResult.Status=="登陆成功")
                {
                    context.Result= new GrantValidationResult(accountResult.User.Id.ToString(), "admin", GetUserClaim(accountResult.User));
                }
               
                else
                {
                    //验证失败
                    context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "密码错误");
                }

    具体的构造函数重载,请自己看。如果有需求的不要忘了,把claim给加上。怎么 加claim呢,

    最简单的方式你数据库验证用户名和密码完后,把一些claim给带上。

    向我这样

     public Claim[] GetUserClaim(UserInfo userInfo)
            {
                
                var claims = new Claim[] { new Claim("USERID", userInfo.UserId), new Claim("USERNAME", userInfo.UserName) };
                return claims;
            }

    完整代码

     public class ResourceOwnerPasswordValidator: IResourceOwnerPasswordValidator
        {
             private readonly IAccountService accountService;
             public ResourceOwnerPasswordValidator(IAccountService _accountService)
            {
                accountService = _accountService;
            }
            public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
            {
                var accountResult = await accountService.SignInAsync(context.UserName, context.Password);
                if (accountResult.Status=="登陆成功")
                {
                    context.Result= new GrantValidationResult(accountResult.User.Id.ToString(), "admin", GetUserClaim(accountResult.User));
                }
               
                else
                {
                    //验证失败
                    context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "密码错误");
                }
            }
            public Claim[] GetUserClaim(UserInfo userInfo)
            {
                
                var claims = new Claim[] { new Claim("USERID", userInfo.UserId), new Claim("USERNAME", userInfo.UserName) };
                return claims;
            }

    测试结果。

    是用postmen来进行测试。没有的话请自行下载。

    忘了说了,把IdentityServer4的包下载下来后 ,运行项目浏览器输入http://localhost:5000/.well-known/openid-configuration  

    看看identiyServer4一些接口地址。

    然后在在postMen中输入一下Key和value(不要把我的给抄了上去)

    scope写不写无所谓,如果你写的了话必须在config类中

       public static IEnumerable<ApiResource> GetApiResource()
            {
                return new List<ApiResource>
                {
                    new ApiResource("gateway_api","gateway service"),
    
                    new ApiResource("user_api","user_api service"),
                    //并且要把contactapi加入到apiResource,并加入到 client的allowedScopes中 
                   // new ApiResource("contact_api","contact_api service")
                };
            }

    在这个方法中添加上。而且也要在

      public static IEnumerable<Client> GetClients()
            {
                return new List<Client>()
              {
                  new Client
                  {
                        ClientId="pc",
                        AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
                        ClientSecrets = { new Secret("yemobai".Sha256()) },
                         RefreshTokenUsage=TokenUsage.ReUse,
                         AlwaysIncludeUserClaimsInIdToken = true,
                         AllowOfflineAccess = true,
                        AllowedScopes=new List<string>
                        {
                            "user_api",
                        IdentityServerConstants.StandardScopes.Profile,
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.OfflineAccess
                        }
    
                  }
              };

    而且也要在 AllowedScopes里面给加上。

    结果

     这个时候我们就拿到了access_token和过期时间和refresh_token,

    就用了IdentityServer4搞了一个access_token出来。算什么身份认证?

    答:下一节解释。

  • 相关阅读:
    thrift 依赖的库
    环球雅思名师公益大讲堂课表2.182.23 雅思资讯 环球雅思
    经验分享band 7.5已经工作的人如何准备雅思考试学习心得雅思频道|太傻网考试频道|常识 辅导 技巧 机经 名师 访谈 交流 资料 试题库
    Chapter 14. Boost.PropertyTree
    少讨论概念,少争论特征、少议论模型;多写代码、多做测试、多做应用。
    澳洲技术移民申请流程
    neo4j——图数据库初探 JDream314的专栏 博客频道 CSDN.NET
    Australia Immigration Network
    boost::property_tree
    海外澳洲技术移民花费一览表(2006年11月完整版) Topboy 博客园
  • 原文地址:https://www.cnblogs.com/wscar/p/9404797.html
Copyright © 2011-2022 走看看