1. 程式人生 > >ASP.NET Core整合現有系統認證

ASP.NET Core整合現有系統認證

我們現在大多數轉向ASP.NET Core來使用開發的團隊,應該都不是從0開始搭建系統,而是老的業務系統已經在執行,ASP.NET Core用來開發新模組。那麼解決使用者認證的問題,成為我們的第一個攔路虎。

if(Session["user"]==null)
{
  Response.redirect("/login.aspx")
}

在ASP.NET Core下,MVC以一個Middleware加入到整個HTTP管道。在此之前還會新增一個Routing的Middleware,注意這裡的意思也就是說 Routing不再和ASP.NET MVC一樣屬於它的一部分。正好相反,在ASP.NET Core裡面是有一個MVCRouteHandler被 Routing Middleware 加載出來處理請求。關於路由這塊我們後面再說。

如果我們要在MVC Middleware執行之請攔截請求只要加一個Middleware在 MVC Middleware或者Routing之前即可。

0?wx_fmt=png

public void Configure(IApplicationBuilder app){
    app.Use(async (context, next) => {   
 if (context.Request.Headers.ContainsKey("token"))    {      
   var token =        context.Request.Headers["token"].FirstOrDefault();      
     if
(token == "jessetalk.cn")        {          await next();        }    }      context.Response.StatusCode = 401;  });      app.UseMvc(); }

上面是我們有簡易的方法實現的一個Middleware,被加到了MVC之前。當Request的Headers中沒有一個值為“jessetalk.cn” 以及 name為” token”的項的時候,我們就返回401狀態,並且不執行後面的處理。(不呼叫 next方法)

定製JWTBearer Authentication

ASP.NET Core為我們實現了JWTBearer Authentication,關於 JWTBearer Authentication的實現可以參考另外一篇文章《在ASP.NET Core中使用JWTBearer Authentication》。我們今天要做的就是通過定製JWTBearer Authentication來達到讓它讀取我們自定義的Token並且用我們自己的方式來校驗這個Token。有點時代倒退的感覺是不是?

如果在時間和人員都足夠的情況下,我們是可能直接整體替換成標準的JWT方案,甚至做到SSO。但是架構是沒有止境的,在一定的時間框架下,要做到高效且安全的切換,這不失為一種好辦法。

首先我們需要看一下在JWTBearer中預設獲取的token是在Authorization的頭裡,Bearer空格加上token。而如果有不規範的做法,可能是直接在headers裡面加了一個token,裡面有一個用我們自己的演算法生成的token。

0?wx_fmt=png

更改token的來源

JWTBearer authentication handler提供的Events中有一個OnMessageReceived委託可以讓我們從另外的地方讀取token。

services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(o => {
    o.Events = new JwtBearerEvents()
    {
        OnMessageReceived = context => {          
 var token = context.Request.Headers["token"];            context.Token = token.FirstOrDefault();      
       return Task.CompletedTask;        },    }; });

定製token的驗證方式

從headers裡面拿到token之後,下一步就是要把它的驗證演算法改成我們自己的。這一步可以通過自定義 ISecurityTokenValidator來實現 。我們在這個Validator裡面,校驗token生成一個ClaimsPrincipal,這個principal就會被賦值到 HttpContext.User上。

同時我們還根據當前的token添加了一個Role Claim,它的值有user和admin。這個可能用來做基於角色的授權 。

public class MyTokenValidator : ISecurityTokenValidator{   
 public ClaimsPrincipal ValidateToken(string securityToken,
TokenValidationParameters validationParameters, out SecurityToken validatedToken
)
   
{        validatedToken = null;      
   var identity = new ClaimsIdentity(JwtBearerDefaults.AuthenticationScheme);        identity.AddClaim(new Claim("name", "jesse"));        identity.AddClaim(new Claim(ClaimsIdentity.DefaultRoleClaimType, securityToken == "jessetalk.cn" ? "admin" : "user"));        var principal = new ClaimsPrincipal(identity);        return principal;    } }

注意ClaimsIdentity的AuthenticationScheme一定要與我們在UseAuthentication時設定的名稱一樣。否則Identity.IsAuthenticated無法正確設定為true,我們的授權就沒有辦法完成。
有了我們自定義的Validator之後,我們要對JwtBearer進行改造,去掉它預設的Validator,加上我們自己定義的這個。

services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(o =>
{

    o.SecurityTokenValidators.Clear();
    o.SecurityTokenValidators.Add(new MyTokenValidator());
});

開始進行授權

為了給大家演示上面的功能,我們新建兩個Controller,一個是Admin,另一個是Home。兩者都需要使用者有token才能正常訪問,但是對於Admin我們需要使用者具有admin的role才可以,否則會被拒絕返回403。

HomeController.cs

[Authorize]public class HomeController : Controller{   
 public IActionResult Index()    {      
   return Ok();    } }

當Headers裡面沒有token 值的時候,API請求返回 401。

0?wx_fmt=png

當Headers裡面有token值時,API可以被正常訪問。

0?wx_fmt=png

我們又加了一個AdminController,不一樣的是這次我們給Authorize加上了Role=”admin”,也就是隻有擁有admin的Role才可以訪問這個API。

[Authorize(Roles ="admin")]
public class AdminController : Controller{  
 public IActionResult Index()    {    
     return Ok();    } }

當我們用user的token訪問時,我們會得到403。

0?wx_fmt=png

只有用admin的token,才能正常訪問。

0?wx_fmt=png

以是就是基於JWT Authentication來定製的我們自己的認證方案的一個基本思路,主要是實現OnMessageReceived來改造token的來源,以及定義自己的 ISecurityTokenValidator 來實現對token的驗證。

原文地址:http://www.jessetalk.cn/2017/11/03/asp-net-core-authentication-with-legacy-system/

.NET社群新聞,深度好文,歡迎訪問公眾號文章彙總 http://www.csharpkit.com

0?wx_fmt=jpeg640?wx_fmt=jpeg