【发布时间】:2021-01-25 01:01:52
【问题描述】:
我正在 .NET Core 3.1 中使用 Identity 和 JWT 身份验证。我将来会添加 Open Id。我现在面临的问题是我对身份验证管道的控制太少了。管道会为您做出一些决定,例如何时重定向到登录。例如,对于身份验证,当您发出 401 状态时,它会尝试重定向到 /login - 即使您在 cookie 配置中指定了不同的页面。令人惊讶的是,JWT auth 也有同样的问题 - 即使提供的唯一策略是 Bearer 策略并且控制器被标记为 ApiController 属性。
[Authorize(AuthenticationSchemes = Schemes.Bearer)]
我想要完全控制管道和响应。通过尽可能多地利用内置工具来实现这一目标的最佳方法是什么?我不想编写自己的 JWT 验证代码,而是使用我配置的验证。
这就是我配置 JWT 的方式。 OnAuthenticationFailed。手动设置标头的回调永远不会运行。
//piranha
services.AddPiranha(options =>
{
options.UseFileStorage(naming: Piranha.Local.FileStorageNaming.UniqueFolderNames);
options.UseImageSharp();
options.UseManager();
options.UseTinyMCE();
options.UseMemoryCache();
options.UseEF<SQLiteDb>(db =>
db.UseSqlite("Filename=./Data/emurse-piranha.db"));
options.UseIdentityWithSeed<IdentitySQLiteDb>(db =>
db.UseSqlite("Filename=./Data/emurse-piranha.db"),
identityOptions =>
{
// Password settings
identityOptions.Password.RequireDigit = false;
identityOptions.Password.RequiredLength = 6;
identityOptions.Password.RequireNonAlphanumeric = false;
identityOptions.Password.RequireUppercase = false;
identityOptions.Password.RequireLowercase = false;
identityOptions.Password.RequiredUniqueChars = 1;
// Lockout settings
identityOptions.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
identityOptions.Lockout.MaxFailedAccessAttempts = 10;
identityOptions.Lockout.AllowedForNewUsers = true;
// User settings
identityOptions.User.RequireUniqueEmail = true;
},
cookieOptions =>
{
cookieOptions.Cookie.HttpOnly = true;
cookieOptions.ExpireTimeSpan = TimeSpan.FromMinutes(30);
cookieOptions.LoginPath = "/manager/login";
cookieOptions.AccessDeniedPath = "/manager/login";
cookieOptions.SlidingExpiration = true;
var defaultAction = cookieOptions.Events.OnRedirectToLogin;
cookieOptions.Events.OnRedirectToLogin = (context) =>
{
if (context.Request.Path.Value.StartsWith("/api"))
{
response.StatusCode = 401;
response.BodyWriter.WriteAsync(new ReadOnlyMemory<byte>
(Encoding.ASCII.GetBytes("unauthorized.")));
return Task.CompletedTask;
}
else
{
return defaultAction(context);
}
};
});
//turn off for prod
options.AddRazorRuntimeCompilation=true;
});
//JWT
services.AddAuthentication(Schemes.Bearer)
.AddApplicationJwt(Configuration);
public static AuthenticationBuilder AddApplicationJwt(this AuthenticationBuilder builder, IConfiguration config)
{
builder.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
{
var issuer = config["Jwt:Issuer"];
var key = config["Jwt:Key"];
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = issuer,
ValidAudience = issuer,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key))
};
//Never executes
options.Events= new JwtBearerEvents()
{
OnAuthenticationFailed = ((context) => {
response.StatusCode = 401;
response.BodyWriter.WriteAsync(new ReadOnlyMemory<byte>
(Encoding.ASCII.GetBytes("unauthorized.")));
return Task.CompletedTask;
}),
};
});
return;
}
然后使用大多数默认选项配置应用程序:
app.UseAuthorization();
app.UsePiranha(options =>
{
options.UseTinyMCE();
//default Auth middleware
options.UseIdentity();
app.UseCors(x => x
.AllowAnyMethod()
.AllowAnyHeader()
.SetIsOriginAllowed(origin => true) //TODO: remove for production
.AllowCredentials());
//use Piranha manager
options.UseManager();
});
【问题讨论】:
-
什么是
Schemes.Bearer?默认的 jwt 方案是JwtBearerDefaults.AuthenticationScheme。 -
JwtBearerDefaults.AuthenticationScheme 只是一个字符串,Schemes.Bearer 设置为等于 JwtBearerDefaults.AuthenticationScheme ("Bearer")。
-
我认为问题不在于发布的代码。我使用几乎相同的设置没有问题。你能多介绍一下你的身份验证/授权设置吗?
-
@Xerillio 我添加了一些代码,显示 Piranha 设置,这是配置 Auth 的地方。深入研究 .NET Core 和 Identity 源代码,希望我能很快获得更多见解。
标签: authentication .net-core jwt asp.net-identity asp.net-core-3.1