題前話:

隨著移動設備的浪潮,以及前端各種JS mvvm框架的發展,前後端分離地更加徹底。最徹底的是網站Html頁面 完全不需要後端來渲染了,前後臺交互全部依靠json來傳遞數據。那麼問題來了,怎麼判斷用戶是否登錄或者用戶是否有許可權訪問當前所請求的資源?這就是今天的主題,好了,Lets Start...(本文默認讀者熟悉asp.core,以及asp許可權控制的相關知識)

asp.core能夠讓我們自定義Middleware(中間件),首先我們先來看一張官方的圖吧

Middleware可以用來處理每個請求,包括給每個請求加上自定義請求頭,加上跨域響應頭,以及給每個請求加上用戶認證,這是本文實現許可權驗證的基礎。(ps:以前我的一篇跨域的文章,這裡我們同樣可以用中間件來實現,不過這樣就是全局跨域,需要細微控制每個action的話,可以採用Attribute的方式實現。)既然如此我們就來New 一個中間件吧

如圖 vs2015可以快捷地新建一個中間件,會默認生成如下核心代碼

直接貼處理核心代碼吧:

public Task Invoke(HttpContext httpContext)

{

//檢測是否包含Authorization請求頭,如果不包含返回context進行下一個中間件,用於訪問不需要認證的API

if (!httpContext.Request.Headers.ContainsKey("Authorization"))

return _next(httpContext);

else

{

var tokenHeader = httpContext.Request.Headers["Authorization"];

try

{

tokenHeader = tokenHeader.ToString().Substring("Bearer ".Length).Trim();

var result = Config.StoreSignedUser.list.Where(m => m.userToken == tokenHeader).FirstOrDefault();

if (result == null)

return httpContext.Response.WriteAsync("非法請求");

else

{

ClaimsIdentity identity = new ClaimsIdentity(result.userClaims);

ClaimsPrincipal principal = new ClaimsPrincipal(identity);

httpContext.User = principal;//構建authorize認證

return _next(httpContext);

}

}

catch(Exception e)

{

return httpContext.Response.WriteAsync("token值長度不夠");

}

}

直接貼一張流程圖吧,更好理解

(圖略醜,下次還是用viso畫吧,word畫起來蛋疼)

然後許可權驗證處理需要添加這個包:Microsoft.AspNetCore.Authentication.JwtBearer

這個用於生成token。我們在stratup.cs裏配置許可權驗證吧

我們在控制器添加上如下配置

第一個表示用的是admin這個策略,starup.cs裏配置的是admin這個策略需要admin這個claim。而這個claim添加是在中間件處理的

第二個表示用的是test這個策略,starup.cs裏配置的是admin這個策略需要test這個test。

最後我們來看一下怎麼生成token的吧。

登錄的時候需要判斷用戶是否存在,如果存在就生成token,查詢出來user的cliams,最後把用戶名,token值,以及用戶的claims存放在本地。請求Middleware時,判斷請求頭"Authorization"的值是否有效。好吧,讓我們就用postman來驗證一下把。

直接請求返回401狀態碼,沒有授權

做如下請求,用戶名和密碼見源碼

把token拷貝下來,再次請求

返回結果。同樣的token值請求:localhost:50072/api/val

同樣返回401,沒有授權,因為這個api,需要test這個claim聲明,111111這個用戶並沒有test這個聲明,所有授權失敗,而222222這個用戶有這個test這個claim這個聲明。同樣我們用222222來請求一下這個api

返回成功,好了本文到此結束(ps:感覺寫地有點亂,不清楚的可以下載源碼自己運行一下)

後記:

關於用redis來儲存已登錄用戶的用戶名,token值,以及claims的思考,無疑這是最好的解決方案。把已登錄的用戶數據存在數據,而每次請求都請求一次資料庫,伺服器壓力肯定大。用redis就可以解決這個問題,token過期也自然解決了。

最後貼上github地址,歡迎大家提issue,如果覺得本文有幫助,可以star,可以讚賞,謝謝~


推薦閱讀:
相关文章