在 ASP.NET Core 3.1 中使用多个身份验证方案?

Asp*_*ian 10 c# asp.net-mvc identity asp.net-web-api asp.net-core

我一直在使用干净的架构使用 ASP.NET Core 3.1 制作 Web 应用程序。

我有一些类库,如基础结构、持久性、域、应用程序和一个名为“Web”的 MVC 应用程序项目作为我的应用程序的启动点。

在 Web 层中,我有一个“区域”,其中我有一个管理区域,其中包含一些控制器和操作方法,它们返回 JSON 作为我的 API 端点,以在基于 React 的应用程序中使用。

我在 Controllers 文件夹中的 Web MVC 项目中也有一些控制器,它们的操作方法返回 html 视图

我的 API 端点也使用 Identity 和 JWT,但是:

- 如果我想在我的 MVC 控制器中使用基于声明的身份,他们的操作结果返回 html 视图怎么办?

- 在这样的应用程序中,在 ASP.NET Core 3.1 中使用基于声明的标识的最佳实践是什么?

任何帮助,将不胜感激。

Asp*_*ian 17

经过一番研究,我在 ASP.NET Core Authorization 文档中找到了一篇题为“在 ASP.NET Core 中使用特定方案进行授权”的文章中的解决方案

基于 Microsoft ASP .NET 核心文档中提到的文章,在某些情况下,例如单页应用程序 (SPA),使用多种身份验证方法是很常见的。例如,应用程序可能使用基于 cookie 的身份验证来登录和 JWT 不记名身份验证对 JavaScript 请求。

身份验证方案是在身份验证过程中配置身份验证服务时命名的。例如:

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/";
        });
Run Code Online (Sandbox Code Playgroud)

在前面的代码中,添加了两个身份验证处理程序:一个用于 cookie,一个用于承载。

选择具有 Authorize 属性的方案

[Authorize(AuthenticationSchemes = 
    JwtBearerDefaults.AuthenticationScheme)]
public class MixedController : Controller
Run Code Online (Sandbox Code Playgroud)

在前面的代码中,只有具有“承载”方案的处理程序运行。任何基于 cookie 的身份都将被忽略。

这是解决了我的问题的解决方案,我认为最好与需要它的人分享。


Pal*_*mar 9

.Net Core 3.1 或 .Net 5.0 中的多种身份验证方案

启动文件

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();
            });
Run Code Online (Sandbox Code Playgroud)

/api/身份验证/登录

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

在此处输入图片说明 在此处输入图片说明

在此处输入图片说明 在此处输入图片说明