.Net Core 使用identity實現Token登錄功能


參考鏈接

todo,需要完成的實體去完善這個文檔
如何根據現有的數據庫以及實體區配置呢

  • 我們需要接入已有用戶體系,只需實現IProfileService和IResourceOwnerPasswordValidator接口即可,並且在Startup配置Service時不再需要AddTestUsers,因為將使用我們自己的用戶信息。

我這邊逐步說明需要配置的哪些玩意

1.IResourceOwnerPasswordValidator 接口

在demo示例里面,我將臨時用戶的更改為數據庫查詢接口,這個最好后期改成實體,有注入風險

	/// <summary>
		/// 驗證
		/// </summary>
		/// <param name="context"></param>
		/// <returns></returns>
		public Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
		{
            //此處使用context.UserName, context.Password 用戶名和密碼來與數據庫的數據做校驗
            //if (_users.ValidateCredentials(context.UserName, context.Password))
            if (LoginCheck(context.UserName, context.Password)) //臨時測試
            {

				var user = _users.FindByUsername(context.UserName);

                //驗證通過返回結果 
                //subjectId 為用戶唯一標識 一般為用戶id
                //authenticationMethod 描述自定義授權類型的認證方法 
                //authTime 授權時間
                //claims 需要返回的用戶身份信息單元 此處應該根據我們從數據庫讀取到的用戶信息 添加Claims 如果是從數據庫中讀取角色信息,那么我們應該在此處添加

                string str = @"select Password,* from Base_User 
where code='" + context.UserName + "'";
                DataTable dt = new DataTable();
                dt = RunSql(str);
                
                //自定義了一個地址,需要在config設置才可以得到
                var Claims = new List<Claim>() { new Claim("自定義信息", dt.Rows[0]["Name"].ToString()) };
                context.Result = new GrantValidationResult(
                    dt.Rows[0]["ID"].ToString(),
                    OidcConstants.AuthenticationMethods.Password, _clock.UtcNow.UtcDateTime,
                    Claims);

                //context.Result = new GrantValidationResult(
                //    user.SubjectId ?? throw new ArgumentException("Subject ID not set", nameof(user.SubjectId)),
                //    OidcConstants.AuthenticationMethods.Password, _clock.UtcNow.UtcDateTime,
                //    user.Claims);
            }
			else
			{
				//驗證失敗
				context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "invalid custom credential");
			}
			return Task.CompletedTask;
		}

        /// <summary>
        /// 這邊只是簡單的測試使用數據庫
        /// </summary>
        /// <param name="code"></param>
        /// <param name="pwd"></param>
        /// <returns></returns>
        public static bool LoginCheck(string code,string pwd)
        {
            string str = @"select Password,* from Base_User 
where code='"+code+"'";
            DataTable dt = new DataTable();
            dt = RunSql(str);
            if (dt.Rows.Count > 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public static DataTable RunSql(string sqlStr)
        {
            using (SqlConnection sqlConnection1 = new SqlConnection("Data Source=ALEX;Initial Catalog=RiBaoOA;User ID=sa;Password=123456;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"))
            {
                using (SqlDataAdapter sqlDataAdapter1 = new SqlDataAdapter(sqlStr, sqlConnection1))
                {
                    DataTable DT = new DataTable();
                    sqlDataAdapter1.Fill(DT);
                    return DT;
                }
            }

        }

2.IProfileService

在這個里面,我重新賦值 Claims,主要就是為了測試自定義聲明

public class CustomProfileService: IProfileService
	{
		/// <summary>
		/// The logger
		/// </summary>
		protected readonly ILogger Logger;

		/// <summary>
		/// The users
		/// </summary>
		protected readonly TestUserStore Users;

		/// <summary>
		/// Initializes a new instance of the <see cref="TestUserProfileService"/> class.
		/// </summary>
		/// <param name="users">The users.</param>
		/// <param name="logger">The logger.</param>
		public CustomProfileService(TestUserStore users, ILogger<TestUserProfileService> logger)
		{
			Users = users;
			Logger = logger;
		}

		/// <summary>
		/// 只要有關用戶的身份信息單元被請求(例如在令牌創建期間或通過用戶信息終點),就會調用此方法
		/// </summary>
		/// <param name="context">The context.</param>
		/// <returns></returns>
		public virtual Task GetProfileDataAsync(ProfileDataRequestContext context)
		{
			context.LogProfileRequest(Logger);

			//判斷是否有請求Claim信息
			if (context.RequestedClaimTypes.Any())
			{
                ////根據用戶唯一標識查找用戶信息
                //var user = Users.FindBySubjectId(context.Subject.GetSubjectId());
                //if (user != null)
                //{
                //	//調用此方法以后內部會進行過濾,只將用戶請求的Claim加入到 context.IssuedClaims 集合中 這樣我們的請求方便能正常獲取到所需Claim

                //	context.AddRequestedClaims(user.Claims);
                //}
                var Claims = new List<Claim>() { new Claim("自定義信息", "名稱") };
                context.AddRequestedClaims(Claims);
            }

			context.LogIssuedClaims(Logger);

			return Task.CompletedTask;
		}

		/// <summary>
		/// 驗證用戶是否有效 例如:token創建或者驗證
		/// </summary>
		/// <param name="context">The context.</param>
		/// <returns></returns>
		public virtual Task IsActiveAsync(IsActiveContext context)
		{
			Logger.LogDebug("IsActive called from: {caller}", context.Caller);

			var user = Users.FindBySubjectId(context.Subject.GetSubjectId());
			//context.IsActive = user?.IsActive == true;
            context.IsActive = true;
            return Task.CompletedTask;
		}
	}

3.Identity4中需要在 配置文件中增加claim

public static IEnumerable<ApiResource> GetApiResources()
        {
            return new List<ApiResource>
            {
//                new ApiResource("api1", "My API")
                new ApiResource("api1", "My API",new List<string>(){"自定義信息"})
            };
        }

4.帶上token請求API接口,通過HttpContext.User.Claims 可以得到你想要的數據

其中 sub 就是用戶的唯一標識,這個可以看着后期如何優化。

5.postman測試

請求token

post地址:http://localhost:46270/connect/token
參數:
grant_type  password
client_id   ro.client
client_secret   secret
username    用戶名
password    密碼
scope   api1

返回如下:
{
    "access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6IjAxOGZlZmIyYmVmN2IxNTY2NzhmMDZkYTRiNGY4NTgzIiwidHlwIjoiSldUIn0.eyJuYmYiOjE1ODY2ODQ0ODksImV4cCI6MTU4NjY4ODA4OSwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo0NjI3MCIsImF1ZCI6WyJodHRwOi8vbG9jYWxob3N0OjQ2MjcwL3Jlc291cmNlcyIsImFwaTEiXSwiY2xpZW50X2lkIjoicm8uY2xpZW50Iiwic3ViIjoiODQiLCJhdXRoX3RpbWUiOjE1ODY2ODQ0ODcsImlkcCI6ImxvY2FsIiwi6Ieq5a6a5LmJ5L-h5oGvIjoi5ZCN56ewIiwic2NvcGUiOlsiYXBpMSJdLCJhbXIiOlsicHdkIl19.2_O07JwtOpD2cq8PFxu9tBU6rpSOw_XI0LrfF7QYivNylyeeb7kvNsEElzVtW2ulx6kjLCDF6tgskrjkFp3JhZ8H3hPiJXDxlwJ-an7D2k5lw1Bcool7WiD9q8IkobEFx-Zg6PAUocr-BCr9yEldkA41pPLtfuf3oZwkS2333AcYnixRNJbX3hHVA21cXSMuj-5rDp899uNeOUrvhrAqSD_eS-dQrdCfa00EwSfDyd6ruFnH3IT0AD0TvBDHjzYyl7VNdUpX1yHnjSKr60oahVtuMi_sy8HGFIgsn1_kKNaYayaiFGsiI7cG_L7FJZ2AksNVW4r1_cEyP1xNaxD-Ag",
    "expires_in": 3600,
    "token_type": "Bearer"
}

帶上token請求解析。這個暫時沒看懂

post地址:http://localhost:46270/connect/userinfo

帶上token請求api.

http://localhost:46269/identity/


免責聲明!

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



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