消息通知系统

This commit is contained in:
2024-08-15 16:25:44 +08:00
parent 704e3c25bf
commit 085dac0630
20 changed files with 768 additions and 136 deletions

View File

@@ -1,133 +1,134 @@
package com.ai.da.common.security.filter;
import cn.hutool.core.util.StrUtil;
import com.ai.da.common.context.UserContext;
import com.ai.da.common.security.config.SecurityProperties;
import com.ai.da.common.security.jwt.JWTTokenHelper;
import com.ai.da.common.utils.LocalCacheUtils;
import com.ai.da.common.utils.MultiReadHttpServletRequest;
import com.ai.da.common.utils.MultiReadHttpServletResponse;
import com.ai.da.common.utils.RequestInfoUtil;
import com.ai.da.model.vo.AuthPrincipalVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.NonNull;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StopWatch;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.annotation.Resource;
import javax.security.sasl.AuthenticationException;
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.Arrays;
import java.util.List;
/**
* @author: dangweijian
* @description: 认证拦截器
* @create: 2020-07-10 16:50
**/
@Slf4j
@Configuration
public class AuthenticationFilter extends OncePerRequestFilter {
@Resource
private JWTTokenHelper jwtTokenHelper;
@Resource
private SecurityProperties properties;
private static final List<String> FILTER_URL =
Arrays.asList("/favicon.ico", "/doc.html", "api/account/login", "api/account/preLogin", "api/account/sendEmail","api/account/noLoginRequired",
"/webjars/", "/swagger-resources", "/v2/api-docs", "api/account/resetPwd",
"/api/python/saveGeneratePicture", "/api/python/getLibraryByUserId",
"/api/third/party/addUser","/api/third/party/addTrialUser", "/api/third/party/editUser", "/api/element/initDefaultSysFile",
"/api/third/party/addNoLoginRequiredNew","/api/third/party/deleteNoLoginRequiredNew",
"/api/third/party/existNoLoginRequired","/api/third/party/getRedirectUrl",
"/api/python/flush","/api/account/healthy","/api/ali-pay/trade/notify","/api/paypal/ipn/back","/api/alipay-hk/trade/notify",
"/api/portfolio/page", "/api/portfolio/detail", "/api/portfolio/commentPage", "/api/portfolio/viewsIncrease",
"/api/account/designWorksRegister","/api/account/questionnaire","/api/stripe/trade/notify"
);
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, @NonNull HttpServletResponse httpServletResponse, @NonNull FilterChain filterChain) throws ServletException, IOException {
String requestURI = httpServletRequest.getRequestURI();
if (calculateUrl(requestURI) || hasAuthorizationToken(httpServletRequest)) {
StopWatch stopWatch = new StopWatch();
HttpServletRequest wrappedRequest = httpServletRequest;
HttpServletResponse wrappedResponse = httpServletResponse;
try {
stopWatch.start();
if ((httpServletRequest.getContentType() == null && httpServletRequest.getContentLength() > 0) || (httpServletRequest.getContentType() != null && !httpServletRequest.getContentType().contains("application/json"))) {
extracted(wrappedRequest);
filterChain.doFilter(wrappedRequest, wrappedResponse);
} else {
wrappedRequest = new MultiReadHttpServletRequest(httpServletRequest);
wrappedResponse = new MultiReadHttpServletResponse(httpServletResponse);
extracted(wrappedRequest);
filterChain.doFilter(wrappedRequest, wrappedResponse);
}
} catch (Exception e) {
SecurityContextHolder.clearContext();
throw e;
} finally {
stopWatch.stop();
}
} else {
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
}
private Boolean calculateUrl(String requestURI) {
String filterUrl = FILTER_URL.stream().filter(url -> requestURI.contains(url)).findFirst().orElse(null);
return null == filterUrl ? Boolean.TRUE : Boolean.FALSE;
}
private boolean hasAuthorizationToken(HttpServletRequest request) {
String authorizationHeader = request.getHeader("Authorization");
return authorizationHeader != null && authorizationHeader.startsWith("Bearer");
}
private void extracted(HttpServletRequest request) throws AuthenticationException {
String jwtToken = request.getHeader(properties.getJwtTokenHeader());
// log.debug("后台检查令牌:{}", jwtToken);
if (StrUtil.isBlank(jwtToken)) {
String ipAddress = RequestInfoUtil.getIpAddress(request);
log.info("本次请求的ip为 " + ipAddress);
throw new RuntimeException("请传入token");
}
if(jwtToken.equals("Bearer-eyJhbGciOiJIUzUxMiJ9.eyJqdGkiOiIyIiwic3ViIjoie1wiaWRcIjoyLFwidXNlcm5hbWVcIjpcImxpcnNcIn0iLCJpYXQiOjE2NjU3NDEwODcsImlzcyI6IkRXSiIsImF1dGhvcml0aWVzIjoiW10iLCJleHAiOjE2NzQzODEwODd9.ShM9R_NNFD7oo1OvxrEgg7PFeWinOuAKkuInUCMQupp66s64Hhv8tN0Wwr83nIN4rHPqtn95wmd4msWcvaFYJA")){
//写死 暂时放行
return;
}
// 检查token
boolean validate = jwtTokenHelper.validateToken(jwtToken);
if (validate) {
AuthPrincipalVo principal = jwtTokenHelper.parserToUser(jwtToken);
if (principal == null) {
throw new RuntimeException("TOKEN已过期请重新登录");
}
//先清空当前线程变量,防止上一个线程遗留
UserContext.delete();
//存取用户信息到缓存
UserContext.setUserHolder(principal);
//校验token
String cacheToken = LocalCacheUtils.getTokenCache(String.valueOf(principal.getId()));
if(StringUtils.isEmpty(cacheToken)){
throw new RuntimeException("TOKEN已过期请重新登录");
}
if(!cacheToken.equals(jwtToken) ){
throw new RuntimeException("TOKEN已过期请重新登录");
}
// UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(null, null);
// SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
}
package com.ai.da.common.security.filter;
import cn.hutool.core.util.StrUtil;
import com.ai.da.common.context.UserContext;
import com.ai.da.common.security.config.SecurityProperties;
import com.ai.da.common.security.jwt.JWTTokenHelper;
import com.ai.da.common.utils.LocalCacheUtils;
import com.ai.da.common.utils.MultiReadHttpServletRequest;
import com.ai.da.common.utils.MultiReadHttpServletResponse;
import com.ai.da.common.utils.RequestInfoUtil;
import com.ai.da.model.vo.AuthPrincipalVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.NonNull;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StopWatch;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.annotation.Resource;
import javax.security.sasl.AuthenticationException;
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.Arrays;
import java.util.List;
/**
* @author: dangweijian
* @description: 认证拦截器
* @create: 2020-07-10 16:50
**/
@Slf4j
@Configuration
public class AuthenticationFilter extends OncePerRequestFilter {
@Resource
private JWTTokenHelper jwtTokenHelper;
@Resource
private SecurityProperties properties;
private static final List<String> FILTER_URL =
Arrays.asList("/favicon.ico", "/doc.html", "api/account/login", "api/account/preLogin", "api/account/sendEmail","api/account/noLoginRequired",
"/webjars/", "/swagger-resources", "/v2/api-docs", "api/account/resetPwd",
"/api/python/saveGeneratePicture", "/api/python/getLibraryByUserId",
"/api/third/party/addUser","/api/third/party/addTrialUser", "/api/third/party/editUser", "/api/element/initDefaultSysFile",
"/api/third/party/addNoLoginRequiredNew","/api/third/party/deleteNoLoginRequiredNew",
"/api/third/party/existNoLoginRequired","/api/third/party/getRedirectUrl",
"/api/python/flush","/api/account/healthy","/api/ali-pay/trade/notify","/api/paypal/ipn/back","/api/alipay-hk/trade/notify",
"/api/portfolio/page", "/api/portfolio/detail", "/api/portfolio/commentPage", "/api/portfolio/viewsIncrease",
"/api/account/designWorksRegister","/api/account/questionnaire","/api/stripe/trade/notify",
"/notification"
);
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest, @NonNull HttpServletResponse httpServletResponse, @NonNull FilterChain filterChain) throws ServletException, IOException {
String requestURI = httpServletRequest.getRequestURI();
if (calculateUrl(requestURI) || hasAuthorizationToken(httpServletRequest)) {
StopWatch stopWatch = new StopWatch();
HttpServletRequest wrappedRequest = httpServletRequest;
HttpServletResponse wrappedResponse = httpServletResponse;
try {
stopWatch.start();
if ((httpServletRequest.getContentType() == null && httpServletRequest.getContentLength() > 0) || (httpServletRequest.getContentType() != null && !httpServletRequest.getContentType().contains("application/json"))) {
extracted(wrappedRequest);
filterChain.doFilter(wrappedRequest, wrappedResponse);
} else {
wrappedRequest = new MultiReadHttpServletRequest(httpServletRequest);
wrappedResponse = new MultiReadHttpServletResponse(httpServletResponse);
extracted(wrappedRequest);
filterChain.doFilter(wrappedRequest, wrappedResponse);
}
} catch (Exception e) {
SecurityContextHolder.clearContext();
throw e;
} finally {
stopWatch.stop();
}
} else {
filterChain.doFilter(httpServletRequest, httpServletResponse);
}
}
private Boolean calculateUrl(String requestURI) {
String filterUrl = FILTER_URL.stream().filter(url -> requestURI.contains(url)).findFirst().orElse(null);
return null == filterUrl ? Boolean.TRUE : Boolean.FALSE;
}
private boolean hasAuthorizationToken(HttpServletRequest request) {
String authorizationHeader = request.getHeader("Authorization");
return authorizationHeader != null && authorizationHeader.startsWith("Bearer");
}
private void extracted(HttpServletRequest request) throws AuthenticationException {
String jwtToken = request.getHeader(properties.getJwtTokenHeader());
// log.debug("后台检查令牌:{}", jwtToken);
if (StrUtil.isBlank(jwtToken)) {
String ipAddress = RequestInfoUtil.getIpAddress(request);
log.info("本次请求的ip为 " + ipAddress);
throw new RuntimeException("请传入token");
}
if(jwtToken.equals("Bearer-eyJhbGciOiJIUzUxMiJ9.eyJqdGkiOiIyIiwic3ViIjoie1wiaWRcIjoyLFwidXNlcm5hbWVcIjpcImxpcnNcIn0iLCJpYXQiOjE2NjU3NDEwODcsImlzcyI6IkRXSiIsImF1dGhvcml0aWVzIjoiW10iLCJleHAiOjE2NzQzODEwODd9.ShM9R_NNFD7oo1OvxrEgg7PFeWinOuAKkuInUCMQupp66s64Hhv8tN0Wwr83nIN4rHPqtn95wmd4msWcvaFYJA")){
//写死 暂时放行
return;
}
// 检查token
boolean validate = jwtTokenHelper.validateToken(jwtToken);
if (validate) {
AuthPrincipalVo principal = jwtTokenHelper.parserToUser(jwtToken);
if (principal == null) {
throw new RuntimeException("TOKEN已过期请重新登录");
}
//先清空当前线程变量,防止上一个线程遗留
UserContext.delete();
//存取用户信息到缓存
UserContext.setUserHolder(principal);
//校验token
String cacheToken = LocalCacheUtils.getTokenCache(String.valueOf(principal.getId()));
if(StringUtils.isEmpty(cacheToken)){
throw new RuntimeException("TOKEN已过期请重新登录");
}
if(!cacheToken.equals(jwtToken) ){
throw new RuntimeException("TOKEN已过期请重新登录");
}
// UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(null, null);
// SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
}