package com.whyc.service;
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.whyc.constant.UserConstant;
|
import com.whyc.constant.UserLogTypeEnum;
|
import com.whyc.constant.YamlProperties;
|
import com.whyc.dto.Response;
|
import com.whyc.dto.UserClient;
|
import com.whyc.mapper.PageParamMapper;
|
import com.whyc.mapper.UserMapper;
|
import com.whyc.pojo.db_app_sys.PageParam;
|
import com.whyc.pojo.db_user.Permitgroup;
|
import com.whyc.pojo.db_user.PermitgroupUsr;
|
import com.whyc.pojo.db_user.User;
|
import com.whyc.util.*;
|
import org.apache.shiro.SecurityUtils;
|
import org.apache.shiro.authc.AuthenticationException;
|
import org.apache.shiro.authc.UsernamePasswordToken;
|
import org.apache.shiro.subject.Subject;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
|
import javax.annotation.Resource;
|
import javax.servlet.ServletContext;
|
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpSession;
|
import java.util.*;
|
|
@Service
|
public class LoginService {
|
|
@Resource
|
private UserMapper userMapper;
|
|
@Resource
|
private PageParamMapper pageParamMapper;
|
|
@Resource
|
private UserService userService;
|
|
@Resource
|
private PermitGroupUserService permitGroupUserService;
|
|
@Resource
|
private PermitGroupService permitGroupService;
|
|
@Autowired
|
private BaojigroupService bjService;
|
|
public Response loginByRSA(String userName, String pwd, String deliveredCode, HttpServletRequest request, Integer validCode) {
|
Response<Object> response = new Response<>();
|
//默认赋值0
|
response.setData3(0);
|
//Locale.setDefault(Locale.ENGLISH);
|
deliveredCode = deliveredCode.toUpperCase(Locale.ENGLISH);
|
if(validCode ==null ) { //属性不存在,则进行验证码校验;属性存在,则不进行验证码校验
|
if (YamlProperties.fontDynamicCodeSwitch.toLowerCase(Locale.ENGLISH).equals("true")) {
|
String fontDynamicCode = (String) ActionUtil.getSession().getAttribute("fontDynamicCode");
|
if (fontDynamicCode == null || "".equals(fontDynamicCode)) {
|
return response.set(1, false, "请刷新验证码");
|
}
|
if (!deliveredCode.equals(fontDynamicCode.toUpperCase(Locale.ENGLISH))) {
|
return response.set(1, false, "验证码错误");
|
}
|
}
|
}
|
//验证正确,清除验证码
|
ActionUtil.getSession().removeAttribute("fontDynamicCode");
|
|
String[] dataArr = RSAUtil.decryptFrontP(pwd, RSAUtil.fontSeparator);
|
//验签md5
|
if (!dataArr[1].equals(ActionUtil.EncryptionMD5(org.apache.commons.lang3.StringUtils.trim(dataArr[0])).toString())) {
|
return response.set(1, false, "密码验签失败");
|
}
|
UsernamePasswordToken userToken = new UsernamePasswordToken(userName, dataArr[0]);
|
Subject subject = SecurityUtils.getSubject();
|
|
ServletContext servletContext = request.getServletContext();
|
Enumeration<String> attributeNames = servletContext.getAttributeNames();
|
|
QueryWrapper<User> queryWrapper = Wrappers.query();
|
queryWrapper.select("id","role","status", "visit_ip", "visit_time", "password_update_time", "last_login_time").eq("name", userName);
|
User userInf = userMapper.selectOne(queryWrapper);
|
//每个登录的用户都有一个全局变量,里面存着对应的SessionId;
|
//同一个账号,后面登录的,会挤掉之前登录的SessionId,这个todo,做限制账号同时登陆人数为1
|
|
//查询账号状态
|
if(userInf == null){
|
return response.set(1,false,"账号或密码错误");
|
}
|
if (userInf.getStatus() != 1) {
|
switch (userInf.getStatus()) {
|
case 0:
|
response.setMsg("当前账号的状态异常,无法登录. 异常信息为" + ": " + UserConstant.ACCOUNT_STATUS_CANCEL.getLabel());
|
break;
|
case 2:
|
response.setMsg("当前账号的状态异常,无法登录. 异常信息为" + ": " + UserConstant.ACCOUNT_STATUS_HIBERNATE.getLabel());
|
break;
|
case 3:
|
response.setMsg("当前账号的状态异常,无法登录. 异常信息为" + ": " + UserConstant.ACCOUNT_STATUS_LOCK.getLabel());
|
break;
|
case 4:
|
response.setMsg("当前账号的状态异常,无法登录. 异常信息为" + ": " + UserConstant.ACCOUNT_STATUS_LOCK_FAIL.getLabel());
|
break;
|
default:
|
response.setMsg("当前账号的状态异常,无法登录. 异常信息为:无" );
|
}
|
return response.set(1, false);
|
}
|
|
//严格标准下的规则校验
|
if (YamlProperties.systemType == 2) {
|
//登录之前,首先校验允许时间和登录ip
|
boolean ipPass = true;
|
|
String firstTime = userInf.getVisitTime().split("~")[0];
|
String lastTime = userInf.getVisitTime().split("~")[1];
|
|
List<String> ipRules = new LinkedList<>();
|
String ipRuleStr = userInf.getVisitIp();
|
ipRules = Arrays.asList(ipRuleStr.split(","));
|
|
Calendar instance = Calendar.getInstance();
|
String hourOfDay = String.format("%1$02d", instance.get(Calendar.HOUR_OF_DAY));
|
int minute = instance.get(Calendar.MINUTE);
|
int second = instance.get(Calendar.SECOND);
|
String nowTime = hourOfDay + ":" + minute + ":" + second;
|
//登录时间校验
|
if (nowTime.compareTo(firstTime) >= 0 && nowTime.compareTo(lastTime) <= 0) {
|
//登录ip校验
|
String clientIp = ActionUtil.getRequest().getRemoteAddr();
|
if (!ipRules.contains("*")) {
|
for (String ipRule : ipRules) {
|
ipPass = true;
|
//ip规则格式为 * 或者 xxx.xxx.x.x
|
String[] ipArr = clientIp.split("\\.");
|
String[] ipRuleArr = ipRule.split("\\.");
|
for (int i = 0; i < ipRuleArr.length; i++) {
|
if (!ipRuleArr[i].equals("*") && !ipRuleArr[i].equals(ipArr[i])) {
|
ipPass = false;
|
break;
|
}
|
}
|
if (ipPass) {
|
break;
|
}
|
}
|
}
|
if (!ipPass) {
|
return response.set(1, false, "您的IP禁止访问,请知晓");
|
}
|
} else {
|
return response.set(1, false,"登录时间不在允许的时间范围内");
|
}
|
//首次登录,密码修改;超过3个月未修改密码,强制修改密码
|
Date passwordUpdateTime = userInf.getPasswordUpdateTime();
|
Calendar now = Calendar.getInstance();
|
now.add(Calendar.MONTH, -3);
|
if (passwordUpdateTime == null) { //密码修改时间为空,尚未修改初始口令
|
/*response.setCode(3);
|
response.setData(false);
|
response.setMsg(MessageUtils.getMessage("FirstLoginModify"));
|
return response;*/
|
response.setData3(2);
|
} else if (passwordUpdateTime.compareTo(now.getTime()) < 0) {
|
/*response.setCode(2);
|
response.setData(false);
|
response.setMsg(MessageUtils.getMessage("ThreeMonthModify"));
|
return response;*/
|
response.setData3(3);
|
}
|
}
|
|
try {
|
subject.login(userToken);
|
} catch (Exception e) {
|
String message = e.getMessage();
|
if (message.contains("did not match the expected credentials")) {
|
//密码错误,记录次数
|
//内存中查找该用户中的登录失败次数
|
int loginFailTimes = 0;
|
List<String> loginFailAttributeList = new LinkedList<>();
|
while (attributeNames.hasMoreElements()){
|
String attributeName = attributeNames.nextElement();
|
if(attributeName.contains(userName+"_login_fail_times_")){
|
loginFailTimes++;
|
loginFailAttributeList.add(attributeName);
|
}
|
}
|
//查询账号密码错误限制次数
|
PageParam loginFailTimesLimit = pageParamMapper.findByCategoryId(9).get(0);
|
if ((++loginFailTimes) == loginFailTimesLimit.getStatus()) {
|
//达到限制次数,锁定账号
|
userService.lock(userInf.getId());
|
//清除登录错误次数统计
|
loginFailAttributeList.forEach(servletContext::removeAttribute);
|
} else {
|
servletContext.setAttribute(userName + "_login_fail_times_" + System.currentTimeMillis(), 0);
|
}
|
CommonUtil.record( UserLogTypeEnum.CATEGORY_SYSTEM.getType(), UserLogTypeEnum.LOGIN_FAIL.getType(),UserLogTypeEnum.LOGIN_FAIL.getName(), UserLogTypeEnum.LOGIN_FAIL.getName());
|
return response.set(1, false, "账号或密码错误");
|
}else if(e instanceof AuthenticationException){
|
return response.set(1, false, "密码解析失败");
|
}
|
return response.set(1, false, message);
|
}
|
|
if (subject.isAuthenticated()) {
|
//验证密码时效性
|
int flag=userService.checkPasswordValidity(userInf);
|
if(flag==-1){
|
return response.set(1, false, "密码长期未修改已失效,请修改密码");
|
}
|
//登录成功
|
servletContext.setAttribute(userName, request.getSession().getId());
|
//日登录用户统计
|
HashMap<String, String> loginMap = (HashMap<String, String>) servletContext.getAttribute("login");
|
if(loginMap == null){
|
loginMap = new HashMap<>();
|
servletContext.setAttribute("login", loginMap);
|
}
|
String dateStr = DateUtil.YYYY_MM_DD.format(new Date());
|
loginMap.put(userName, dateStr);
|
/*//累计访问人次
|
pageParam2Service.updateVisitCount();*/
|
//Session存储当前用户及权限组列表
|
request.getSession().setAttribute("user", subject.getPrincipal());
|
request.getSession().setMaxInactiveInterval(60*30);
|
request.getSession().setAttribute("permits", ActionUtil.getGson().toJson(permitGroupUserService.getItemList(userInf.getId())));
|
//清除账号登录失败记录
|
while (attributeNames.hasMoreElements()) {
|
String attributeName = attributeNames.nextElement();
|
if (attributeName.contains(userName + "_login_fail_times_")) {
|
servletContext.removeAttribute(attributeName);
|
}
|
}
|
//回写登录时间到数据库
|
userService.updateLoginTime(userInf.getId());
|
//查询用户对应的权限组id并返回给前端
|
LinkedList<Object> dataList = new LinkedList<>();
|
dataList.add(userInf);
|
PermitgroupUsr permitGroup = permitGroupUserService.getPermitGroup(userInf.getId());
|
if(permitGroup == null){
|
return response.set(1, false, "当前用户没有对应的权限组,登录失败");
|
}else {
|
int permitGroupId = permitGroup.getPermitGroupId();
|
//查询权限组信息
|
List<Permitgroup> permitgroupList=permitGroupService.getPermitGroup(permitGroupId);
|
dataList.add(permitgroupList);
|
}
|
//查询用户对应的班组标识
|
dataList.add(bjService.getGroupFlag(userInf.getId().intValue()));
|
CommonUtil.record( UserLogTypeEnum.CATEGORY_SYSTEM.getType(), UserLogTypeEnum.LOGIN.getType(),UserLogTypeEnum.LOGIN.getName(), UserLogTypeEnum.LOGIN.getName());
|
return response.setII(1, true, dataList, "登录成功");
|
}
|
return response.set(1, false,"认证未通过");
|
}
|
|
|
|
|
//登录检测
|
public Response checkUserWebSocket(HttpSession httpSession){
|
Response model = new Response();
|
try {
|
User user = (User) httpSession.getAttribute("user");
|
if(user!=null){
|
String sessionId = (String) httpSession.getServletContext().getAttribute(user.getName());
|
if(httpSession.getId().equals(sessionId)){
|
model.set(1,user,null);
|
}else{
|
if(sessionId.equals("123456")){
|
model.set(1,false,"身份权限变更,请重新登录");
|
}else{
|
model.set(1,false,"不同主机登录");
|
}
|
//用户在其他主机登录,强迫用户在本机的session失效
|
httpSession.invalidate();
|
}
|
}
|
else {
|
model.set(1,false,"用户信息失效,请重新登录");
|
}
|
}catch (Exception e){
|
model.set(1,false,"登录信息失效,重新登录");
|
}
|
return model;
|
}
|
|
public void logout() {
|
Subject subject = SecurityUtils.getSubject();
|
subject.logout();
|
}
|
|
}
|