将 JWT 添加到 .Net Identity 后,基于角色的授权不起作用

问题描述 投票:0回答:1

将 Jwt 身份验证添加到 Web API 后,如果我不在天气预报控制器方法中指定角色,似乎也可以。指定角色后,只有 JWT 授权有效。我尝试了各种方法,改变主张等,但没有任何帮助。使用.net身份认证时,会出现401 Unauthorized。

[完整源代码][https://drive.google.com/file/d/1N57j7NYkH-d_pS3cYAEU_yTVZF47JqcV/view?usp=drive_link]

创业班


    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);
            ConfigurationManager configuration = builder.Configuration;

            // Add services to the container.

            // For Entity Framework
            builder.Services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(configuration.GetConnectionString("ConnStr")));

            // For Identity
            builder.Services.AddIdentity<IdentityUser, IdentityRole>()
                .AddEntityFrameworkStores<ApplicationDbContext>()
                .AddClaimsPrincipalFactory<AppClaimsPrincipalFactory>()
                .AddDefaultTokenProviders();

            // Adding Authentication
            builder.Services.AddAuthentication(options =>
                {
                    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
                })

                // Adding Jwt Bearer
                .AddJwtBearer(options =>
                {
                    options.SaveToken = true;
                    options.RequireHttpsMetadata = false;
                    options.TokenValidationParameters = new TokenValidationParameters()
                    {
                        ValidateIssuer = true,
                        ValidateAudience = true,
                        ValidAudience = configuration["JWT:ValidAudience"],
                        ValidIssuer = configuration["JWT:ValidIssuer"],
                        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["JWT:Secret"]))
                    };
                });

            builder.Services.ConfigureApplicationCookie(options =>
            {
                options.Events.OnRedirectToLogin = context =>
                {
                    context.Response.Headers["Location"] = context.RedirectUri;
                    context.Response.StatusCode = 401;
                    return Task.CompletedTask;
                };
            });

            builder.Services.AddAuthorization(options =>
            {
                options.DefaultPolicy = new AuthorizationPolicyBuilder("Identity.Application", JwtBearerDefaults.AuthenticationScheme)
                    
                    .RequireAuthenticatedUser()
                    .Build();
            });

            builder.Services.AddControllers();
            // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
            builder.Services.AddEndpointsApiExplorer();
            builder.Services.AddSwaggerGen();

            var app = builder.Build();

            // Configure the HTTP request pipeline.
            if (app.Environment.IsDevelopment())
            {
                app.UseSwagger();
                app.UseSwaggerUI();
            }

            app.UseRouting();
            app.UseHttpsRedirection();

            // Authentication & Authorization
            app.UseAuthentication();
            app.UseAuthorization();

            app.MapControllers();

            app.Run();
        }
    }

天气预报控制器


    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

        private readonly ILogger<WeatherForecastController> _logger;

        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }

        [HttpGet, Authorize(Roles = "Admin")]
        public IEnumerable<WeatherForecast> Get()
        {
            var identity = HttpContext.User.Identity as ClaimsIdentity;

            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
                TemperatureC = Random.Shared.Next(-20, 55),
                Summary = Summaries[Random.Shared.Next(Summaries.Length)]
            })
            .ToArray();
        }

    }
asp.net-core jwt asp.net-identity role-based
1个回答
0
投票

我测试了你的代码。问题是您正在使用 jwt 身份验证。需要在请求中包含

Authorize
标头以及值
Bearer ...token...
来传递 api。
但另一方面,您正尝试使用 asp.net 身份 cookie 通过身份验证。 “JWT”和“asp.net 身份cookie”是不同的身份验证方案。使用此 cookie 永远不会传递受“JWT”保护的 api。
此响应意味着您通过尝试使用“承载者”传递 cookie 来获得 cookie

解决此问题的一个简单方法是使用此授权属性来指定 api 使用“asp.net 身份”方案

[Authorize(AuthenticationSchemes = "Identity.Application", Roles = "Admin")]

如果你希望这个 api 可以通过“jwt”和“cookie”传递。修改如下:

            builder.Services.AddAuthorization(options =>
            {
                options.AddPolicy("Jwt_Or_AspIdentiyCookie", policy =>
                {
                    policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
                    policy.AuthenticationSchemes.Add("Identity.Application");
                    policy.RequireAuthenticatedUser();
                });
            });

然后在控制器中使用

        [Authorize(policy: "Jwt_Or_AspIdentiyCookie", Roles = "Admin")]
© www.soinside.com 2019 - 2024. All rights reserved.