IdentityServer用户名密码模式

前言

用户名密码模式相较于客户端凭证模式,多了用户。通过用户的用户名和密码向Identity Server申请访问令牌。密码模式有两种实现方式.
1.把用户写进内存Identity从中读取账号密码验证
AddInMemoryUsers(config.GetUsers())

2.通过实现 IResourceOwnerPasswordValidator 接口来验证用户
AddResourceOwnerValidator(ResourcePasswordValidator)

第二种更加实用灵活,这篇笔记也是实现的第二种。

20191223142903.png

实现用户名密码授权

我们在之前的搭建好的Identity服务上新增一个名为 ResourcePasswordValidator 的类继承 IResourceOwnerPasswordValidator 重写ValidateAsync 方法来验证用户名和密码

using System.Security.Claims;
using System.Threading.Tasks;
using IdentityModel;
using IdentityServer4.Models;
using IdentityServer4.Validation;

namespace IdentityServer
{
    public class ResourcePasswordValidator: IResourceOwnerPasswordValidator
    {
        public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
        {
            //判断账号密码是否正确。
            if (context.UserName == "userName" && context.Password == "1234567")
            {
                context.Result = new GrantValidationResult(
                 subject: "userInfo",
                    authenticationMethod: OidcConstants.AuthenticationMethods.Password,
                    claims: GetUserClaims());
            }
            else
            {
                //验证失败
                context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "invalid custom credential");
            }
        }

        //可以根据需要设置相应的Claim/需要实现IProfileService接口
        private Claim[] GetUserClaims()
        {

            return new Claim[]
            {
            new Claim("userId","110"),
            new Claim(JwtClaimTypes.Name,"林辉"),
            new Claim(JwtClaimTypes.Role,"菜鸡")
            };
        }
    }
}

Config.cs 中新增一个客户端

new Client
{
    ClientId = "client_b",
    AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,
    //AccessToken过期时间(秒),默认为3600秒/1小时
    AccessTokenLifetime=3600,

    //RefreshToken的最长生命周期
    //AbsoluteRefreshTokenLifetime = 2592000,

    //RefreshToken生命周期以秒为单位。默认为1296000秒
    SlidingRefreshTokenLifetime = 2592000,//以秒为单位滑动刷新令牌的生命周期。

    //刷新令牌时,将刷新RefreshToken的生命周期。RefreshToken的总生命周期不会超过AbsoluteRefreshTokenLifetime。
    RefreshTokenExpiration = TokenExpiration.Sliding,

    //AllowOfflineAccess 允许使用刷新令牌的方式来获取新的令牌
    AllowOfflineAccess = true,
    ClientSecrets =
    {
        new Secret("secret".Sha256())
    },
    AllowedScopes = { "Api"}
}

新建一个 ProfileService 来实现 IProfileService 接口来扩展自定义Claim

using System;
using System.Linq;
using System.Threading.Tasks;
using IdentityServer4.Models;
using IdentityServer4.Services;

namespace IdentityServer
{
    public class ProfileService : IProfileService
    {
        public async Task GetProfileDataAsync(ProfileDataRequestContext context)
        {
            try
            {
                //depending on the scope accessing the user data.
                var claims = context.Subject.Claims.ToList();

                //set issued claims to return
                context.IssuedClaims = claims.ToList();
            }
            catch (Exception ex)
            {
                //log your error
            }
        }

        public async Task IsActiveAsync(IsActiveContext context)
        {
            context.IsActive = true;
        }
    }
}


修改 Startup

//注入DI
services.AddIdentityServer()
    .AddDeveloperSigningCredential()
    .AddInMemoryIdentityResources(Config.GetIdentityResourceResources())
    .AddInMemoryApiResources(Config.GetApiResources())//Api资源信息
    .AddInMemoryClients(Config.GetClients())//客户端信息
    .AddResourceOwnerValidator<ResourcePasswordValidator>()//用户验证
    .AddProfileService<ProfileService>();//扩展claims

测试效果

通过用户名密码申请令牌

20191223155822.png

当access_token过期的时候通过refresh_token来刷新access_token,refresh_token只能使用一次,每次刷新后会返给信的refresh_token和access_token

20191223172456.png

我们通过jwt.io解析出来。可以发现jwt里面包含了我们添加的身份信息,这些信息可以直接在资源服务器中获取使用

20191223160011.png

修改资源服务器

我们在Api中可以通过 User.Claims.FirstOrDefault(m => m.Type == "userId").value; 获取我们用户身份信息。

[HttpGet("userInfo")]
[Authorize]
public ActionResult UserIno()
{
    return new JsonResult($"用户id{User.Claims.FirstOrDefault(m => m.Type == "userId").Value }" );
}

20191223160044.png

posted @ 2019-12-23 17:35  她微笑的脸  阅读(2086)  评论(5编辑  收藏  举报