我已为用户提供了必要的权限,其内容如下所示我收到的令牌内容
{
"exp": 1676888952,
"iat": 1676888652,
"jti": "e9c4cdd9-6ad2-4d26-a031-e5d35bc83439",
"iss": "http://localhost:2011/realms/TestInventoryRealm",
"aud": "testcompany-inventory-client",
"sub": "022a83d1-42e3-40b2-ac11-542d87c5672f",
"typ": "Bearer",
"azp": "testcompany-inventory-client",
"session_state": "24f85a76-0637-4dd7-8b8c-0ac1ae2afb66",
"acr": "1",
"realm_access": {
"roles": [
"offline_access",
"default-roles-testcompanyinventoryrealm",
"Super Role",
"uma_authorization"
]
},
"resource_access": {
"realm-management": {
"roles": [
"view-identity-providers",
"view-realm",
"manage-identity-providers",
"impersonation",
"realm-admin",
"create-client",
"manage-users",
"query-realms",
"view-authorization",
"query-clients",
"query-users",
"manage-events",
"manage-realm",
"view-events",
"view-users",
"view-clients",
"manage-authorization",
"manage-clients",
"query-groups"
]
},
"broker": {
"roles": [
"read-token"
]
},
"testcompany-inventory-client": {
"roles": [
"Super Admin Role",
"Computing Role",
"uma_protection",
"Admin Role",
"User Role"
]
},
"account": {
"roles": [
"manage-account",
"view-applications",
"view-consent",
"view-groups",
"manage-account-links",
"delete-account",
"manage-consent",
"view-profile"
]
}
},
"authorization": {
"permissions": [
{
"scopes": [
"create:company",
"update:company",
"get:company",
"delete:company"
],
"rsid": "f2f036b2-4921-4e2b-9216-996d8cc5a349",
"rsname": "Company Resource"
},
{
"rsid": "c59c75c9-3bbe-4a1c-8671-71e3d4b975fc",
"rsname": "Default Resource"
}
]
},
"scope": "openid profile email",
"sid": "24f85a76-0637-4dd7-8b8c-0ac1ae2afb66",
"email_verified": false,
"name": "test user",
"preferred_username": "testuser001",
"given_name": "test",
"family_name": "user",
"email": "testuser@gmail.com"
}
应用程序设置
"Keycloak": {
"ServerRealm": "http://localhost:2011/realms/TestCompanyInventoryRealm",
"Metadata": "http://localhost:2011/realms/TestCompanyInventoryRealm/.well-known/openid-configuration",
"ClientId": "testcompany-inventory-client",
"ClientSecret": "faYwQ8ttVGO7R5wxVGrrZDqqPUCgWL7B",
"TokenExchange": "http://localhost:2011/realms/TestCompanyInventoryRealm/protocol/openid-connect/token",
"Audience": "testcompany-inventory-client",
"PublicKey": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjdT3dINxLFTnY8kxDPqfoh9U+TjUdisjG71RMpD6Wnd0wX64E9HeRaVxwPURDpUokoGVsVD++V8/U4aQRH3AbGzyw+90rKdPQEEAIkO/gcq8/1ppXojFX+qVT3N4/+4h/PPulwYZeO5FYoRoJAR5t4RXln4+ehOT6ShMKE/9Nxm41ijb/aUaOInp0mWO1kodn//qjqs0tZEU4YsOqeqL8ReM0/+IzYHZlyEZ11cjisxtH0fv5XI9y1C6IuRK55Iwf3yzQrDwmGQfuD3gyzs3v+WcGVdMT4e+9/QqE76WPscUwbZMNWwc0nTS4Vm+VXS5uwCcoYnRWHYY+Pw3E5ljGQIDAQAB"
}
程序.cs
我在应用程序的主要区域中使用如下定义开始项目。
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers(options =>
{
options.Filters.Add(new ValidateFilterAttribute());
}).AddJsonOptions(options =>
{
options.JsonSerializerOptions.IgnoreReadOnlyFields = true;
options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault | JsonIgnoreCondition.WhenWritingNull;
});
builder.Services.Configure<ApiBehaviorOptions>(options =>
{
options.SuppressModelStateInvalidFilter = true;
});
builder.Services.AddEndpointsApiExplorer();
//Custom FluentValidation
builder.Services.AddCustomApplicationServices();
#region Swagger
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "InventoryManagement.API", Version = "v1" });
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
{
Name = "Authorization",
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer",
BearerFormat = "JWT",
In = ParameterLocation.Header,
Description = "JWT Authorization header using the Bearer scheme. \r\n\r\n Enter 'Bearer' [space] and then your token in the text input below.\r\n\r\nExample: \"Bearer 1safsfsdfdfd\"",
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement {
{
new OpenApiSecurityScheme {
Reference = new OpenApiReference {
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
new string[] {}
}
});
});
#endregion
#region JWT
builder.Services
.AddAuthentication(auth =>
{
auth.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
auth.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.RequireHttpsMetadata = false;
options.Authority = builder.Configuration["Keycloak:ServerRealm"];
options.Audience = "testcompany-inventory-client";
options.IncludeErrorDetails= true;
options.SaveToken = true;
options.TokenValidationParameters = new()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = builder.Configuration["Keycloak:ServerRealm"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Keycloak:PublicKey"])),
};
});
builder.Services.AddAuthorization(opts =>
{
opts.AddPolicy("create:company", policy =>
{
policy.RequireClaim("scope", new[] { "create:company", "get:company", "update:company", "delete:company" });
});
});
#endregion
#region Dependencies
builder.Services.AddScoped<IUnitOfWork, UnitOfWork>();
builder.Services.AddScoped(typeof(IGenericRepository<>), typeof(GenericRepository<>));
builder.Services.AddScoped(typeof(IService<>), typeof(Service<>));
builder.Services.AddScoped(typeof(NotFoundFilter<>));
builder.Services.AddAutoMapper(typeof(AutoMapperProfile));
#endregion
#region Sql Server Connection
builder.Services.AddDbContext<DataContext>(x =>
{
x.UseSqlServer(builder.Configuration.GetConnectionString("IMDbConnection"), options =>
{
options.MigrationsAssembly(Assembly.GetAssembly(typeof(DataContext)).GetName().Name);
});
});
#endregion
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
builder.Host.ConfigureContainer<ContainerBuilder>(containerBuilder => containerBuilder.RegisterModule(new RepositoryServiceModule()));
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.UseAuthentication();
app.MapControllers().RequireAuthorization();
app.UseCustomException();
app.Run();
公司财务总监.cs
[Authorize(AuthenticationSchemes = "Bearer", Roles = "Super Admin Role", Policy = "company")]
public class CompanyController : CustomBaseController
{ }
但即使它是允许的,它也不能以任何方式进行认证。我错过了一个地方吗?
1条答案
按热度按时间u0sqgete1#
如果您得到一个401错误状态代码,那么这通常意味着您的令牌未被接受(身份验证)。
如果你得到一个403错误,那么这意味着你不被允许在(授权)
对此进行调试的一种方法是在AddJwtBearer中将此标志设置为true:
如果这样做,WWW-Authenticate报头将包括拒绝令牌的原因,例如:
代码中的另一个问题是这两个代码的顺序不对:
你应该总是在授权之前进行身份验证,否则就没有任何意义了。
如果出现403 Forbiddn错误,那么这是由授权模块引起的,为了解决这个问题,我通常创建一个action方法,它允许匿名请求,并且只返回在用户对象中找到的声明:
如果缺少作用域声明,那么您需要显式地将其添加到User对象,使用类似于以下内容的语句: