c# - .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
解决方案
推荐阅读
- javascript - 当我在我的 Vue 应用程序中使用选择标签时,下拉图标消失了。(铬合金)
- ios - 将存储的struct数据修改为其他结构
- react-native - 如何更改本机 ios 警报按钮颜色
- pandas - 替换 Pandas 列中距离度量大于阈值的元素
- google-chrome - 如何在 CentOS 7 上安装带有前缀的谷歌浏览器?
- c++ - 用指针编译代码后,.cpp 文件变成随机字符
- android - 发送到 handleSamplingAndRotationBitmap 的正确 URI 是什么?
- php - 完整性约束违规:laravel 6.2 中的 1048
- c# - C# Selenium WebDriver - 如何使用 FindElement.(By.XPath).Text 获取纯文本
- node.js - JsonWebToken 在 1 秒内完成的请求中具有相同的值