注意:這是一種非常簡單且不是最低限度安全的設置 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本文先介紹到這里了。
如果您喜歡此文章,請收藏、點贊、評論,謝謝,祝您快樂每一天。