whycxzp
2022-03-16 02c1a11bb26a262ff9269b5e2e626fb1acfab97b
账号登录各种校验,信息传递
6个文件已修改
1个文件已添加
247 ■■■■■ 已修改文件
src/main/java/com/whyc/constant/UserConstant.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/mapper/PermitGroupUserMapper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/pojo/UserInf.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/service/LoginService.java 161 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/service/PermitGroupUserService.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/service/UserService.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/PermitGroupUserMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/whyc/constant/UserConstant.java
New file
@@ -0,0 +1,40 @@
package com.whyc.constant;
/**
 * 用户常量
 */
public enum UserConstant {
    ACCOUNT_TYPE_NORMAL("账号类型-长期",1),
    ACCOUNT_TYPE_TEMP("账号类型-临时",2),
    ACCOUNT_STATUS_ACTIVE("账号状态-激活",1),
    ACCOUNT_STATUS_HIBERNATE("账号状态-休眠",2),
    ACCOUNT_STATUS_LOCK("账号状态-锁定",3),
    ACCOUNT_STATUS_LOCK_FAIL("账号状态-锁定-连续失败",4),
    ACCOUNT_STATUS_CANCEL("账号状态-注销",0),
    ;
    private String label;
    private Integer value;
    UserConstant(String label, Integer value) {
        this.label = label;
        this.value = value;
    }
    public String getLabel() {
        return label;
    }
    public void setLabel(String label) {
        this.label = label;
    }
    public Integer getValue() {
        return value;
    }
    public void setValue(Integer value) {
        this.value = value;
    }
}
src/main/java/com/whyc/mapper/PermitGroupUserMapper.java
@@ -11,4 +11,6 @@
    List<UserInf> getUserInf(Integer permitGroupId);
    List<String> getItemList(Long uId);
}
src/main/java/com/whyc/pojo/UserInf.java
@@ -112,6 +112,14 @@
     */
    private int uRole;
    private Integer status;
    private Date expirationTime;
    private Date lastLoginTime;
    private Date passwordUpdateTime;
    private Date createTime;
    private Date lockTime;
    private String visitIp;
    private String visitTime;
    public UserInf() {
    }
src/main/java/com/whyc/service/LoginService.java
@@ -1,6 +1,14 @@
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.YamlProperties;
import com.whyc.dto.Response;
import com.whyc.mapper.PageParamMapper;
import com.whyc.mapper.PermitGroupUserMapper;
import com.whyc.mapper.UserMapper;
import com.whyc.pojo.PageParam;
import com.whyc.pojo.UserClient;
import com.whyc.pojo.UserInf;
import com.whyc.util.ActionUtil;
@@ -10,14 +18,28 @@
import org.apache.shiro.subject.Subject;
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.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Map;
import java.util.*;
@Service
public class LoginService {
    @Resource
    private UserMapper userMapper;
    @Resource
    private UserService userService;
    @Resource
    private PermitGroupUserService permitGroupUserService;
    @Resource
    private PageParamMapper pageParamMapper;
    public Response login(String userName, String password, HttpServletRequest request) {
        UsernamePasswordToken userToken = new UsernamePasswordToken(userName, password);
@@ -74,14 +96,16 @@
        }
        return new Response<>().set(1,false,"密码错误");
    }
    public Response loginByRSA(String userName, String pwd,String deliveredCode, HttpServletRequest request) {
        Response<Object> response = new Response<>();
        deliveredCode = deliveredCode.toUpperCase();
        String fontDynamicCode = (String) ActionUtil.getSession().getAttribute("fontDynamicCode");
        if (fontDynamicCode==null||"".equals(fontDynamicCode)){
            return new Response().set(1,false,"请刷新验证码");
            return response.set(1,false,"请刷新验证码");
        }
        if (!deliveredCode.equals(fontDynamicCode.toUpperCase())){
            return new Response().set(1,false,"验证码错误");
            return response.set(1,false,"验证码错误");
        }
        //验证正确,清除验证码
        ActionUtil.getSession().removeAttribute("fontDynamicCode");
@@ -94,7 +118,7 @@
        String[] dataArr = RSAUtil.decryptFront(password, RSAUtil.fontSeparator);
        //验签md5
        if(!dataArr[1].equals(ActionUtil.EncryptionMD5(org.apache.commons.lang3.StringUtils.trim(dataArr[0])).toString())){
            return new Response<>().set(0,"密码验签失败");
            return response.set(1,false,"密码验签失败");
        }
        UsernamePasswordToken userToken = new UsernamePasswordToken(userName, dataArr[0]);
        Subject subject = SecurityUtils.getSubject();
@@ -103,17 +127,136 @@
        }catch (Exception e){
            String message = e.getMessage();
            if(message.contains("did not match the expected credentials")){
                return new Response<>().set(1,false,"密码错误");
                return response.set(1,false,"密码错误");
            }
            return new Response<>().set(1,false,message);
            return response.set(1,false,message);
        }
        ServletContext servletContext = request.getServletContext();
        Enumeration<String> attributeNames = servletContext.getAttributeNames();
        QueryWrapper<UserInf> queryWrapper = Wrappers.query();
        queryWrapper.select("uId","status","visit_ip","visit_time","password_update_time","last_login_time").eq("uName",userName);
        UserInf userInf = userMapper.selectOne(queryWrapper);
        if (subject.isAuthenticated()){
            //每个登录的用户都有一个全局变量,里面存着对应的SessionId;
            //同一个账号,后面登录的,会挤掉之前登录的SessionId,这个todo,做限制账号同时登陆人数为1
            request.getServletContext().setAttribute(userName,request.getSession().getId());
            //Session存储当前用户
            //查询账号状态
            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("首次登录,请先修改初始化口令");
                    return response;
                }
                else if(passwordUpdateTime.compareTo(now.getTime()) < 0){
                    response.setCode(2);
                    response.setData(false);
                    response.setMsg("超过3个月没有修改口令,请修改口令后重新登录");
                    return response;
                }
            }
            //登录成功
            servletContext.setAttribute(userName,request.getSession().getId());
            //Session存储当前用户及权限组列表
            request.getSession().setAttribute("user",subject.getPrincipal());
            return new Response<>().setII(1,true,subject.getPrincipal(),"登录成功");
            request.getSession().setAttribute("permits",ActionUtil.getGson().toJson(permitGroupUserService.getItemList(userInf.getUId())));
            //清除账号登录失败记录
            while (attributeNames.hasMoreElements()){
                String attributeName = attributeNames.nextElement();
                if(attributeName.contains(userName +"_login_fail_times_")){
                    servletContext.removeAttribute(attributeName);
                }
            }
            //回写登录时间到数据库
            userService.updateLoginTime(userInf.getUId());
            //查询用户对应的权限组id并返回给前端
            LinkedList<Object> dataList = new LinkedList<>();
            dataList.add(subject.getPrincipal());
            int permitGroupId = permitGroupUserService.getPermitGroupId(userInf.getUId());
            dataList.add(permitGroupId);
            return new Response<>().setII(1,true,dataList,"登录成功");
        }
        //密码错误,记录次数
        //内存中查找该用户中的登录失败次数
        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.getUId());
            //清除登录错误次数统计
            loginFailAttributeList.forEach(servletContext::removeAttribute);
        }else {
            servletContext.setAttribute(userName + "_login_fail_times_"+System.currentTimeMillis(), 0);
        }
        return new Response<>().set(1,false,"密码错误");
    }
src/main/java/com/whyc/service/PermitGroupUserService.java
@@ -1,5 +1,7 @@
package com.whyc.service;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.whyc.mapper.PermitGroupUserMapper;
@@ -42,4 +44,14 @@
            mapper.delete(wrapper);
        }
    }
    public int getPermitGroupId(Long uId) {
        QueryWrapper<PermitGroupUser> wrapper = Wrappers.query();
        wrapper.select("permit_group_id").eq("uId",uId).last(" limit 1");
        return mapper.selectOne(wrapper).getPermitGroupId();
    }
    public List<String> getItemList(Long uId) {
        return mapper.getItemList(uId);
    }
}
src/main/java/com/whyc/service/UserService.java
@@ -5,6 +5,7 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.whyc.constant.UserConstant;
import com.whyc.dto.Response;
import com.whyc.mapper.UserMapper;
import com.whyc.pojo.UserClient;
@@ -200,4 +201,20 @@
        userMapper.update(null,updateWrapper);
        return new Response().set(1,true,"密码修改成功");
    }
    /**锁定账号*/
    public void lock(Long uId) {
        UpdateWrapper<UserInf> wrapper = Wrappers.update();
        wrapper.set("status", UserConstant.ACCOUNT_STATUS_LOCK_FAIL.getValue()).eq("uId",uId);
        userMapper.update(null,wrapper);
    }
    /**更新登录时间*/
    public void updateLoginTime(Long uId) {
        UpdateWrapper<UserInf> wrapper = Wrappers.update();
        wrapper.set("last_login_time", new Date()).eq("uId",uId);
        userMapper.update(null,wrapper);
    }
}
src/main/resources/mapper/PermitGroupUserMapper.xml
@@ -15,4 +15,11 @@
        where u.uId = d.uId
        and d.permit_group_id = #{permitGroupId}
    </select>
    <select id="getItemList" resultType="java.lang.String">
        select  tb_user_permitgroup.permit_item_name
        from db_user.tb_user_permitgroup,db_user.tb_user_permitgroup_data
        where tb_user_permitgroup.permit_group_id=tb_user_permitgroup_data.permit_group_id
        and tb_user_permitgroup_data.uId=#{uId}
        and tb_user_permitgroup.permit_item_value=1
    </select>
</mapper>