C#基于JWT实现分布式登录攻略
概述
JWT (JSON Web Token) 是一种用于在网络应用间传递身份信息的安全加密方式。它不需要在服务端存储token信息,使用时请求时发送jwt,服务端解析jwt和密钥进行验证即可,因此是一种轻量级的协议。在分布式架构下,使用JWT可以方便地实现服务间的身份验证。
本攻略将帮助你使用C#实现基于JWT的分布式登录。
步骤
第一步:安装依赖
JWT需要使用依赖包System.IdentityModel.Tokens.Jwt
,使用Nuget进行安装:
Install-Package System.IdentityModel.Tokens.Jwt -Version 5.6.0
第二步:定义用户和用户服务
以下为一个简单的用户模型:
public class User
{
public string Username { get; set; }
public string Password { get; set; }
}
以下为一个简单的用户服务模型:
public interface IUserService
{
User Authenticate(string username, string password);
}
你可以使用任何你喜欢的用户和用户服务模型,下面的示例中我们将使用以上提供的模型。
第三步:定义数据源
在我们的示例中,我们使用了一个静态变量作为我们的数据源,如下所示:
public class UserService : IUserService
{
// 用于演示的数据源
private List<User> _users = new List<User>
{
new User { Username = "admin", Password = "admin" },
new User { Username = "test", Password = "test" }
};
public User Authenticate(string username, string password)
{
var user = _users.SingleOrDefault(u => u.Username == username && u.Password == password);
// 用户不存在或密码错误
if (user == null)
return null;
// 验证成功,返回用户信息
return user;
}
}
在一个实际的应用中,你需要从数据库或其他数据源中检索并验证用户信息,而不是像本示例那样使用静态变量。
第四步:定义JWT Token以及过期时间
为了加强token的安全性,我们需要定义一个key来验证token的有效性。
在本示例中,假设我们已经定义好了jwt security key:
private readonly byte[] _secretKey = Encoding.UTF8.GetBytes("thisIsMyJwtSecurityKey");
在此之后,我们需要定义JWT Token以及过期时间:
private string GenerateJwtToken(User user)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = _secretKey;
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim(JwtRegisteredClaimNames.Sub, user.Username),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
}),
Expires = DateTime.UtcNow.AddHours(1),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
在此示例中,我们使用了SymmetricSecurityKey
和HmacSha256Signature
,但是你也可以使用其他的签名算法。
第五步:登录验证
在我们的用户服务中,我们定义了一个Authenticate
方法。我们需要在此方法中完成身份验证并输出JWT Token。
在此之后,每次鉴权时,需要将JWT Token附加在HTTP请求标头上。
以下是详细的代码实现:
public class UserController : ControllerBase
{
private readonly IUserService _userService;
private readonly byte[] _secretKey = Encoding.UTF8.GetBytes("thisIsMyJwtSecurityKey");
public UserController(IUserService userService)
{
_userService = userService;
}
[HttpPost("login")]
public IActionResult Login([FromBody] User userParam)
{
// 身份验证
var user = _userService.Authenticate(userParam.Username, userParam.Password);
if (user == null)
return BadRequest(new { message = "用户名或密码错误。" });
// 创建jwt token
var tokenString = GenerateJwtToken(user);
return Ok(new { token = tokenString });
}
[Authorize]
[HttpGet("test")]
public IActionResult Test()
{
return Ok("身份验证已通过。");
}
// 生成 jwt token
private string GenerateJwtToken(User user)
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = _secretKey;
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim(JwtRegisteredClaimNames.Sub, user.Username),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
}),
Expires = DateTime.UtcNow.AddHours(1),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
return tokenHandler.WriteToken(token);
}
}
在此示例中,我们定义了一个Login
方法和一个Test
方法。当用户成功通过Login
方法时,将返回JWT Token。此后,我们可以使用Test
方法进行身份验证。HTTP请求应该附带一个标头——Authorization: Bearer <token>
,其中<token>
是在Login
方法调用时获取到的JWT Token。
示例1:在ASP.Net Core中使用JWT验证身份
以下是一个具体的ASP.Net Core应用场景,其中代码提供了一个可用的控制器:
public class UserController : ControllerBase
{
private readonly IConfiguration _configuration;
public UserController(IConfiguration configuration)
{
_configuration = configuration;
}
[HttpPost("login")]
public IActionResult Login([FromBody] User user)
{
if (user == null)
{
return BadRequest("Invalid client request");
}
if (user.Username == "test" && user.Password == "test")
{
var secretKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["SecretKey"]));
var signinCredentials = new SigningCredentials(secretKey, SecurityAlgorithms.HmacSha256);
var tokeOptions = new JwtSecurityToken(
issuer: "http://localhost:5000",
audience: "http://localhost:5000",
claims: new List<Claim>(),
expires: DateTime.Now.AddSeconds(30),
signingCredentials: signinCredentials
);
var tokenString = new JwtSecurityTokenHandler().WriteToken(tokeOptions);
return Ok(new { Token = tokenString });
}
return Unauthorized();
}
[HttpGet("{id}")]
public IActionResult Get(int id)
{
var currentUser = HttpContext.User;
var result = $"Your id is {id} and you are {currentUser.Identity.Name}.";
return Ok(result);
}
}
以上示例中,我们首先定义了一个Login
方法,其中完成了用户验证并生成了JWT Token。而对于其他需要身份验证的方法,使用了ASP.Net Core默认的[Authorize]
验证。
示例2:在WPF中使用JWT验证身份
以下示例是一个WPF应用中使用JWT进行身份验证的示例。我们使用JWT Token作为HTTP请求标头的Authorization参数。
private void SignInButton_Click(object sender, RoutedEventArgs e)
{
var client = new WebClient();
try
{
client.Headers.Add("authorization", "Bearer " + GetJwtToken());
var result = client.DownloadString(_url + "/api/values");
MessageBox.Show(result, "Success");
}
catch (WebException ex)
{
MessageBox.Show(ex.Message, "Error");
}
}
private string GetJwtToken()
{
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes(_secretKey);
var tokenDescriptor = new SecurityTokenDescriptor
{
Issuer = "issuer",
Expires = DateTime.UtcNow.AddHours(_tokenDurationHours),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key),
SecurityAlgorithms.HmacSha256Signature),
};
var token = tokenHandler.CreateToken(tokenDescriptor);
var tokenString = tokenHandler.WriteToken(token);
return tokenString;
}
结论
通过本攻略,我们学习了C#中基于JWT的分布式登录实现方法。在实际应用中,您可以将各种Web和桌面应用程序连接到您的身份验证服务,以实现高度安全的分布式身份验证。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#基于jwt实现分布式登录 - Python技术站