首页 > 解决方案 > .net core 3.1 结合 Cookies 和 Bearer Authorization 但授权角色不能正常工作

问题描述

我想使用 OAuth 登录

并且可以使用cookies和Bearer Authorization进行认证

来自ASP.NET Core 2.0 的参考,将 Cookie 和承载授权结合到同一端点

但是cookie可以正常工作,Bearer Authorization不能

这是我在 Startup.cs 中进行身份验证的设置:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();

        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        // JWT tokens
        .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options => // JwtBearerDefaults.AuthenticationScheme
        {
            options.Authority = Configuration["auth:oidc:AuthBaseUri"];
            options.Audience = Configuration["auth:oidc:Scopes"];

            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,
                NameClaimType = "name",
                RoleClaimType = "role",
            };

            options.SaveToken = true;
        });

        services.AddAuthentication(options =>
        {
            options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
        })
        .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
        .AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
        {
            options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            options.AuthenticationMethod = OpenIdConnectRedirectBehavior.RedirectGet;

            options.Authority = Configuration["auth:oidc:AuthBaseUri"];
            options.ClientId = Configuration["auth:oidc:ClientId"];
            options.ClientSecret = Configuration["auth:oidc:ClientSecret"];

            options.Scope.Clear();
            options.Scope.Add("openid roles profile");
            options.Scope.Add(Configuration["auth:oidc:Scopes"]);

            options.GetClaimsFromUserInfoEndpoint = true;
            options.ClaimActions.MapJsonKey("role", "role", "role");

            options.UseTokenLifetime = true;

            options.TokenValidationParameters = new TokenValidationParameters
            {
                NameClaimType = "name",
                RoleClaimType = "role"
            };

            options.SaveTokens = true;
            options.ResponseType = OpenIdConnectResponseType.Code;
        });

        services.AddAuthorization(options =>
        {
            var defaultAuthorizationPolicyBuilder = new AuthorizationPolicyBuilder(CookieAuthenticationDefaults.AuthenticationScheme, JwtBearerDefaults.AuthenticationScheme);
            defaultAuthorizationPolicyBuilder = defaultAuthorizationPolicyBuilder.RequireAuthenticatedUser();

            options.DefaultPolicy = defaultAuthorizationPolicyBuilder.Build();
        });
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseHttpsRedirection();

        app.UseRouting();

        app.UseAuthentication(); 
        app.Use(async (context, next) =>
        {
            await next();
            var bearerAuth = context.Request.Headers["Authorization"]
                .FirstOrDefault()?.StartsWith("Bearer ") ?? false;
            if (context.Response.StatusCode == 401
                && !context.User.Identity.IsAuthenticated
                && !bearerAuth)
            {
                await context.ChallengeAsync(OpenIdConnectDefaults.AuthenticationScheme);
            }
        });
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }

我有以下示例端点:

    [HttpGet]
    [Authorize(Roles = "xxxRole")]
    public IEnumerable<WeatherForecast> Get()
    {
        var rng = new Random();
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = rng.Next(-20, 55),
            Summary = Summaries[rng.Next(Summaries.Length)]
        })
        .ToArray();
    }

jwt示例:

eyJhbGciOiJSUzI1NiIsImtpZCI6InlYa2hPMTc5XzlUM0Jkc1ZBbjhEV2ciLCJ0eXAiOiJhdCtqd3QifQ.eyJuYmYiOjE2MjEzNDM3NzYsImV4cCI6MTYyMTM0NzM3NiwiaXNzIjoiaHR0cHM6Ly9taWNyb3N1Z2Fyb2F1dGguYXp1cmV3ZWJzaXRlcy5uZXQiLCJhdWQiOiJ0QXV0aG9yaXphdGlvbkNvZGVBcGkiLCJjbGllbnRfaWQiOiJ0QXV0aG9yaXphdGlvbkNvZGVDbGllbnRJZCIsInN1YiI6IjUxMzI1ODExLWU2Y2EtNGRkNS05NmMzLTk4YzY1OTYxNzQxNyIsImF1dGhfdGltZSI6MTYyMTMzNjc2NywiaWRwIjoibG9jYWwiLCJ3ZWJzaXRlIjpbImh0dHBzOi8vbG9jYWxob3N0OjQ0Mzg4IiwiaHR0cHM6Ly9sb2NhbGhvc3Q6NTAwMSJdLCJyb2xlIjoidFJvbGUiLCJqdGkiOiJzUUtvY3ZwbWdfcjY1cERtc1VXTXNnIiwic2NvcGUiOlsib3BlbmlkIiwicHJvZmlsZSIsInRBdXRob3JpemF0aW9uQ29kZUFwaSJdLCJhbXIiOlsicHdkIl19.FiZJDMOXYA72yd-q7qesU1apqxURDKE73IfGGuyHmDVKlc8UWpkTIeEl4bUBpoahs2FSNs5FX7fdgS1uq3xhAH9D-7Mozg8R0C1fhmAkCU8JvQ9TRoKUf8IjdZTO0dv59mBryAisUBUfygiAOUbnvcsHODGX5MV7EmViw8rcgbusSmI7SC6wSeFBaD9IbiJVsBfdveD2NVMTpJacTZfDb15ngo5HS3K571pZ9mFMgMVqu9-SzOb6PdwZXcHuPXUXzFQfJCYBOpWMA_kVHtI5jhUEm1GeG7S92fgk7eHYHj7cBiPIqeHTvlf5ab6AQ3kooNgEzFgSQLU0M66z8HlocQ

标签: c#asp.net-core.net-corecookiesbearer-token

解决方案


推荐阅读