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(); } }