如何在不查找 AspNetUserRoles 表的情況下在 WebAPI 方法中獲取使用者角色?
我有一個更新狀態的儲存過程。根據使用者的角色,儲存過程的程式碼可能允許也可能不允許狀態更改。出於這個原因,我需要將角色名稱傳遞給儲存過程。我的角色名稱儲存在我的 javascript 程式碼中的客戶端上,但我當然需要對伺服器進行第二次檢查。每個使用者只有三個角色之一,當請求更新狀態時,我可以根據客戶端的角色呼叫三種方法之一。這是我嘗試過的。
我正在使用**基於承載令牌的身份驗證和 ASP.NET Identity 2.1 的 WebApi,**並且該應用程序始終在瀏覽器中執行。我的使用者已經設置了適當的角色。
我放置了一些程式碼來獲取 userId,然後轉到 AspNetUserRoles 表以獲取方法開始時的角色。但是我注意到這需要大約 500 毫秒才能執行。作為替代方案,我正在考慮以下內容:
[HttpPut] [Authorize(Roles = "Admin")] [Route("AdminUpdateStatus/{userTestId:int}/{userTestStatusId:int}")] public async Task<IHttpActionResult> AdminUpdateStatus(int userTestId, int userTestStatusId) { return await UpdateStatusMethod(userTestId, userTestStatusId, "Admin"); } [HttpPut] [Authorize(Roles = "Student")] [Route("StudentUpdateStatus/{userTestId:int}/{userTestStatusId:int}")] public async Task<IHttpActionResult> StudentUpdateStatus(int userTestId, int userTestStatusId) { return await UpdateStatusMethod(userTestId, userTestStatusId, "Student"); } [HttpPut] [Authorize(Roles = "Teacher")] [Route("TeacherUpdateStatus/{userTestId:int}/{userTestStatusId:int}")] public async Task<IHttpActionResult> TeacherUpdateStatus(int userTestId, int userTestStatusId) { return await UpdateStatusMethod(userTestId, userTestStatusId, "Teacher"); } private async Task<IHttpActionResult> UpdateStatusMethod(int userTestId, int userTestStatusId, string roleName) { // Call the stored procedure here and pass in the roleName }這是一種有效的方法,還是可能有另一種更乾淨的方法。我不太清楚的是前端或後端是否記憶體了使用者角色。我假設這已經完成,或者有一些設置允許這樣做。
注意我在這裡使用聲明將角色資訊發送給我的客戶:
public static AuthenticationProperties CreateProperties( string userName, ClaimsIdentity oAuthIdentity, string firstName, string lastName, int organization) { IDictionary<string, string> data = new Dictionary<string, string> { { "userName", userName}, { "firstName", firstName}, { "lastName", lastName}, { "organization", organization.ToString()}, { "roles",string.Join(":",oAuthIdentity.Claims.Where(c=> c.Type == ClaimTypes.Role).Select(c => c.Value).ToArray())} }; return new AuthenticationProperties(data); }但是,我的問題與伺服器有關,以及如果使用者處於特定角色而不訪問數據庫,我如何檢查我的方法。也許有一種方法可以通過聲明安全地做到這一點,但我不知道該怎麼做。
任何幫助和建議將不勝感激。
正如您所說,您正在使用不記名令牌來保護您的端點。我相信對於那些不記名令牌神奇字元串裡麵包含的內容幾乎沒有誤解。那麼這些令牌包含您為其頒發令牌的使用者的所有角色,以及如果您在 Web API 中使用預設數據保護 DPAPI 而不是(JWT 令牌),那麼這些令牌將被簽名和加密,因此沒有人可以篡改數據在令牌裡面,除非他有 mashineKey 為 web 伺服器發布這個令牌,所以不用擔心數據保護。
我的建議是從數據庫中讀取使用者的角色/聲明,不需要您嘗試做的這種變通方法和黑客攻擊,您需要做的就是在使用者登錄時為使用者設置聲明
GrantResourceOwnerCredentials您可以通過獲取使用者然後從數據庫中讀取角色並將它們設置為“角色”類型的聲明來設置它var identity = new ClaimsIdentity(context.Options.AuthenticationType); identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName)); identity.AddClaim(new Claim(ClaimTypes.Role, "Admin")); identity.AddClaim(new Claim(ClaimTypes.Role, "Supervisor"));請記住,這僅在使用者登錄時發生一次,然後您將收到一個不記名簽名和加密的令牌,其中包含該使用者的所有聲明,無需任何數據庫訪問來驗證它。
或者,如果您想從數據庫創建身份,您可以使用以下內容:
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager, string authenticationType) { // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType var userIdentity = await manager.CreateIdentityAsync(this, authenticationType); // Add custom user claims here return userIdentity; }然後
GrantResourceOwnerCredentials執行以下操作:ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager, OAuthDefaults.AuthenticationType);現在,一旦您將不記名令牌發送到具有屬性的受保護端點,
Authorize例如[Authorize(Roles = "Teacher")]我可以向您保證,您的程式碼不會去數據庫進行任何查詢,打開 SQL 探查器並檢查它是否會從加密令牌中讀取聲明以及角色聲明並檢查此使用者是否屬於教師角色並允許或拒絕請求。我已經在部落格中詳細介紹了 5 篇關於基於令牌的身份驗證以及授權伺服器和JWT 令牌的文章。我建議您閱讀這些文章,以更好地理解不記名令牌。