using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.DependencyInjection; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; using VolPro.Core.CacheManager; using VolPro.Core.Configuration; using VolPro.Core.Controllers.Basic; using VolPro.Core.DBManager; using VolPro.Core.DbSqlSugar; using VolPro.Core.EFDbContext; using VolPro.Core.Enums; using VolPro.Core.Extensions; using VolPro.Core.Filters; using VolPro.Core.Infrastructure; using VolPro.Core.ManageUser; using VolPro.Core.ObjectActionValidator; using VolPro.Core.Services; using VolPro.Core.SignalR; using VolPro.Core.Utilities; using VolPro.Entity.AttributeManager; using VolPro.Entity.DomainModels; using VolPro.Sys.IRepositories; using VolPro.Sys.IServices; using VolPro.Sys.Repositories; using VolPro.WebApi.Controllers.Hubs; namespace VolPro.Sys.Controllers { [Route("api/User")] public partial class Sys_UserController { private ISys_UserRepository _userRepository; private ICacheService _cache; [ActivatorUtilitiesConstructor] public Sys_UserController( ISys_UserService userService, ISys_UserRepository userRepository, ICacheService cahce ) : base(userService) { _userRepository = userRepository; _cache = cahce; } [Route("GetUserNumber"), HttpPost] [AllowAnonymous] public int GetUserNumber() { return Service.GetUserNumber(); } [Route("GetUserList"), HttpPost] [AllowAnonymous] public List GetUserList() { return Service.GetUserList(); } [HttpPost, HttpGet, Route("login"), AllowAnonymous] [ObjectModelValidatorFilter(ValidatorModel.Login)] public async Task Login([FromBody] LoginInfo loginInfo) { return Json(await Service.Login(loginInfo)); } private readonly ConcurrentDictionary _lockCurrent = new ConcurrentDictionary(); [HttpPost, Route("replaceToken")] public IActionResult ReplaceToken() { WebResponseContent responseContent = new WebResponseContent(); string error = ""; string key = $"rp:Token:{UserContext.Current.UserId}"; UserInfo userInfo = null; try { //如果5秒内替换过token,直接使用最新的token(防止一个页面多个并发请求同时替换token导致token错位) if (_cache.Exists(key)) { return Json(responseContent.OK(null, _cache.Get(key))); } var _obj = _lockCurrent.GetOrAdd(UserContext.Current.UserId, new object() { }); lock (_obj) { if (_cache.Exists(key)) { return Json(responseContent.OK(null, _cache.Get(key))); } string requestToken = HttpContext.Request.Headers[AppSetting.TokenHeaderName]; requestToken = requestToken?.Replace("Bearer ", ""); if (JwtHelper.IsExp(requestToken)) return Json(responseContent.Error("Token已过期!")); int userId = UserContext.Current.UserId; userInfo = _userRepository.FindAsIQueryable(x => x.User_Id == userId).Select( s => new UserInfo() { User_Id = userId, UserName = s.UserName, UserTrueName = s.UserTrueName, Role_Id = s.Role_Id ?? 0, // RoleName = s.RoleName }).FirstOrDefault(); if (userInfo == null) return Json(responseContent.Error("未查到用户信息!")); int expir = UserContext.MenuType == 1 ? 43200 : AppSetting.ExpMinutes; string token = JwtHelper.IssueJwt(userInfo, expir); //移除当前缓存 _cache.Remove(userId.GetUserIdKey()); //只更新的token字段 _userRepository.Update(new Sys_User() { User_Id = userId, Token = token }, x => x.Token, true); //添加一个5秒缓存 _cache.Add(key, token, 5); string accessToken = null; if (AppSetting.FileAuth) { expir = expir + 30; string dt = DateTime.Now.AddMinutes(expir).ToString("yyyy-MM-dd HH:mm"); accessToken = $"{userId}_{dt}".EncryptDES(AppSetting.Secret.User); _cache.Add(accessToken, dt, expir); responseContent.OK(null, new { accessToken, token }); } else { responseContent.OK(null, token); } } } catch (Exception ex) { error = ex.Message + ex.StackTrace; responseContent.Error("token替换异常"); } finally { _lockCurrent.TryRemove(UserContext.Current.UserId, out object val); string _message = $"用户{userInfo?.User_Id}_{userInfo?.UserTrueName},({(responseContent.Status ? "token替换成功" : "token替换失败")})"; Logger.Info(LoggerType.ReplaceToeken, _message, null, error); } return Json(responseContent); } [HttpPost, Route("modifyPwd")] [ApiActionPermission] public async Task ModifyPwd([FromBody] Dictionary info) { return Json(await Service.ModifyPwd(info?["oldPwd"], info?["newPwd"])); } [HttpPost, Route("getCurrentUserInfo")] public async Task GetCurrentUserInfo() { return Json(await Service.GetCurrentUserInfo()); } //只能超级管理员才能修改密码 //2020.08.01增加修改密码功能 //[HttpPost, Route("modifyUserPwd"), ApiActionPermission(ActionRolePermission.SuperAdmin)] [HttpPost, Route("modifyUserPwd"), ApiActionPermission(ActionPermissionOptions.Add | ActionPermissionOptions.Update)] public IActionResult ModifyUserPwd([FromBody] LoginInfo loginInfo) { string userName = loginInfo?.UserName; string password = loginInfo?.Password; WebResponseContent webResponse = new WebResponseContent(); if (string.IsNullOrEmpty(password) || string.IsNullOrEmpty(userName)) { return Json(webResponse.Error("参数不完整")); } if (password.Length < 6) return Json(webResponse.Error("密码长度不能少于6位")); ISys_UserRepository repository = Sys_UserRepository.Instance; Sys_User user = repository.FindFirst(x => x.UserName == userName); if (user == null) { return Json(webResponse.Error("用户不存在")); } user.UserPwd = password.EncryptDES(AppSetting.Secret.User); repository.Update(user, x => new { x.UserPwd }, true); //如果用户在线,强制下线 UserContext.Current.LogOut(user.User_Id); if (userName != UserContext.Current.UserName) { var message = HttpContext.GetService(); message.SendMessage(new MessageChannelData() { UserName = new List() { userName }, Code = "-1", MessageNotification = new MessageNotification() { Content = "密码已被修改,即将退出登录" } }); //通知下线 message.Remove(user.UserName); } return Json(webResponse.OK("密码修改成功")); } /// /// 2020.06.15增加登陆验证码 /// /// [HttpGet, Route("getVierificationCode"), AllowAnonymous] public IActionResult GetVierificationCode() { string code = VierificationCode.RandomText(); var data = new { img = VierificationCode.CreateBase64Imgage(code), uuid = Guid.NewGuid() }; HttpContext.GetService().Set(data.uuid.ToString(), code, new TimeSpan(0, 5, 0)); return Json(data); } [ApiActionPermission()] public override IActionResult Upload(IEnumerable fileInput) { return base.Upload(fileInput); } [HttpPost, Route("updateUserInfo")] public IActionResult UpdateUserInfo([FromBody] Sys_User user) { user.User_Id = UserContext.Current.UserId; _userRepository.Update(user, x => new { x.UserTrueName, x.Gender, x.Remark, x.HeadImageUrl }, true); return Content("修改成功"); } public override ActionResult GetPageData([FromBody] PageDataOptions loadData) { PageGridData gridData = Service.GetPageData(loadData); //是否使用用户数据权限 gridData.extra = AppSetting.UserAuth; //设置用户是否在线 var message = HttpContext.GetService(); foreach (var item in gridData.rows) { item.IsOnline = message.GetOnline(item.UserName); } return JsonNormal(gridData); } [HttpPost, Route("getUserAuth"), ApiActionPermission(ActionPermissionOptions.Add | ActionPermissionOptions.Update)] public async Task GetUserAuth(int userId) { var data = await _userRepository.DbContext.Set().Where(x => x.UserId == userId && x.AuthUserIds != "") .Select(s => new { id = s.MenuId, userIds = s.AuthUserIds }) .ToListAsync(); var userIds = data.Select(s => s.userIds.Split(",")).SelectMany(x => x).Select(s => s.GetInt()).Distinct(); var users = await _userRepository.FindAsIQueryable(x => userIds.Contains(x.User_Id)) .Select(s => new { userId = s.User_Id, userName = s.UserTrueName }) .ToListAsync(); return Json(new { data, users }); } [HttpPost, Route("saveUserAuth"), ApiActionPermission(ActionPermissionOptions.Add | ActionPermissionOptions.Update)] public async Task SaveUserAuth([FromBody] List userAuths, int userId) { if (userAuths == null || userId < 0) { return Content("参数不完整"); } var query = _userRepository.DbContext.Set(); var data = await query.Where(x => x.UserId == userId).ToListAsync(); List add = new List(); List update = new List(); foreach (var item in userAuths) { var auth = data.Where(x => item.MenuId == x.MenuId).FirstOrDefault(); if (auth == null) { if (!string.IsNullOrEmpty(item.AuthUserIds)) { item.UserId = userId; add.Add(item); } } else { item.Id = auth.Id; update.Add(item); } } _userRepository.AddRange(add); _userRepository.UpdateRange(update, x => new { x.AuthUserIds }, true); UserContext.Current.RemoveUserAuthData(userId); return Content("保存成功"); } } }