在 ASP.NET Core 3.1 中使用多种身份验证方案?
Using multiple authentication schemes in ASP.NET Core 3.1?
我一直在使用 ASP.NET Core 3.1 和干净的架构制作 Web 应用程序。
我有一些 class 库,例如 Infrastructure、Persistence、Domain、Application 和一个名为“Web”的 MVC 应用程序项目作为我的应用程序的启动点。
在 Web 层中,我有一个“区域”,其中有一个管理区域,其中包含一些控制器和 操作方法,return JSON 作为我的 API在基于 React 的应用程序中使用的端点。
我在 Controllers 文件夹中的 Web MVC 项目中也有一些控制器,它们的 action 方法 return html views.
我的 API 端点也使用 Identity 和 JWT,但是:
- 如果我想在我的 MVC 控制器中使用基于声明的身份,他们的操作会导致 return html 次查看怎么办?
- 在此类应用程序中使用 ASP.NET Core 3.1 中基于声明的身份的最佳实践是什么?
如有任何帮助,我们将不胜感激。
经过一些研究,我在一篇标题为“Authorize with a specific scheme in ASP.NET Core”的文章中的 ASP.NET 核心授权文档中找到了解决方案。
根据Microsoft ASP .NET core 文档中提到的文章,在某些情况下,例如单页应用程序(SPA),使用多种身份验证方法是很常见的。例如,应用程序可能使用 cookie-based 身份验证登录,并为 JavaScript 请求使用 JWT 承载身份验证。
认证方案是在认证时配置认证服务时命名的。例如:
public void ConfigureServices(IServiceCollection services)
{
// Code omitted for brevity
services.AddAuthentication()
.AddCookie(options => {
options.LoginPath = "/Account/Unauthorized/";
options.AccessDeniedPath = "/Account/Forbidden/";
})
.AddJwtBearer(options => {
options.Audience = "http://localhost:5001/";
options.Authority = "http://localhost:5000/";
});
在前面的代码中,添加了两个身份验证处理程序:一个用于 cookie,一个用于承载。
选择具有授权属性的方案
[Authorize(AuthenticationSchemes =
JwtBearerDefaults.AuthenticationScheme)]
public class MixedController : Controller
在前面的代码中,只有具有 "Bearer" 方案的处理程序运行。忽略任何 cookie-based 个身份。
这是解决我问题的解决方案,我认为与需要它的人分享它会很好。
Multiple Authentication Schemes in .Net Core 3.1 or .Net 5.0
Startup.cs
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(x =>
{
x.LoginPath = "/";
x.ExpireTimeSpan = TimeSpan.FromMinutes(Configuration.GetValue<int>("CookieExpiry"));
})
.AddJwtBearer(x =>
{
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Configuration.GetValue<string>("JWTSecret"))),
ValidateIssuer = false,
ValidateAudience = false
};
});
services.AddAuthorization(options =>
{
var defaultAuthorizationPolicyBuilder = new AuthorizationPolicyBuilder(CookieAuthenticationDefaults.AuthenticationScheme, JwtBearerDefaults.AuthenticationScheme);
defaultAuthorizationPolicyBuilder = defaultAuthorizationPolicyBuilder.RequireAuthenticatedUser();
options.DefaultPolicy = defaultAuthorizationPolicyBuilder.Build();
});
/api/auth/login
public async Task<AuthenticationResult> Login([FromForm] string userName, [FromForm] string password, [FromHeader] string authmode = "")
{
if (userName != "demo" || password != "demo")
return new AuthenticationResult { HasError = true, Message = "Either the user name or password is incorrect." };
var claims = new Claim[]
{
new Claim(ClaimTypes.Name, userName)
};
if(authmode?.ToLower() == "token")
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_config.GetValue<string>("JWTSecret"));
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(claims, "JWT"),
Expires = DateTime.UtcNow.AddMinutes(_config.GetValue<int>("JWTExpiry")),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
var jwt = tokenHandler.WriteToken(token);
return new AuthenticationResult { Token = jwt };
}
else
{
ClaimsPrincipal princ = new ClaimsPrincipal(new ClaimsIdentity(claims, "COOKIE"));
await HttpContext.SignInAsync(princ);
return new AuthenticationResult();
}
}
输出:
我一直在使用 ASP.NET Core 3.1 和干净的架构制作 Web 应用程序。
我有一些 class 库,例如 Infrastructure、Persistence、Domain、Application 和一个名为“Web”的 MVC 应用程序项目作为我的应用程序的启动点。
在 Web 层中,我有一个“区域”,其中有一个管理区域,其中包含一些控制器和 操作方法,return JSON 作为我的 API在基于 React 的应用程序中使用的端点。
我在 Controllers 文件夹中的 Web MVC 项目中也有一些控制器,它们的 action 方法 return html views.
我的 API 端点也使用 Identity 和 JWT,但是:
- 如果我想在我的 MVC 控制器中使用基于声明的身份,他们的操作会导致 return html 次查看怎么办?
- 在此类应用程序中使用 ASP.NET Core 3.1 中基于声明的身份的最佳实践是什么?
如有任何帮助,我们将不胜感激。
经过一些研究,我在一篇标题为“Authorize with a specific scheme in ASP.NET Core”的文章中的 ASP.NET 核心授权文档中找到了解决方案。
根据Microsoft ASP .NET core 文档中提到的文章,在某些情况下,例如单页应用程序(SPA),使用多种身份验证方法是很常见的。例如,应用程序可能使用 cookie-based 身份验证登录,并为 JavaScript 请求使用 JWT 承载身份验证。
认证方案是在认证时配置认证服务时命名的。例如:
public void ConfigureServices(IServiceCollection services)
{
// Code omitted for brevity
services.AddAuthentication()
.AddCookie(options => {
options.LoginPath = "/Account/Unauthorized/";
options.AccessDeniedPath = "/Account/Forbidden/";
})
.AddJwtBearer(options => {
options.Audience = "http://localhost:5001/";
options.Authority = "http://localhost:5000/";
});
在前面的代码中,添加了两个身份验证处理程序:一个用于 cookie,一个用于承载。
选择具有授权属性的方案
[Authorize(AuthenticationSchemes =
JwtBearerDefaults.AuthenticationScheme)]
public class MixedController : Controller
在前面的代码中,只有具有 "Bearer" 方案的处理程序运行。忽略任何 cookie-based 个身份。
这是解决我问题的解决方案,我认为与需要它的人分享它会很好。
Multiple Authentication Schemes in .Net Core 3.1 or .Net 5.0
Startup.cs
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(x =>
{
x.LoginPath = "/";
x.ExpireTimeSpan = TimeSpan.FromMinutes(Configuration.GetValue<int>("CookieExpiry"));
})
.AddJwtBearer(x =>
{
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Configuration.GetValue<string>("JWTSecret"))),
ValidateIssuer = false,
ValidateAudience = false
};
});
services.AddAuthorization(options =>
{
var defaultAuthorizationPolicyBuilder = new AuthorizationPolicyBuilder(CookieAuthenticationDefaults.AuthenticationScheme, JwtBearerDefaults.AuthenticationScheme);
defaultAuthorizationPolicyBuilder = defaultAuthorizationPolicyBuilder.RequireAuthenticatedUser();
options.DefaultPolicy = defaultAuthorizationPolicyBuilder.Build();
});
/api/auth/login
public async Task<AuthenticationResult> Login([FromForm] string userName, [FromForm] string password, [FromHeader] string authmode = "")
{
if (userName != "demo" || password != "demo")
return new AuthenticationResult { HasError = true, Message = "Either the user name or password is incorrect." };
var claims = new Claim[]
{
new Claim(ClaimTypes.Name, userName)
};
if(authmode?.ToLower() == "token")
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_config.GetValue<string>("JWTSecret"));
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(claims, "JWT"),
Expires = DateTime.UtcNow.AddMinutes(_config.GetValue<int>("JWTExpiry")),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
var jwt = tokenHandler.WriteToken(token);
return new AuthenticationResult { Token = jwt };
}
else
{
ClaimsPrincipal princ = new ClaimsPrincipal(new ClaimsIdentity(claims, "COOKIE"));
await HttpContext.SignInAsync(princ);
return new AuthenticationResult();
}
}
输出: