我想在 .net 8.0.0 中为我的 Web api 创建身份验证和授权(考虑到在另一个项目的 7.0.0 中,我能够使用与下面描述的相同方法使用承载者,这一点很重要),并且我想使用JWT 不记名令牌。我有一个具有授权属性的 GetRequest,因此只有授权用户才能发出请求,但它不起作用。登录后,我成功获取了令牌,但是当我粘贴它(使用 swagger ui 授权按钮)并想要使用 GetRequest 时,我收到 401 错误,有什么想法吗?
我有两个我认为相互关联的文件,一个称为 tokenservice,另一个是program.cs:
public class TokenService : ITokenService
{
private const int ExpirationMinutes = 30;
public string CreateToken(IdentityUser user)
{
var expiration = DateTime.UtcNow.AddMinutes(ExpirationMinutes);
var token = CreateJwtToken(
CreateClaims(user),
CreateSigningCredentials(),
expiration
);
var tokenHandler = new JwtSecurityTokenHandler();
return tokenHandler.WriteToken(token);
}
private JwtSecurityToken CreateJwtToken(List<Claim> claims, SigningCredentials credentials, DateTime expiration) =>
new JwtSecurityToken(
"apiWithAuthBackend",
"apiWithAuthBackend",
claims,
expires: expiration,
signingCredentials: credentials
);
private List<Claim> CreateClaims(IdentityUser user)
{
try
{
var claims = new List<Claim>
{
new Claim(JwtRegisteredClaimNames.Sub, "TokenForTheApiWithAuth"),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Iat, DateTime.UtcNow.ToString(CultureInfo.InvariantCulture)),
new Claim(ClaimTypes.NameIdentifier, user.Id ?? ""),
new Claim(ClaimTypes.Name, user.UserName ?? ""),
new Claim(ClaimTypes.Email, user.Email ?? "")
};
return claims;
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
private SigningCredentials CreateSigningCredentials()
{
string secretKey = "!SomethingSecret!";
byte[] keyBytes = Encoding.UTF8.GetBytes(secretKey);
// Trim or pad the key to make it exactly 32 bytes
Array.Resize(ref keyBytes, 32);
return new SigningCredentials(
new SymmetricSecurityKey(keyBytes),
SecurityAlgorithms.HmacSha256
);
}
}
var builder = WebApplication.CreateBuilder(args);
// Add services
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddScoped<IPageService, PageService>();
builder.Services.AddDbContext<UsersContext>();
builder.Services.AddScoped<IAuthService, AuthService>();
builder.Services.AddScoped<ITokenService, TokenService>();
builder.Services.AddDbContext<ProductDataContext>(options =>
{
options.UseSqlServer(builder.Configuration.GetConnectionString("ProductDataContext"));
});
// Add Identity
builder.Services.AddIdentityCore<IdentityUser>(options =>
{
options.SignIn.RequireConfirmedAccount = false;
options.User.RequireUniqueEmail = true;
options.Password.RequireDigit = false;
options.Password.RequiredLength = 6;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = false;
options.Password.RequireLowercase = false;
}).AddEntityFrameworkStores<UsersContext>();
// Configure Swagger
builder.Services.AddSwaggerGen(option =>
{
option.SwaggerDoc("v1", new OpenApiInfo { Title = "Demo API", Version = "v1" });
option.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
In = ParameterLocation.Header,
Description = "Please enter a valid token",
Name = "Authorization",
Type = SecuritySchemeType.Http,
BearerFormat = "JWT",
Scheme = "Bearer"
});
option.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type=ReferenceType.SecurityScheme,
Id="Bearer"
}
},
new string[]{}
}
});
});
// Configure Authentication
builder.Services
.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters()
{
ClockSkew = TimeSpan.Zero,
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = "apiWithAuthBackend",
ValidAudience = "apiWithAuthBackend",
IssuerSigningKey = new SymmetricSecurityKey(
PadKey(Encoding.UTF8.GetBytes("!SomethingSecret!"), 32)
),
};
});
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
但是当我粘贴它(使用 swagger ui 授权按钮)并想要使用时 GetRequest,我收到 401 错误
您必须在令牌前添加“Bearer”(注意空格)