package com.sandu.common.security;
|
|
import cn.hutool.json.JSONUtil;
|
import com.sandu.common.enums.ResponseStatusEnums;
|
import com.sandu.common.redis.online.OnlineUser;
|
import com.sandu.common.redis.online.OnlineUserService;
|
import com.sandu.common.security.config.SecurityProperties;
|
import com.sandu.common.security.jwt.JwtTokenProvider;
|
import com.sandu.common.util.ResponseUtil;
|
import com.sandu.common.util.SpringContextHolder;
|
import io.jsonwebtoken.ExpiredJwtException;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.security.core.AuthenticationException;
|
import org.springframework.security.web.AuthenticationEntryPoint;
|
import org.springframework.stereotype.Component;
|
import org.springframework.util.StringUtils;
|
|
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletResponse;
|
import java.io.IOException;
|
|
/**
|
* @author hupeng
|
*/
|
@Component
|
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
|
|
@Autowired
|
private JwtTokenProvider tokenProvider;
|
|
@Override
|
public void commence(HttpServletRequest request,
|
HttpServletResponse response,
|
AuthenticationException authException) throws IOException {
|
|
String token = tokenProvider.getToken(request);
|
SecurityProperties properties = SpringContextHolder.getBean(SecurityProperties.class);
|
|
if (!StringUtils.hasText(token)) {
|
writeResponse(response, ResponseUtil.error(ResponseStatusEnums.TOKEN_NONE.getCode(), ResponseStatusEnums.TOKEN_NONE.getMessage()));
|
return;
|
}
|
|
|
Throwable exception = tokenProvider.getException(token);
|
|
// jwt过期 替换新的jwt
|
if (exception instanceof ExpiredJwtException) {
|
String usernameForce = tokenProvider.getSubjectForce(token);
|
if (properties.isCacheOnline()) {
|
OnlineUserService onlineUserService = SpringContextHolder.getBean(OnlineUserService.class);
|
OnlineUser onlineUser = onlineUserService.getOne(properties.getOnlineKey() + usernameForce);
|
if (onlineUser == null || !token.equals(onlineUser.getToken())) {
|
// redis上没有 或者不是当前用户的token 返回失效
|
writeResponse(response, ResponseUtil.error(ResponseStatusEnums.TOKEN_INVALID.getCode(), ResponseStatusEnums.TOKEN_INVALID.getMessage()));
|
} else {
|
// 返回过期,携带新的token
|
String refreshToken = tokenProvider.refreshToken(token);
|
onlineUser.setToken(refreshToken);
|
onlineUserService.updateOne(onlineUser);
|
writeResponse(response, ResponseUtil.error(ResponseStatusEnums.TOKEN_EXPIRED.getCode(), ResponseStatusEnums.TOKEN_EXPIRED.getMessage(), properties.getTokenStartWith() + refreshToken));
|
}
|
} else {
|
// 返回过期,携带新的token
|
String refreshToken = properties.getTokenStartWith() + tokenProvider.refreshToken(token);
|
writeResponse(response, ResponseUtil.error(ResponseStatusEnums.TOKEN_EXPIRED.getCode(), ResponseStatusEnums.TOKEN_EXPIRED.getMessage(), null));
|
}
|
return;
|
}
|
|
// 其他jwt解析异常
|
if (exception != null) {
|
writeResponse(response, ResponseUtil.error(ResponseStatusEnums.TOKEN_INVALID.getCode(), ResponseStatusEnums.TOKEN_INVALID.getMessage()));
|
} else {
|
//jwt解析正常 看看是不是redis的问题
|
if (properties.isCacheOnline()) {
|
String usernameForce = tokenProvider.getSubjectForce(token);
|
OnlineUserService onlineUserService = SpringContextHolder.getBean(OnlineUserService.class);
|
OnlineUser onlineUser = onlineUserService.getOne(properties.getOnlineKey() + usernameForce);
|
if (onlineUser != null && !token.equals(onlineUser.getToken())) {
|
// 和服务器保存的token不一样,说明在其他地方登录
|
writeResponse(response, ResponseUtil.error(ResponseStatusEnums.SINGLE_LOGIN.getCode(), ResponseStatusEnums.SINGLE_LOGIN.getMessage()));
|
} else {
|
// 服务器没有在线用户token或者token不一致 都返回token失效
|
writeResponse(response, ResponseUtil.error(ResponseStatusEnums.TOKEN_INVALID.getCode(), ResponseStatusEnums.TOKEN_INVALID.getMessage()));
|
}
|
} else {
|
writeResponse(response, ResponseUtil.error(ResponseStatusEnums.FAIL.getCode(), "认证出错"));
|
}
|
}
|
return;
|
|
}
|
|
private void writeResponse(HttpServletResponse response, Object result) throws IOException {
|
response.setHeader("Access-Control-Allow-Origin", "*");
|
response.setHeader("Cache-Control", "no-cache");
|
response.setCharacterEncoding("UTF-8");
|
response.setContentType("application/json");
|
response.getWriter().println(JSONUtil.parse(result));
|
response.getWriter().flush();
|
response.getWriter().close();
|
}
|
|
}
|