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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM