注意:这是一种非常简单且不是最低限度安全的设置 JWT 的方法。
步骤 1——安装软件包
首先,您需要安装一些 NuGet 包。
dotnet add package Microsoft.AspCore.Authentication.JwtBearer
dotnet add package System.IdentityModel.Tokens.Jwt
步骤 2——创建类
你需要创建一些类来处理登录请求、注册请求和授权响应。你还需要某种类型的用户。
using System.ComponentModel.DataAnnotations;
namespace Auth;
public class LoginRequest
{
[Required]
[EmailAddress]
public string Email { get; set; }
[Required]
public string Password { get; set; }
}
using System.ComponentModel.DataAnnotations;
namespace Auth;
public class RegistrationRequest
{
[Required]
public string UserID { get; set; }
[Required]
public string Username { get; set; }
[Required]
public string Firstname { get; set; }
[Required]
public string Lastname { get; set; }
[Required]
[EmailAddress]
public string Email { get; set; }
[Required]
public string Password { get; set; }
}
namespace Auth;
public class AuthResponse
{
public string UserId { get; set; }
public string Username { get; set; }
public string Token { get; set; }
public string? ProfileImage { get; set; }
}
步骤 3——创建控制器
当我们创建了类之后,我们需要实现注册用户和登录的逻辑。我将跳过创建用户的逻辑,只在我的示例中使用我的服务,您需要自己做这件事。
[HttpPost("register")]
public async Task<IActionResult> Register([FromBody] RegistrationRequest request)
{
var salt = GenerateSalt();
var saltedPassword = request.Password + salt;
var user = new User
{
Firstname = request.Firstname,
Lastname = request.Lastname,
Email = request.Email,
Password = _passwordHasher.HashPassword(null, saltedPassword), // Null is because the user is not created yet, normally this is where the user object is.
Salt = salt,
Role = Enums.Role.USER
};
await _userService.CreateUser(user);
var token = _tokenService.CreateToken(user);
return Ok(new AuthResponse { Token = token });
}
[HttpPost("login")]
public async Task<IActionResult> Login([FromBody] LoginRequest request)
{
User? user = await _userService.FindByEmailAsync(request.Email);
if (user == null)
{
return Unauthorized("Invalid credentials 1");
}
var saltedPassword = request.Password + user.Salt;
var result = _passwordHasher.VerifyHashedPassword(user, user.Password,saltedPassword);
if (result != PasswordVerificationResult.Success)
{
return Unauthorized("Invalid credentials 2");
}
// Generate token
var token = _tokenService.CreateToken(user);
// Return the token
return Ok(new AuthResponse { Token = token });
}
步骤4 —创建令牌服务
现在我们需要创建一个生成 JWT 令牌的方法。在我们的令牌中,我们可以添加任意数量的索赔正如我们想要的那样。这里需要注意的是,我们的 SecurityTokenDescriptor 必须具有与“Program.cs”中的授权设置相同的令牌验证参数。我们稍后会再讨论这一点。我在这里使用的名为“_configuration”的变量,正是通过“IConfiguration”依赖注入到我的控制器中的。
public string CreateToken(User user)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_configuration["Jwt:Key"]);
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim(ClaimTypes.NameIdentifier, user.UserID),
new Claim(ClaimTypes.Role, user.Role.ToString()),
// Add more claims as needed
}),
Expires = DateTime.UtcNow.AddHours(1),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature),
Issuer = _configuration["Jwt:Issuer"], // Add this line
Audience = _configuration["Jwt:Audience"]
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
步骤 5 — 设置 Swagger 配置
现在我们需要配置 Swagger,以便稍后测试我们的端点。这里需要注意的是,当我们在 Swagger 的授权输入框中输入令牌字符串时,需要依次输入:Bearer,后跟一个空格,然后是令牌字符串。
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new() { Title = "Pappa´s API", Version = "v1" });
// Define the OAuth2.0 scheme that's in use (i.e., Implicit Flow)
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer"
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement()
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
},
Scheme = "oauth2",
Name = "Bearer",
In = ParameterLocation.Header,
},
new List<string>()
}
});
});
步骤 6——设置授权
这里重要的是,我们的令牌验证参数与我们在令牌服务中的“CreateToken”方法中添加的参数相同。
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = builder.Configuration["Jwt:Issuer"],
ValidAudience = builder.Configuration["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])),
ClockSkew = TimeSpan.Zero
};
});
步骤 7——设置中间件
我们放置中间件的顺序非常重要,所以不要弄错顺序。我们也指定 Swagger 仅在开发环境中有效。
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.MapControllers();
步骤 8 — 设置应用程序设置
现在我们需要将 JWT 值添加到我们的“apptsettings.json”文件中,包括密钥、颁发者和受众。出于演示和开发目的,我仅使用这些简单的值。但请注意,密钥尤其不应以纯文本形式存储,为了安全起见,最好将所有值存储在安全的地方,例如 Azure Secrets 或 GitHub Secrets。
"Jwt": {
"Key": "your_secret_key_here_your_secret_key_here",
"Issuer": "your_issuer",
"Audience": "your_audience"
}
步骤 9 — 在控制器中设置授权
现在是时候将我们的令牌集成到我们的某个 API 中了。为此,我们让 .NET 处理编码,就像我们在“Program.cs”文件中设置的那样。我们还添加了“[Authroize]”和“Roles”,以实现基于角色的身份验证。如果您想添加更多角色,只需在同一字符串中用逗号分隔它们即可。
[HttpGet("getuser")]
[Authorize(Roles = "USER")]
public async Task<ActionResult<User>> GetUser()
{
// Retrieve userId from the claims
var userIdClaim = User.Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier)?.Value;
Console.WriteLine("Claims received:");
foreach (var claim in User.Claims)
{
Console.WriteLine($"{claim.Type}: {claim.Value}");
}
if(userIdClaim == null)
{
return Unauthorized("No user ID claim present in token.");
}
try
{
User? user = await _userService.GetUser(userIdClaim);
return Ok(user);
}
catch (InvalidOperationException ex)
{
return BadRequest(ex.Message);
}
}
关于.NET8集成JWT本文先介绍到这里了。
如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。