Browse Source

账号安全相关

chenyongxing 6 years ago
parent
commit
1057bf8c15

+ 39 - 16
server/svr-authentication/src/main/java/com/yihu/jw/security/core/userdetails/jdbc/WlyyUserDetailsService.java

@ -6,6 +6,7 @@ import com.yihu.jw.security.model.WlyyUserSimple;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;
@ -20,6 +21,7 @@ import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.sql.DataSource;
import java.sql.Timestamp;
import java.util.*;
import java.util.concurrent.TimeUnit;
@ -39,6 +41,12 @@ public class WlyyUserDetailsService extends JdbcDaoSupport implements UserDetail
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Value("${user.autoUnlockTime}")
    private Integer autoUnlockTime;//自动解锁时间 以分钟计算
    @Value("${user.reflashFailedCountTime}")
    private Integer reflashFailedCountTime;//将失败次数重置为0 ,以分钟计算
    @Value("${user.tryLoginTimes}")
    private Integer tryLoginTimes;//失败重试次数
    public WlyyUserDetailsService(DataSource dataSource) {
        this.setDataSource(dataSource);
@ -60,7 +68,7 @@ public class WlyyUserDetailsService extends JdbcDaoSupport implements UserDetail
        }
        if (users.get(0).isLocked()) {
            Date date = users.get(0).getLockedDate();
            if (new Date().after(DateUtils.addMinutes(date, 5))) {
            if (new Date().after(DateUtils.addMinutes(date, autoUnlockTime))) {
                //解除锁定
                unlocked(username);
                users.get(0).setLocked(false);
@ -137,33 +145,48 @@ public class WlyyUserDetailsService extends JdbcDaoSupport implements UserDetail
        //获取失败次数
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String username = request.getParameter("username");
        Integer loginFailureCount = getLoginFailureCount(username);
        Map<String,Object> map = getLoginFailureCount(username);
        Integer loginFailureCount = Integer.valueOf(map.get("login_failure_count").toString());
        Object timeObj = map.get("last_login_failure_time");
        if(timeObj == null){
            loginFailureCount = 0;
        }else{
            Timestamp timestamp = (Timestamp) timeObj;
            //判断是否得重置登陆次数
            Date date = new Date(timestamp.getTime());
            if (new Date().after(DateUtils.addMinutes(date, reflashFailedCountTime))) {
                //重置登陆次数
                loginFailureCount = 0;
            }
        }
        loginFailureCount ++;
        if (loginFailureCount >= 5) {
        if (loginFailureCount >= tryLoginTimes) {
            locked(username);
            return "账号已被锁定,请5分钟后重试!";
            return "账号已被锁定,请"+autoUnlockTime+"分钟后重试!";
        } else {
            addFailureCount(username,loginFailureCount);
            return "账号或密码错误,还可以再试" + (5 - loginFailureCount) + "次!";
            return "账号或密码错误,还可以再试" + (tryLoginTimes - loginFailureCount) + "次!";
        }
    }
    /**
     * 获取失败次数
     * 获取失败次数 返回 map  key1: login_failure_count   失败次数
     *                       key2: last_login_failure_time 上次登录失败时间 /可能为null
     *
     * @param username
     * @return
     */
    public Integer getLoginFailureCount(String username){
    public Map<String, Object> getLoginFailureCount(String username){
        Map<String, Object> result = new HashMap<>();
        String loginType = getLogintype();
        Integer loginFailureCount = 0;
        if(StringUtils.isBlank(loginType)||"1".equals(loginType)){ //1或默认查找user表,为平台管理员账号
            loginFailureCount = this.getJdbcTemplate().queryForObject("select u.login_failure_count from base_user u where u.username = ? or u.mobile = ? or u.idcard = ?", Integer.class, username, username, username);
            result = this.getJdbcTemplate().queryForMap("select u.login_failure_count,u.last_login_failure_time from base_user u where u.username = ? or u.mobile = ? or u.idcard = ?", username, username, username);
        }else if("2".equals(loginType)){//2.为医生账号
            loginFailureCount = this.getJdbcTemplate().queryForObject("select d.login_failure_count from base_doctor d where d.mobile = ? or d.idcard = ?", Integer.class, username, username);
            result = this.getJdbcTemplate().queryForMap("select d.login_failure_count,d.last_login_failure_time from base_doctor d where d.mobile = ? or d.idcard = ?", username, username);
        }else if("3".equals(loginType)){ //3.患者账号
            loginFailureCount = this.getJdbcTemplate().queryForObject("select p.login_failure_count from base_patient p where p.mobile = ? or p.idcard = ?", Integer.class, username, username);
        } //...
        return loginFailureCount;
            result = this.getJdbcTemplate().queryForMap("select p.login_failure_count,p.last_login_failure_time from base_patient p where p.mobile = ? or p.idcard = ?",username, username);
        }
        return result;
    }
    /**
@ -193,13 +216,13 @@ public class WlyyUserDetailsService extends JdbcDaoSupport implements UserDetail
        String loginType = getLogintype();
        if(StringUtils.isBlank(loginType)||"1".equals(loginType)){ //1或默认查找user表,为平台管理员账号
            //更新失败次数
            this.getJdbcTemplate().update("update base_user u set u.login_failure_count = ? where u.username = ? or u.mobile = ? or u.idcard = ?", loginFailureCount, username, username, username);
            this.getJdbcTemplate().update("update base_user u set u.login_failure_count = ? ,u.last_login_failure_time = ? where u.username = ? or u.mobile = ? or u.idcard = ?", loginFailureCount,new Date(), username, username, username);
        }else if("2".equals(loginType)){//2.为医生账号
            //更新失败次数
            this.getJdbcTemplate().update("update base_doctor d set d.login_failure_count = ? where d.mobile = ? or d.idcard = ?", loginFailureCount, username, username);
            this.getJdbcTemplate().update("update base_doctor d set d.login_failure_count = ?, d.last_login_failure_time = ?  where d.mobile = ? or d.idcard = ?", loginFailureCount,new Date(), username, username);
        }else if("3".equals(loginType)){ //3.患者账号
            //更新失败次数
            this.getJdbcTemplate().update("update base_patient p set p.login_failure_count = ? where p.mobile = ? or p.idcard = ?", loginFailureCount, username, username);
            this.getJdbcTemplate().update("update base_patient p set p.login_failure_count = ? ,p.last_login_failure_time = ? where p.mobile = ? or p.idcard = ?", loginFailureCount,new Date(),username, username);
        } //...
    }

+ 4 - 0
server/svr-authentication/src/main/java/com/yihu/jw/security/oauth2/provider/endpoint/WlyyLoginEndpoint.java

@ -164,6 +164,10 @@ public class WlyyLoginEndpoint extends AbstractEndpoint {
        if(!StringUtils.isEmpty(openid) && !"undefined".equalsIgnoreCase(openid) && "3".equalsIgnoreCase(loginType)){
            userDetailsService.updateOpenId(openid,wlyyUserSimple.getId());
        }
        if (parameters.get("password") != null) {
            //使用密码登录成功后, 更新失败次数为 0
            userDetailsService.addFailureCount(username,0);
        }
        userDetailsService.setRolePhth(loginType,token,wlyyUserSimple.getId(),redisTemplate);
        return getResponse(wlyyUserSimple);
    }

+ 5 - 0
server/svr-authentication/src/main/resources/application.yml

@ -17,6 +17,11 @@ spring:
      max-idle: 8 # Max number of "idle" connections in the pool. Use a negative value to indicate an unlimited number of idle connections.
      max-wait: -1 # Maximum amount of time (in milliseconds) a connection allocation should block before throwing an exception when the pool is exhausted. Use a negative value to block indefinitely.
      min-idle: 1 # Target for the minimum number of idle connections to maintain in the pool. This settings only has an effect if it is positive.
user:
  autoUnlockTime: 5  #账户锁定后,自动解锁时间  以分钟计算
  reflashFailedCountTime: 5 #将失败次数重置为0
  tryLoginTimes: 5 #失败重试次数
#logging:
#  level: