Compare commits

...

2 Commits

Author SHA1 Message Date
soul2 077751021e 修复解密问题 1 year ago
soul2 7e63ad937d 尝试修复 失败次数1 1 year ago
  1. 2
      src/main/java/cn/soul2/jyjc/admin/JavaJyjcAdminApplication.java
  2. 4
      src/main/java/cn/soul2/jyjc/admin/bean/UserLoginStatusBean.java
  3. 28
      src/main/java/cn/soul2/jyjc/admin/config/CorsConfig.java
  4. 45
      src/main/java/cn/soul2/jyjc/admin/config/WebMvcConfig.java
  5. 1
      src/main/java/cn/soul2/jyjc/admin/filter/ReplaceStreamFilter.java
  6. 16
      src/main/java/cn/soul2/jyjc/admin/filter/ShaoduoRequestWrapper.java
  7. 74
      src/main/java/cn/soul2/jyjc/admin/interceptor/FinallyInterceptor.java
  8. 2
      src/main/java/cn/soul2/jyjc/admin/repository/impl/UserLoginOutRepositoryImpl.java
  9. 2
      src/main/resources/application-cors.yml

@ -3,7 +3,6 @@ package cn.soul2.jyjc.admin;
import org.mybatis.spring.annotation.MapperScan; import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
/** /**
* @author Soul2 * @author Soul2
@ -11,7 +10,6 @@ import org.springframework.context.annotation.ComponentScan;
*/ */
@SpringBootApplication @SpringBootApplication
@MapperScan("cn.soul2.jyjc.admin.mapper") @MapperScan("cn.soul2.jyjc.admin.mapper")
@ComponentScan("cn.soul2.jyjc.admin.config")
public class JavaJyjcAdminApplication { public class JavaJyjcAdminApplication {
public static void main(String[] args) { public static void main(String[] args) {

@ -1,4 +1,4 @@
package cn.soul2.jyjc.admin.config; package cn.soul2.jyjc.admin.bean;
import cn.soul2.jyjc.admin.entity.UserLoginOutDO; import cn.soul2.jyjc.admin.entity.UserLoginOutDO;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
@ -80,7 +80,7 @@ public class UserLoginStatusBean {
return Boolean.FALSE; return Boolean.FALSE;
} }
UserLoginOutDO loginStatus = loginStatusMap.getOrDefault(token, null); UserLoginOutDO loginStatus = loginStatusMap.getOrDefault(token, null);
if (loginStatus.getLapseTime() != null) { if (loginStatus != null && loginStatus.getLapseTime() != null) {
LocalDateTime now = LocalDateTime.now(); LocalDateTime now = LocalDateTime.now();
if (now.isAfter(loginStatus.getLapseTime())) { if (now.isAfter(loginStatus.getLapseTime())) {
logout(token); logout(token);

@ -1,28 +0,0 @@
package cn.soul2.jyjc.admin.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @author Soul2
* @date 2024-03-25
*/
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Value("${cors.allow-origin}")
private String[] allowOrigin;
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedHeaders("*")
.allowedOrigins(allowOrigin)
.allowCredentials(true)
.allowedMethods("POST")
.maxAge(3600);
}
}

@ -1,7 +1,12 @@
package cn.soul2.jyjc.admin.config; package cn.soul2.jyjc.admin.config;
import cn.soul2.jyjc.admin.interceptor.FinallyInterceptor; import cn.soul2.jyjc.admin.interceptor.FinallyInterceptor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@ -15,9 +20,47 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration @Configuration
public class WebMvcConfig implements WebMvcConfigurer { public class WebMvcConfig implements WebMvcConfigurer {
@Value("${cors.allow-origin}")
private String[] allowOrigin;
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
// 设置允许跨域请求的域名
for (String url : allowOrigin) {
config.addAllowedOrigin(url);
}
// 是否允许证书 不再默认开启
// config.setAllowCredentials(true);
// 设置允许的方法
config.addAllowedMethod("*");
// 允许任何头
config.addAllowedHeader("*");
config.addExposedHeader("token");
config.setMaxAge(3600L);
UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
configSource.registerCorsConfiguration("/**", config);
return new CorsFilter(configSource);
}
// @Override
// public void addCorsMappings(CorsRegistry registry) {
// registry.addMapping("/**")
// .allowedHeaders("*")
// .allowedOrigins(allowOrigin)
// .allowCredentials(true)
// .allowedMethods("POST")
// .maxAge(3600);
// }
@Bean
FinallyInterceptor createFinallyInterceptor() {
return new FinallyInterceptor();
}
@Override @Override
public void addInterceptors(InterceptorRegistry registry) { public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new FinallyInterceptor()) registry.addInterceptor(createFinallyInterceptor())
// 拦截所有路径 // 拦截所有路径
.addPathPatterns("/**"); .addPathPatterns("/**");
} }

@ -27,6 +27,7 @@ public class ReplaceStreamFilter implements Filter {
return; return;
} else { } else {
ServletRequest requestWrapper = new ShaoduoRequestWrapper((HttpServletRequest) request); ServletRequest requestWrapper = new ShaoduoRequestWrapper((HttpServletRequest) request);
// System.out.printf("ReplaceStreamFilter触发, Method: %s, URI: %s%n", ((HttpServletRequest) request).getMethod(), ((HttpServletRequest) request).getRequestURI());
chain.doFilter(requestWrapper, response); chain.doFilter(requestWrapper, response);
return; return;
} }

@ -14,7 +14,7 @@ import java.nio.charset.StandardCharsets;
/** /**
* @author shaoduo * @author shaoduo
* @description 包装HttpServletRequest目的是让其输入流可重复读 * @description 包装HttpServletRequest目的是让其输入流可重复读
* @since 1.0 * @since <a href="https://blog.csdn.net/shaoduo/article/details/122322578">shaoduo</a>
**/ **/
@Slf4j @Slf4j
public class ShaoduoRequestWrapper extends HttpServletRequestWrapper { public class ShaoduoRequestWrapper extends HttpServletRequestWrapper {
@ -23,7 +23,7 @@ public class ShaoduoRequestWrapper extends HttpServletRequestWrapper {
*/ */
private byte[] body; private byte[] body;
public ShaoduoRequestWrapper(HttpServletRequest request) throws IOException { public ShaoduoRequestWrapper(HttpServletRequest request) {
super(request); super(request);
// 将body数据存储起来 // 将body数据存储起来
@ -51,9 +51,8 @@ public class ShaoduoRequestWrapper extends HttpServletRequestWrapper {
* *
* @return String * @return String
*/ */
public String getBodyString() { public String getBodyString() throws IOException {
InputStream inputStream = new ByteArrayInputStream(body); InputStream inputStream = new ByteArrayInputStream(body);
return inputStream2String(inputStream); return inputStream2String(inputStream);
} }
@ -63,7 +62,6 @@ public class ShaoduoRequestWrapper extends HttpServletRequestWrapper {
* @param val * @param val
*/ */
public void setBody(String val) { public void setBody(String val) {
body = val.getBytes(StandardCharsets.UTF_8); body = val.getBytes(StandardCharsets.UTF_8);
} }
@ -73,7 +71,7 @@ public class ShaoduoRequestWrapper extends HttpServletRequestWrapper {
* @param inputStream inputStream * @param inputStream inputStream
* @return String * @return String
*/ */
private String inputStream2String(InputStream inputStream) { private String inputStream2String(InputStream inputStream) throws IOException {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
BufferedReader reader = null; BufferedReader reader = null;
@ -95,8 +93,6 @@ public class ShaoduoRequestWrapper extends HttpServletRequestWrapper {
} }
} }
} }
return sb.toString(); return sb.toString();
} }
@ -106,13 +102,13 @@ public class ShaoduoRequestWrapper extends HttpServletRequestWrapper {
} }
@Override @Override
public ServletInputStream getInputStream() throws IOException { public ServletInputStream getInputStream() {
final ByteArrayInputStream inputStream = new ByteArrayInputStream(body); final ByteArrayInputStream inputStream = new ByteArrayInputStream(body);
return new ServletInputStream() { return new ServletInputStream() {
@Override @Override
public int read() throws IOException { public int read() {
return inputStream.read(); return inputStream.read();
} }

@ -2,22 +2,21 @@ package cn.soul2.jyjc.admin.interceptor;
import cn.soul2.jyjc.admin.annotation.SkinEncrypt; import cn.soul2.jyjc.admin.annotation.SkinEncrypt;
import cn.soul2.jyjc.admin.annotation.SkinLogin; import cn.soul2.jyjc.admin.annotation.SkinLogin;
import cn.soul2.jyjc.admin.config.UserLoginStatusBean; import cn.soul2.jyjc.admin.bean.UserLoginStatusBean;
import cn.soul2.jyjc.admin.filter.ShaoduoRequestWrapper; import cn.soul2.jyjc.admin.filter.ShaoduoRequestWrapper;
import cn.soul2.jyjc.admin.utils.EncryptUtils; import cn.soul2.jyjc.admin.utils.EncryptUtils;
import cn.soul2.jyjc.admin.vo.base.Back;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.MediaType;
import org.springframework.web.method.HandlerMethod; import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.HandlerInterceptor;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.lang.reflect.Method; import java.lang.reflect.Method;
/** /**
@ -29,18 +28,14 @@ import java.lang.reflect.Method;
@Slf4j @Slf4j
public class FinallyInterceptor implements HandlerInterceptor { public class FinallyInterceptor implements HandlerInterceptor {
@Autowired
@Lazy
private ApplicationContext context;
@Resource @Resource
@Lazy
private UserLoginStatusBean userLoginStatusBean; private UserLoginStatusBean userLoginStatusBean;
@Override @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
boolean pass = false; boolean pass = false;
// 允许OPTIONS请求通过 // 允许OPTIONS请求通过
if ("OPTIONS".equals(request.getMethod()) && request.getHeader("Origin") != null) { if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
return true; return true;
} }
// 如果不是映射到方法直接通过 // 如果不是映射到方法直接通过
@ -68,60 +63,63 @@ public class FinallyInterceptor implements HandlerInterceptor {
if (request.getContentType() == null) { if (request.getContentType() == null) {
pass = true; pass = true;
} }
// 如果类型不是json 就放行
if (!(request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE))) {
pass = true;
}
} }
// 跳过使用 @SkinEncrypt 的情况
// 跳过使用SkinEncrypt注解的情况
if (skinEncrypt != null) { if (skinEncrypt != null) {
pass = true; pass = true;
} }
if (!pass) {
ShaoduoRequestWrapper shaoduoRequestWrapper; ShaoduoRequestWrapper shaoduoRequestWrapper;
if (request instanceof ShaoduoRequestWrapper) { try {
shaoduoRequestWrapper = (ShaoduoRequestWrapper) request; shaoduoRequestWrapper = (ShaoduoRequestWrapper) request;
} else { } catch (Exception e) {
shaoduoRequestWrapper = new ShaoduoRequestWrapper(request); System.out.printf("request.ClassTypeError: %s%n", request.getClass().getName());
request = shaoduoRequestWrapper; return true;
} }
String jsonParamBody = shaoduoRequestWrapper.getBodyString(); String sourceParamBody = shaoduoRequestWrapper.getBodyString();
JSONObject obj = JSON.parseObject(EncryptUtils.decrypt(jsonParamBody)); JSONObject obj = JSON.parseObject(EncryptUtils.decrypt(sourceParamBody));
String afterBody = JSONObject.toJSONString(obj); String afterBody = JSONObject.toJSONString(obj);
System.out.println("加密前 " + jsonParamBody);
System.out.println("解密后 " + afterBody);
shaoduoRequestWrapper.setBody(afterBody); shaoduoRequestWrapper.setBody(afterBody);
String temp = new ShaoduoRequestWrapper(shaoduoRequestWrapper).getBodyString(); log.info(String.format("解密: %s -> %s", sourceParamBody, afterBody));
System.out.println("过滤器中缓存 " + temp);
/* }
token验证
*/
/* token验证 */
if (hasSkinLogin) { if (hasSkinLogin) {
// 如果存在,绕过拦截器 // 跳过使用 @SkinLogin 的情况
pass = true; pass = true;
} else { } else {
// 验证token // 验证token
if (userLoginStatusBean == null) {
userLoginStatusBean = context.getBean(UserLoginStatusBean.class);
}
// 检查 token 是否存在并且有效 // 检查 token 是否存在并且有效
if (token == null) { if (token == null) {
// 没有Token,拒绝请求 // 没有Token,拒绝请求
response.setStatus(40401); response.setStatus(40401);
pass = false; pass = false;
} else if (userLoginStatusBean != null && !userLoginStatusBean.containsToken(token)) { } else if (userLoginStatusBean != null) {
// Token 无效,拒绝请求,可以返回特定的响应状态码,例如 401 Unauthorized if (!userLoginStatusBean.containsToken(token)) {
response.setStatus(40401); // Token 无效,拒绝请求
response.setStatus(0);
Back<String> back = new Back<String>().setCode(40401).setMessage("Token invalid!");
// 转换为 JSON 字符串
ObjectMapper objectMapper = new ObjectMapper();
String responseBody = objectMapper.writeValueAsString(back);
// 输出错误信息到响应中
PrintWriter writer = response.getWriter();
writer.print(responseBody);
writer.flush();
pass = false; pass = false;
} else {
// token存在, 通过拦截器
pass = true;
}
} }
} }
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
return pass; return pass;
} }

@ -1,6 +1,6 @@
package cn.soul2.jyjc.admin.repository.impl; package cn.soul2.jyjc.admin.repository.impl;
import cn.soul2.jyjc.admin.config.UserLoginStatusBean; import cn.soul2.jyjc.admin.bean.UserLoginStatusBean;
import cn.soul2.jyjc.admin.dto.UserLoginDTO; import cn.soul2.jyjc.admin.dto.UserLoginDTO;
import cn.soul2.jyjc.admin.dto.UserLoginOutPageDTO; import cn.soul2.jyjc.admin.dto.UserLoginOutPageDTO;
import cn.soul2.jyjc.admin.dto.UserLogoutDTO; import cn.soul2.jyjc.admin.dto.UserLogoutDTO;

@ -1,7 +1,7 @@
# 允许跨域的地址 # 允许跨域的地址
cors: cors:
allow-origin: http://localhost allow-origin: http://localhost:6100, http://localhost:7620
--- ---
spring: spring:

Loading…
Cancel
Save