package cn.cetc54.platform.core.config.security.jwt;
|
|
import cn.cetc54.platform.core.common.exception.LoginFailLimitException;
|
import cn.cetc54.platform.core.common.utils.ResponseUtil;
|
import cn.cetc54.platform.core.config.properties.PlatformTokenProperties;
|
import cn.hutool.core.util.StrUtil;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
import org.springframework.security.authentication.BadCredentialsException;
|
import org.springframework.security.authentication.DisabledException;
|
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
|
import org.springframework.stereotype.Component;
|
|
import javax.servlet.ServletException;
|
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletResponse;
|
import java.io.IOException;
|
import java.util.concurrent.TimeUnit;
|
|
/**
|
* @author
|
*/
|
@Slf4j
|
@Component
|
public class AuthenticationFailHandler extends SimpleUrlAuthenticationFailureHandler {
|
|
@Autowired
|
private PlatformTokenProperties tokenProperties;
|
|
@Autowired
|
private StringRedisTemplate redisTemplate;
|
|
@Override
|
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
|
|
if (e instanceof UsernameNotFoundException || e instanceof BadCredentialsException) {
|
String username = request.getParameter("username");
|
recordLoginTime(username);
|
String key = "loginTimeLimit:"+username;
|
String value = redisTemplate.opsForValue().get(key);
|
if(StrUtil.isBlank(value)){
|
value = "0";
|
}
|
//获取已登录错误次数
|
int loginFailTime = Integer.parseInt(value);
|
int restLoginTime = tokenProperties.getLoginTimeLimit() - loginFailTime;
|
log.info("用户"+username+"登录失败,还有"+restLoginTime+"次机会");
|
if(restLoginTime<=3&&restLoginTime>0){
|
ResponseUtil.out(response, ResponseUtil.resultMap(false,500,"用户名或密码错误,还有"+restLoginTime+"次尝试机会"));
|
} else if(restLoginTime<=0) {
|
ResponseUtil.out(response, ResponseUtil.resultMap(false,500,"登录错误次数超过限制,请"+tokenProperties.getLoginAfterTime()+"分钟后再试"));
|
} else {
|
ResponseUtil.out(response, ResponseUtil.resultMap(false,500,"用户名或密码错误"));
|
}
|
} else if (e instanceof DisabledException) {
|
ResponseUtil.out(response, ResponseUtil.resultMap(false,500,"账户被禁用,请联系管理员"));
|
} else if (e instanceof LoginFailLimitException){
|
ResponseUtil.out(response, ResponseUtil.resultMap(false,500,((LoginFailLimitException) e).getMsg()));
|
} else {
|
ResponseUtil.out(response, ResponseUtil.resultMap(false,500,"登录失败,其他内部错误"));
|
}
|
}
|
|
/**
|
* 判断用户登陆错误次数
|
*/
|
public boolean recordLoginTime(String username){
|
|
String key = "loginTimeLimit:"+username;
|
String flagKey = "loginFailFlag:"+username;
|
String value = redisTemplate.opsForValue().get(key);
|
if(StrUtil.isBlank(value)){
|
value = "0";
|
}
|
// 获取已登录错误次数
|
Integer loginFailTime = Integer.parseInt(value) + 1;
|
redisTemplate.opsForValue().set(key, String.valueOf(loginFailTime), tokenProperties.getLoginAfterTime(), TimeUnit.MINUTES);
|
if(loginFailTime>=tokenProperties.getLoginTimeLimit()){
|
redisTemplate.opsForValue().set(flagKey, "fail", tokenProperties.getLoginAfterTime(), TimeUnit.MINUTES);
|
return false;
|
}
|
return true;
|
}
|
}
|