|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.IdentityModel.Tokens.Jwt;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Security.Claims;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using Admin.Core.Common;
|
|
|
|
|
using Admin.Core.Extensions;
|
|
|
|
|
using Admin.Core.IService;
|
|
|
|
|
using Admin.Core.IService.ISys;
|
|
|
|
|
using Admin.Core.Model;
|
|
|
|
|
using Admin.Core.Model.Sys;
|
|
|
|
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
|
|
|
|
using Microsoft.AspNetCore.Authorization;
|
|
|
|
|
using Microsoft.AspNetCore.Http;
|
|
|
|
|
using Microsoft.AspNetCore.Mvc;
|
|
|
|
|
using UAParser;
|
|
|
|
|
|
|
|
|
|
namespace Admin.Core.Api
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 登录管理
|
|
|
|
|
/// </summary>
|
|
|
|
|
[Produces("application/json")]
|
|
|
|
|
[Route("api/Login")]
|
|
|
|
|
[Authorize(Permissions.Name)]
|
|
|
|
|
public class LoginController : BaseApiUserController
|
|
|
|
|
{
|
|
|
|
|
readonly ISysMenuService _sysMenuService;
|
|
|
|
|
readonly ISysPermissionService _sysPermissionService;
|
|
|
|
|
readonly ISysLoginInfoService _sysLoginInfoService;
|
|
|
|
|
readonly ICaptcha _captcha;
|
|
|
|
|
readonly ISysConfigService _sysConfigService;
|
|
|
|
|
readonly PermissionRequirement _requirement;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 构造函数注入
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="sysUserService"></param>
|
|
|
|
|
/// <param name="sysMenuService"></param>
|
|
|
|
|
/// <param name="sysPermissionService"></param>
|
|
|
|
|
/// <param name="captcha"></param>
|
|
|
|
|
/// <param name="requirement"></param>
|
|
|
|
|
/// <param name="sysLoginInfoService"></param>
|
|
|
|
|
/// <param name="sysConfigService"></param>
|
|
|
|
|
public LoginController(ISysUserService sysUserService, ISysMenuService sysMenuService, ISysPermissionService sysPermissionService,
|
|
|
|
|
ICaptcha captcha, PermissionRequirement requirement, ISysLoginInfoService sysLoginInfoService,
|
|
|
|
|
ISysConfigService sysConfigService) : base(sysUserService)
|
|
|
|
|
{
|
|
|
|
|
_sysUserService = sysUserService;
|
|
|
|
|
_sysMenuService = sysMenuService;
|
|
|
|
|
_sysPermissionService = sysPermissionService;
|
|
|
|
|
_sysLoginInfoService = sysLoginInfoService;
|
|
|
|
|
_captcha = captcha;
|
|
|
|
|
_sysConfigService = sysConfigService;
|
|
|
|
|
_requirement = requirement;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 登录获取Token-JWT
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="loginBody"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
[HttpPost]
|
|
|
|
|
[Route("Login")]
|
|
|
|
|
[AllowAnonymous]
|
|
|
|
|
public async Task<MessageModel<TokenInfoViewModel>> GetJwtToken([FromBody] LoginBody loginBody)
|
|
|
|
|
{
|
|
|
|
|
string jwtStr = string.Empty;
|
|
|
|
|
|
|
|
|
|
if (!loginBody.IsNotEmptyOrNull() || string.IsNullOrEmpty(loginBody.LoginName) || string.IsNullOrEmpty(loginBody.Password))
|
|
|
|
|
{
|
|
|
|
|
return Failed<TokenInfoViewModel>("用户名或密码不能为空");
|
|
|
|
|
}
|
|
|
|
|
// 验证码校验
|
|
|
|
|
var captchaOnOff = (await _sysConfigService.QueryAsync(x => x.ConfigKey == SysConst.KEY_OFF_CAPTCHA)).FirstOrDefault();
|
|
|
|
|
if (captchaOnOff.ConfigValue == "true")
|
|
|
|
|
{
|
|
|
|
|
if (!loginBody.Code.IsNotEmptyOrNull())
|
|
|
|
|
{
|
|
|
|
|
return Failed<TokenInfoViewModel>("验证码错误");
|
|
|
|
|
}
|
|
|
|
|
var code = CookieHelper.GetCookies(HttpContext, CacheKey.Captcha);
|
|
|
|
|
if (loginBody.Code.ToLower() != code.ToLower())
|
|
|
|
|
{
|
|
|
|
|
return Failed<TokenInfoViewModel>("验证码错误");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
loginBody.Password = MD5Helper.MD5Encrypt32(loginBody.Password);
|
|
|
|
|
var user = (await _sysUserService.QueryAsync(d => d.LoginName == loginBody.LoginName && d.Password == loginBody.Password && d.DelFlag == false && d.Status == SysConst.ENABLE)).FirstOrDefault();
|
|
|
|
|
|
|
|
|
|
if (user.IsNotEmptyOrNull())
|
|
|
|
|
{
|
|
|
|
|
var userRoles = await _sysUserService.GetUserRoleNameStr(loginBody.LoginName, loginBody.Password);
|
|
|
|
|
//如果是基于用户的授权策略,这里要添加用户;如果是基于角色的授权策略,这里要添加角色
|
|
|
|
|
var claims = new List<Claim> {
|
|
|
|
|
new Claim(ClaimTypes.Name, user.LoginName.ToString()),
|
|
|
|
|
new Claim(ClaimTypes.Sid, user.UserID.ToString()),
|
|
|
|
|
new Claim(JwtRegisteredClaimNames.Jti, user.UserID.ToString()),
|
|
|
|
|
new Claim(ClaimTypes.Expiration, DateTime.Now.AddSeconds(_requirement.Expiration.TotalSeconds).ToString()) };
|
|
|
|
|
claims.AddRange(userRoles.Split(',').Select(s => new Claim(ClaimTypes.Role, s)));
|
|
|
|
|
|
|
|
|
|
var token = JwtToken.BuildJwtToken(claims.ToArray(), _requirement);
|
|
|
|
|
//记录登录信息
|
|
|
|
|
await RecordLoginInfo(user);
|
|
|
|
|
return Success(token, "获取成功");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
user = (await _sysUserService.QueryAsync(d => d.LoginName == loginBody.LoginName && d.DelFlag == false)).FirstOrDefault();
|
|
|
|
|
if (user == null)
|
|
|
|
|
{
|
|
|
|
|
return Failed<TokenInfoViewModel>("用户不存在");
|
|
|
|
|
}
|
|
|
|
|
user = (await _sysUserService.QueryAsync(d => d.LoginName == loginBody.LoginName && d.DelFlag == false && d.Status == SysConst.DISABLE)).FirstOrDefault();
|
|
|
|
|
if (user != null)
|
|
|
|
|
{
|
|
|
|
|
return Failed<TokenInfoViewModel>("用户处于禁用状态");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Failed<TokenInfoViewModel>("用户名或密码错误");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 默认使用管理员账号登录获取Token-JWT
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
[HttpGet]
|
|
|
|
|
[Route("LoginAdmin")]
|
|
|
|
|
[AllowAnonymous]
|
|
|
|
|
public async Task<MessageModel<TokenInfoViewModel>> GetJwtTokenAdmin()
|
|
|
|
|
{
|
|
|
|
|
// 是否开启测试环境
|
|
|
|
|
var isTestCurrent = Appsettings.app(new string[] { "AppSettings", "UseLoadTest" }).ObjToBool();
|
|
|
|
|
if (!isTestCurrent) return Failed<TokenInfoViewModel>("测试环境未开启");
|
|
|
|
|
string jwtStr = string.Empty;
|
|
|
|
|
//管理员账号信息
|
|
|
|
|
string loginName = "admin";
|
|
|
|
|
string password = "Password01!";
|
|
|
|
|
|
|
|
|
|
password = MD5Helper.MD5Encrypt32(password);
|
|
|
|
|
|
|
|
|
|
var user = (await _sysUserService.QueryAsync(d => d.LoginName == loginName && d.Password == password && d.DelFlag == false && d.Status == SysConst.ENABLE)).FirstOrDefault();
|
|
|
|
|
if (user.IsNotEmptyOrNull())
|
|
|
|
|
{
|
|
|
|
|
var userRoles = await _sysUserService.GetUserRoleNameStr(loginName, password);
|
|
|
|
|
//如果是基于用户的授权策略,这里要添加用户;如果是基于角色的授权策略,这里要添加角色
|
|
|
|
|
var claims = new List<Claim> {
|
|
|
|
|
new Claim(ClaimTypes.Name, user.LoginName.ToString()),
|
|
|
|
|
new Claim(ClaimTypes.Sid, user.UserID.ToString()),
|
|
|
|
|
new Claim(JwtRegisteredClaimNames.Jti, user.UserID.ToString()),
|
|
|
|
|
new Claim(ClaimTypes.Expiration, DateTime.Now.AddSeconds(_requirement.Expiration.TotalSeconds).ToString()) };
|
|
|
|
|
claims.AddRange(userRoles.Split(',').Select(s => new Claim(ClaimTypes.Role, s)));
|
|
|
|
|
|
|
|
|
|
var token = JwtToken.BuildJwtToken(claims.ToArray(), _requirement);
|
|
|
|
|
return Success(token, "获取成功");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
return Failed<TokenInfoViewModel>("认证失败");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 请求刷新Token(以旧换新)
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="token"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
[HttpGet]
|
|
|
|
|
[Route("RefreshToken")]
|
|
|
|
|
[AllowAnonymous]
|
|
|
|
|
public async Task<MessageModel<TokenInfoViewModel>> RefreshToken(string token = "")
|
|
|
|
|
{
|
|
|
|
|
string jwtStr = string.Empty;
|
|
|
|
|
|
|
|
|
|
if (string.IsNullOrEmpty(token))
|
|
|
|
|
return Failed<TokenInfoViewModel>("token无效,请重新登录!");
|
|
|
|
|
var tokenModel = JwtHelper.SerializeJwt(token);
|
|
|
|
|
if (tokenModel != null && tokenModel.Uid > 0)
|
|
|
|
|
{
|
|
|
|
|
var user = await _sysUserService.QueryByIdAsync(tokenModel.Uid);
|
|
|
|
|
if (user != null)
|
|
|
|
|
{
|
|
|
|
|
var userRoles = await _sysUserService.GetUserRoleNameStr(user.LoginName, user.Password);
|
|
|
|
|
//如果是基于用户的授权策略,这里要添加用户;如果是基于角色的授权策略,这里要添加角色
|
|
|
|
|
var claims = new List<Claim> {
|
|
|
|
|
new Claim(ClaimTypes.Name, tokenModel.Uid.ObjToString()),
|
|
|
|
|
new Claim(JwtRegisteredClaimNames.Jti, tokenModel.Uid.ObjToString()),
|
|
|
|
|
new Claim(ClaimTypes.Expiration, DateTime.Now.AddSeconds(_requirement.Expiration.TotalSeconds).ToString()) };
|
|
|
|
|
claims.AddRange(userRoles.Split(',').Select(s => new Claim(ClaimTypes.Role, s)));
|
|
|
|
|
|
|
|
|
|
//用户标识
|
|
|
|
|
var identity = new ClaimsIdentity(JwtBearerDefaults.AuthenticationScheme);
|
|
|
|
|
identity.AddClaims(claims);
|
|
|
|
|
|
|
|
|
|
var refreshToken = JwtToken.BuildJwtToken(claims.ToArray(), _requirement);
|
|
|
|
|
return Success(refreshToken, "获取成功");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return Failed<TokenInfoViewModel>("认证失败!");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取用户信息
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns> 用户信息 </returns>
|
|
|
|
|
[HttpGet]
|
|
|
|
|
[Route("GetUserInfo")]
|
|
|
|
|
public async Task<MessageModel<UserPermission>> GetUserInfo()
|
|
|
|
|
{
|
|
|
|
|
UserPermission userPermission = new UserPermission()
|
|
|
|
|
{
|
|
|
|
|
SysUser = await _sysUserService.QueryByIdAsync(CurrentUser.UserID),
|
|
|
|
|
Perms = await _sysPermissionService.GetMenuPermission(CurrentUser.UserID),
|
|
|
|
|
Roles = await _sysPermissionService.GetRolePermission(CurrentUser.UserID)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return Success(userPermission);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 获取路由信息
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <returns> 路由信息 </returns>
|
|
|
|
|
[HttpGet]
|
|
|
|
|
[Route("GetRouters")]
|
|
|
|
|
public async Task<MessageModel<List<RouterVo>>> GetRouters()
|
|
|
|
|
{
|
|
|
|
|
var menus = await _sysMenuService.SelectMenuTreeByUserId(CurrentUser.UserID);
|
|
|
|
|
return Success(_sysMenuService.BuildMenus(menus));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 生成验证码
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="_captcha"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
[HttpGet]
|
|
|
|
|
[Route("Captcha")]
|
|
|
|
|
[AllowAnonymous]
|
|
|
|
|
public async Task<FileContentResult> Captcha()
|
|
|
|
|
{
|
|
|
|
|
var code = await _captcha.GenerateRandomCaptcha();
|
|
|
|
|
|
|
|
|
|
var result = await _captcha.GenerateCaptchaImage(code);
|
|
|
|
|
// 将验证码的token放入cookie
|
|
|
|
|
CookieHelper.SetCookies(HttpContext, CacheKey.Captcha, code);
|
|
|
|
|
return File(result.CaptchaMemoryStream.ToArray(), "image/png");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 退出登录
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="token"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
[HttpPost]
|
|
|
|
|
[Route("Logout")]
|
|
|
|
|
[AllowAnonymous]
|
|
|
|
|
public MessageModel<bool> Logout(string token = "")
|
|
|
|
|
{
|
|
|
|
|
var refresh = RefreshToken(token).Result;
|
|
|
|
|
return Success(refresh.data.IsNotEmptyOrNull() && refresh.data.token.IsNotEmptyOrNull());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 用户注册
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="user"></param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
[HttpPost]
|
|
|
|
|
[Route("Register")]
|
|
|
|
|
[AllowAnonymous]
|
|
|
|
|
public async Task<MessageModel<bool>> Register([FromBody] SysUser user)
|
|
|
|
|
{
|
|
|
|
|
MessageModel<bool> model = new MessageModel<bool>();
|
|
|
|
|
if (await _sysUserService.CheckLoginNameUnique(user.LoginName))
|
|
|
|
|
{
|
|
|
|
|
model.success = false;
|
|
|
|
|
model.msg = "登录账号已存在!";
|
|
|
|
|
return model;
|
|
|
|
|
}
|
|
|
|
|
user.Password = MD5Helper.MD5Encrypt32(user.Password);
|
|
|
|
|
user.UserType = "00";
|
|
|
|
|
user.DelFlag = false;
|
|
|
|
|
user.CreateTime = DateTime.Now;
|
|
|
|
|
user.UpdateTime = DateTime.Now;
|
|
|
|
|
user.CreateBy = user.LoginName;
|
|
|
|
|
user.UpdateBy = user.LoginName;
|
|
|
|
|
user.Status = SysConst.ENABLE;
|
|
|
|
|
user.Sex = 0;
|
|
|
|
|
return Success(await _sysUserService.AddAsync(user) > 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 记录登录信息
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="user"></param>
|
|
|
|
|
[NonAction]
|
|
|
|
|
public async Task RecordLoginInfo(SysUser user)
|
|
|
|
|
{
|
|
|
|
|
user.LoginIP = IpHelper.GetIpAddr(HttpContext);
|
|
|
|
|
user.LoginDate = DateTime.Now;
|
|
|
|
|
await _sysUserService.UpdateAsync(user);
|
|
|
|
|
|
|
|
|
|
var agent = HttpContext.Request.Headers["User-Agent"].ObjToString();
|
|
|
|
|
var parser = Parser.GetDefault();
|
|
|
|
|
var info = parser.Parse(agent);
|
|
|
|
|
|
|
|
|
|
SysLoginInfo loginInfo = new SysLoginInfo()
|
|
|
|
|
{
|
|
|
|
|
UserName = user.LoginName,
|
|
|
|
|
IPAddr = user.LoginIP,
|
|
|
|
|
LoginLocation = AddressHelper.GetRealAddressByIP(user.LoginIP),
|
|
|
|
|
Browser = info.UA.Family,
|
|
|
|
|
OS = info.OS.Family,
|
|
|
|
|
Status = SysConst.SUCCESS,
|
|
|
|
|
Msg = user.UserName,
|
|
|
|
|
LoginTime = DateTime.Now
|
|
|
|
|
};
|
|
|
|
|
await _sysLoginInfoService.AddAsync(loginInfo);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|