public UsersController(ILogger<UsersController> logger, IUserRepository userRepository, IMapper mapper, IConfiguration config, IHttpContextAccessor httpContextAccessor)
{
_logger = logger;
_userRepository = userRepository;
_mapper = mapper;
_config = config;
_httpContextAccessor = httpContextAccessor;
}
[HttpGet]
public async Task<JsonResult> Get()
{
var userId = int.Parse(_httpContextAccessor.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value);
var userInfo = await _userRepository.GetUserDetail(userId);
if (userInfo == null)
{
return Json(new { Code = 200, Msg = "未找到该用户的信息" });
}
var outputModel = _mapper.Map<UserModel>(userInfo);
return Json(new { Code = 200, Data = outputModel }); ;
}
[HttpPost]
[AllowAnonymous]
public async Task<JsonResult> Login([FromBody] UserLoginModel user)
{
// 查询用户信息
var data = await _userRepository.GetUserDetailByEmail(user.Email);
// 账号不存在
if (data == null)
{
return Json(new { Code = 200, Msg = "账号或密码错误" });
}
user.Password = Encrypt.Md5(data.Salt + user.Password);
// 密码不一致
if (!user.Password.Equals(data.Password))
{
return Json(new { Code = 200, Msg = "账号或密码错误" });
}
var userModel = _mapper.Map<UserModel>(data);
// 生成token
var token = GenerateJwtToken(userModel);
// 存入Redis
await new RedisHelper().StringSetAsync($"token:{data.Id}", token);
return Json(new
{
Code = 200,
Msg = "登录成功",
Data = userModel,
Token = token
});
}
[HttpPost]
[AllowAnonymous]
public async Task<JsonResult> Register([FromBody] UserRegisterModel user)
{
// 查询用户信息
var data = await _userRepository.GetUserDetailByEmail(user.Email);
if (data != null)
{
return Json(new { Code = 200, Msg = "该邮箱已被注册" });
}
var salt = Guid.NewGuid().ToString("N");
user.Password = Encrypt.Md5(salt + user.Password);
var users = new Users
{
Email = user.Email,
Password = user.Password,
UserName = user.UserName
};
var model = _mapper.Map<Users>(user);
model.Salt = salt;
await _userRepository.AddUser(model);
return Json(new { Code = 200, Msg = "注册成功" });
}
/// <summary>
/// 生成Token
/// </summary>
/// <param>用户信息</param>
/// <returns></returns>
private string GenerateJwtToken(UserModel user)
{
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var claims = new[] {
new Claim(JwtRegisteredClaimNames.Email, user.Email),
new Claim(JwtRegisteredClaimNames.Gender, user.Gender.ToString()),
new Claim(ClaimTypes.NameIdentifier,user.Id.ToString()),
new Claim(ClaimTypes.Name,user.UserName),
new Claim(ClaimTypes.MobilePhone,user.Mobile??""),
};
var token = new JwtSecurityToken(_config["Jwt:Issuer"],
_config["Jwt:Issuer"],
claims,
expires: DateTime.Now.AddMinutes(120),
signingCredentials: credentials);
return new JwtSecurityTokenHandler().WriteToken(token);
}
}
}
```
最后,来测试一下我们的功能,首先是注册。
先来验证一下我们的传入的参数是否符合我们定义的规则。
输入一个错误的邮箱号试试看!
![注册](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/cc82cdbc9582433d9da23a9b173cf3a7~tplv-k3u1fbpfcp-zoom-1.image)
ok,没有问题,和我们在 UserRegisterModel 中 添加的验证特性返回结果一致,最后我们测试一下完全符合规则的情况。
![注册成功](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4ccdc22db2ab49dfa679985b40014f2e~tplv-k3u1fbpfcp-zoom-1.image)
最后,注册成功了,查询下数据库也是存在的。
![user](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/cae6c5377c174866b2597a280229ff24~tplv-k3u1fbpfcp-zoom-1.image)
我们来试试登录接口,在调用登录接口之前我们先来测试一下我们的配置的权限验证是否已经生效,在不登录的情况下直接访问获取用户信息接口。
![未授权](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/4f8da469271b4835976987706ecde349~tplv-k3u1fbpfcp-zoom-1.image)
直接访问会返回未授权,那是因为我们没有登录,自然也就没有 Token,目前来看是没问题的,但要看看我们传入正确的Token 是否能过权限验证。
现在,我们需要调用登录接口,登录成功后会返回一个Token,后面的接口请求都需要用到,不然会无权限访问。
先来测试一下密码错误的情况。
![密码错误](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5fea1fd34fbb4dadbb78e7f721194ffe~tplv-k3u1fbpfcp-zoom-1.image)
返回正确,符合我们的预期结果,下面将试试正确的密码登录,看是否能够返回我们想要的结果。
![登录成功](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/49b543a313c14ef68414b5fcab2e0b63~tplv-k3u1fbpfcp-zoom-1.image)
登录成功,接口也返回了我们预期的结果,最后看看生成的 token 是否按照我们写的逻辑那样,存一份到 redis 当中。
![redis](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/efe0dc798691492abe8766b8e48a9c83~tplv-k3u1fbpfcp-zoom-1.image)
也是没有问题的,和我们预想的一样。
下面将携带正确的 token 请求获取用户信息的接口,看看是否能够正确返回。
获取用户信息的接口不会携带任何参数,只会在请求头的 Headers 中 添加 Authorization ,将我们正确的 token 传入其中。
![获取用户信息](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e9c052ebaaa94a1bb7334605e6460e0b~tplv-k3u1fbpfcp-zoom-1.image)
能够正确获取到我们的用户信息,也就是说我们的权限这一块也是没有问题的了,下面将使用 Docker 打包部署到 Linux 服务器中。
## 打包部署
在项目的根目录下添加 Dockerfile 文件,内容如下。
```
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.
FROM mcr.microsoft.com/dotnet/aspnet:5.0-buster-slim AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443