咨询区
Felipe Deveza:
我自己实现了一个 basic 验证,现在我的做法是在每一个 Action 中都提取 Request.Headers["Authorization"]
进行权限验证。
[HttpGet]
public IActionResult Get()
{string token = Request.Headers["Authorization"];// Validate token.
}[HttpPost]
public IActionResult Post(int id)
{string token = Request.Headers["Authorization"];// Validate token.
}
请问我是否可以在某一个集中地方做 Request.Headers["Authorization"]
的全局验证呢?
回答区
miechooy:
你可以通过自定义中间件的方式对 header
进行统一验证,然后决定是否传给后端的的 Controller。
中间件的逻辑大概如下:
public class YourMidllewareClass{public async Task Invoke(HttpContext context){string token = context.Request.Headers["Authorization"];//do the checkingif (token == null){context.Response.StatusCode = 401;await context.Response.WriteAsync("Access denied!");return;}//pass request further if correctawait _next(context);}}
有了中间件之后,接下来通过 IApplicationBuilder 将其注入到Http请求管道中,参考如下代码:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, IConnectionManager conn, ILoggerFactory loggerFactory)
{app.UseMiddleware<YourMidllewareClass>();
}
Matheus Lacerda:
在 ASP.NET Core 中,你可以使用内置的 AuthenticationHandler 类,详细文档请参考:https://docs.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/identity-2x 。
刚好我的项目中有一个自定义验证
功能。
Startup.ConfigureServices:
services.AddAuthentication(options =>{options.DefaultAuthenticateScheme = "Custom Scheme";options.DefaultChallengeScheme = "Custom Scheme";}).AddCustomAuth(o => { });
Startup.Configure:
app.UseAuthentication();
finally
internal class CustomAuthenticationHandler : AuthenticationHandler<CustomAuthenticationOptions>
{public CustomAuthenticationHandler(IOptionsMonitor<CustomAuthenticationOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock){}protected override async Task<AuthenticateResult> HandleAuthenticateAsync(){try{// Your auth code here// Followed by something like this:return AuthenticateResult.Success(new AuthenticationTicket(new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>() { new Claim(ClaimTypes.Sid, Id.ToString()) },Scheme.Name)),Scheme.Name));} catch{return AuthenticateResult.Fail("Error message.");}}
}
这样配置之后,所有对Controller的请求都会先经过 authentication ,如果某些 Controller 有特殊需求,可以使用 [AllowAnonymous]
忽略它。
点评区
说实话在.netcore 时代实现这种统一验证的需求不要太简单了,中间件这块也是大家必须理解的基础知识。