我正在使用JWT承载认证,配置如下。
我的问题是中间件在令牌验证之前正在执行 如何配置中间件以后运行?
services.AddAuthentication()
.AddCookie(_ => _.SlidingExpiration = true)
.AddJwtBearer(
_ =>
{
_.Events = new JwtBearerEvents
{
// THIS CODE EXECUTES AFTER THE MIDDLEWARE????
OnTokenValidated = context =>
{
context.Principal = new ClaimsPrincipal(
new ClaimsIdentity(context.Principal.Claims, "local"));
return Task.CompletedTask;
}
};
_.RequireHttpsMetadata = false;
_.SaveToken = false;
_.TokenValidationParameters = new TokenValidationParameters()
{
ValidIssuer = this.Configuration["Tokens:Issuer"],
ValidAudience = this.Configuration["Tokens:Issuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(this.Configuration["Tokens:Key"])),
};
});
我正在尝试将中间件添加到访问当前用户的管道中。不幸的是,此代码在验证令牌之前执行 。如何让它在之后执行?
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseStaticFiles();
app.UseIdentityServer();
app.UseAuthentication();
app.Use(async (httpContext, next) =>
{
// THIS CODE EXECUTES BEFORE THE TOKEN IS VALIDATED IN OnTokenValidated.
var userName = httpContext.User.Identity.IsAuthenticated
? httpContext.User.GetClaim("email")
: "(unknown)";
LogContext.PushProperty("ActiveUser", !string.IsNullOrWhiteSpace(userName) ? userName : "(unknown)");
await next.Invoke();
});
答案 0 :(得分:8)
看起来你已经找到了解决问题的好方法,但我想我会添加一个答案来解释你所看到的行为。
由于您注册了多个身份验证方案,并且没有一个是默认方案,因此当请求通过管道时,身份验证不会自动发生。这就是HttpContext.User
在通过您的自定义中间件时为空/未经身份验证的原因。在这种“被动”模式中,在请求之前不会调用认证方案。在您的示例中,当请求通过您的AuthorizeFilter
时会发生这种情况。这会触发JWT身份验证处理程序,该处理程序验证令牌,验证身份并设置身份等。这就是为什么(as in your other question)User
在到达控制器操作时正确填充的原因。
对于您的场景可能没有意义(因为您同时使用了cookie和jwt)...但是,如果您确实希望自动进行Jwt身份验证,请为其他中间件设置HttpContext.User
在管道中,您只需要在配置身份验证时将其注册为默认方案:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
答案 1 :(得分:3)
基于@ leppie的评论,这是一个有效的解决方案。
public class ActiveUserFilter : IAsyncActionFilter
{
public async Task OnActionExecutionAsync(
ActionExecutingContext context,
ActionExecutionDelegate next)
{
var userName = context.HttpContext.User.Identity.IsAuthenticated
? context.HttpContext.User.GetClaim("email")
: "(unknown)";
using (LogContext.PushProperty("ActiveUser", !string.IsNullOrWhiteSpace(userName) ? userName : "(unknown)"))
await next();
}
}
插入如下......
services.AddMvc(
_ =>
{
_.Filters.Add(
new AuthorizeFilter(
new AuthorizationPolicyBuilder(
JwtBearerDefaults.AuthenticationScheme,
IdentityConstants.ApplicationScheme)
.RequireAuthenticatedUser()
.Build()));
_.Filters.Add(new ActiveUserFilter());
...