package com.ruoyi.errand.interceptor;
|
|
|
|
import com.ruoyi.common.exception.ServiceException;
|
import com.ruoyi.errand.constant.AppUserStatusConstant;
|
import com.ruoyi.errand.constant.DelFlagConstant;
|
import com.ruoyi.errand.domain.AppUser;
|
import com.ruoyi.errand.mapper.AppUserMapper;
|
import com.ruoyi.errand.utils.JwtUtil;
|
import com.ruoyi.errand.utils.TokenBlacklistService;
|
import com.ruoyi.errand.utils.WeAppAuthenticationToken;
|
import com.ruoyi.errand.utils.WeAppSecurityProperties;
|
import io.jsonwebtoken.Claims;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.http.HttpStatus;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.stereotype.Component;
|
import org.springframework.util.AntPathMatcher;
|
import org.springframework.util.PathMatcher;
|
import org.springframework.web.filter.OncePerRequestFilter;
|
|
import javax.servlet.FilterChain;
|
import javax.servlet.ServletException;
|
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletResponse;
|
import java.io.IOException;
|
import java.util.Objects;
|
|
/**
|
* jwt令牌校验的拦截器
|
*/
|
@Component
|
@Slf4j
|
public class APPJwtTokenInterceptor extends OncePerRequestFilter {
|
|
@Autowired
|
private WeAppSecurityProperties weAppSecurityProperties;
|
@Autowired
|
private TokenBlacklistService tokenBlacklistService;
|
|
|
|
@Autowired
|
private AppUserMapper appUserMapper;
|
private static final PathMatcher pathMatcher = new AntPathMatcher();
|
@Override
|
protected void doFilterInternal(HttpServletRequest request,
|
HttpServletResponse response,
|
FilterChain chain) throws IOException, ServletException {
|
try {
|
String path = request.getRequestURI();
|
log.info("进入appJwt认证");
|
// 检查是否在白名单中
|
if (isExcludedPath(path)) {
|
chain.doFilter(request, response);
|
return;
|
}
|
//不是app开头的也不用校验
|
if (!path.startsWith("/app")) {
|
chain.doFilter(request, response);
|
return;
|
}
|
|
|
// 从Header提取Token(如:Authorization: WeApp {token})
|
String token = request.getHeader("Authorization");
|
if (token == null || !token.startsWith("app:")) {
|
throw new ServiceException("无效token", 401);
|
}
|
//解析token 获取userid,再查询到AppUser
|
String realToken = token.substring(4);
|
//查看是否在黑名单中
|
if (tokenBlacklistService.isBlacklisted(realToken)) {
|
throw new ServiceException("无效token", 401);
|
}
|
try {
|
|
Claims claims = JwtUtil.parseJWT(realToken);
|
String userId = claims.get("userId").toString();
|
AppUser appUser = appUserMapper.selectById(userId);
|
if (appUser == null || appUser.getDelFlag().equals(DelFlagConstant.DELETE)) {
|
throw new ServiceException("用户不存在", 401);
|
}
|
if (Objects.equals(appUser.getStatus(), AppUserStatusConstant.FREEZE)) {
|
throw new ServiceException("该账户已被冻结", 401);
|
}
|
if (Objects.equals(appUser.getStatus(), AppUserStatusConstant.LOGOUT)) {
|
throw new ServiceException("该账户已被注销", 401);
|
}
|
// 将userId存入SecurityContext(需自定义Authentication对象)
|
WeAppAuthenticationToken authentication =
|
new WeAppAuthenticationToken(appUser, token);
|
SecurityContextHolder.getContext().setAuthentication(authentication);
|
chain.doFilter(request, response);
|
} catch (Exception e) {
|
throw new ServiceException("TOKEN解析失败", 401);
|
}
|
}catch (ServiceException e) {
|
response.setStatus(e.getCode() != null ? e.getCode() : 401);
|
response.setContentType("application/json;charset=UTF-8");
|
response.getWriter().write(
|
String.format("{\"code\":%d,\"msg\":\"%s\"}",
|
e.getCode(), e.getMessage())
|
);
|
return;
|
}catch (Exception e) {
|
response.setStatus(401);
|
response.setContentType("application/json;charset=UTF-8");
|
response.getWriter().write(
|
"{\"code\":500,\"msg\":\"系统内部错误\"}"
|
);
|
return;
|
}
|
}
|
/**
|
* 判断路径是否在白名单中
|
*/
|
private boolean isExcludedPath(String requestPath) {
|
return weAppSecurityProperties.getExcludeUrls().stream()
|
.anyMatch(excludedPath ->
|
pathMatcher.match(excludedPath, requestPath)
|
);
|
}
|
}
|