diff --git a/pom.xml b/pom.xml
index d4df389..61a09ee 100644
--- a/pom.xml
+++ b/pom.xml
@@ -45,6 +45,11 @@
org.springframework.boot
+ spring-boot-starter-security
+
+
+
+ org.springframework.boot
spring-boot-starter-web
@@ -135,18 +140,6 @@
- com.itextpdf
- itext-asian
- ${itext-asian.version}
-
-
-
- com.itextpdf
- itextpdf
- ${itextpdf.version}
-
-
-
com.auth0
java-jwt
${java-jwt.version}
@@ -177,6 +170,12 @@
4.5.13
+
+ com.amdelamar
+ jhash
+ 2.0.0
+
+
diff --git a/src/main/java/com/zhongzhi/common/configure/SecurityConfig.java b/src/main/java/com/zhongzhi/common/configure/SecurityConfig.java
new file mode 100644
index 0000000..6b60dce
--- /dev/null
+++ b/src/main/java/com/zhongzhi/common/configure/SecurityConfig.java
@@ -0,0 +1,91 @@
+package com.zhongzhi.common.configure;
+
+import com.zhongzhi.common.interceptor.JwtAuthenticationEntryPoint;
+import com.zhongzhi.common.interceptor.JwtAuthenticationTokenFilter;
+import com.zhongzhi.common.utils.EncryptUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.web.access.AccessDeniedHandler;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+
+/**
+ * @description: security ConfigurerAdapter
+ * @author DengMin
+ * @date 2025/5/8 15:30
+ * @version 1.0
+ */
+@Configuration
+@EnableWebSecurity
+public class SecurityConfig extends WebSecurityConfigurerAdapter {
+
+ @Autowired
+ private UserDetailsService userDetailsService;
+
+ @Autowired
+ @Qualifier("RestAuthenticationAccessDeniedHandler")
+ private AccessDeniedHandler accessDeniedHandler;
+
+ @Autowired
+ private JwtAuthenticationEntryPoint unauthorizedHandler;
+
+
+ /**
+ * 配置加密方式(security 不支持明文验证方式)
+ * @param auth
+ * @throws Exception
+ */
+ @Override
+ protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+ auth.userDetailsService(userDetailsService).passwordEncoder(new PasswordEncoder() {
+ @Override
+ public String encode(CharSequence rawPassword) {
+ return EncryptUtil.encrypt((String) rawPassword);
+ }
+
+ @Override
+ public boolean matches(CharSequence charSequence, String s) {
+ return EncryptUtil.verify(s, charSequence.toString());
+ }
+ });
+ }
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+ http
+ .exceptionHandling().accessDeniedHandler(accessDeniedHandler)
+ .and()
+ .csrf().disable()
+ .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
+ .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+ .and()
+ .authorizeRequests()
+ .antMatchers(HttpMethod.POST, "/**").permitAll()
+ .antMatchers("/openApi/login", "/openApi/**").permitAll()//接口白名单配置
+ .anyRequest().authenticated();
+
+ http.headers().cacheControl();
+ http.addFilterBefore(authenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);
+ }
+
+ @Bean
+ public JwtAuthenticationTokenFilter authenticationTokenFilter() {
+ return new JwtAuthenticationTokenFilter();
+ }
+
+ @Bean
+ @Override
+ public AuthenticationManager authenticationManagerBean() throws Exception {
+ return super.authenticationManagerBean();
+ }
+}
diff --git a/src/main/java/com/zhongzhi/common/constant/PDFCheckBox.java b/src/main/java/com/zhongzhi/common/constant/PDFCheckBox.java
deleted file mode 100644
index d02ae14..0000000
--- a/src/main/java/com/zhongzhi/common/constant/PDFCheckBox.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package com.zhongzhi.common.constant;
-
-import org.apache.commons.lang3.StringUtils;
-
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-
-public class PDFCheckBox {
-
- public static String getType(String type, String projectGroup) {
- if (StringUtils.isBlank(type) &&
- projectGroup.equals(ProjectType.TECHNOLOGY_INNOVATION_GROUP)) {
- return "□方案设计类 □模型创意类 □虚拟演示类";
- } else if (StringUtils.isBlank(type) &&
- projectGroup.equals(ProjectType.CULTURAL_CREATIVE_GROUP)) {
- return "□服装与服饰类设计 □视觉传达类 □产品设计类";
- }
-
- String[] typeT = {"方案设计类", "模型创意类", "虚拟演示类"};
- String typeValue = "";
- if (projectGroup.equals(ProjectType.TECHNOLOGY_INNOVATION_GROUP)) {
- List typeList = Arrays.stream(typeT).collect(Collectors.toList());
- List str = Arrays.stream(type.split(",")).collect(Collectors.toList());
- for (String s : typeList) {
- if (str.contains(s)) {
- typeValue += "■" + s + " ";
- } else {
- typeValue += "□" + s + " ";
- }
- }
- return typeValue;
- } else if (projectGroup.equals(ProjectType.CULTURAL_CREATIVE_GROUP)) {
- if (type.equals("服装与服饰类设计")) {
- return "■服装与服饰类设计 □视觉传达类 □产品设计类";
- } else if (type.equals("视觉传达类")) {
- return "□服装与服饰类设计 ■视觉传达类 □产品设计类";
- } else if (type.equals("产品设计类")) {
- return "□服装与服饰类设计 □视觉传达类 ■产品设计类";
- } else {
- return "□服装与服饰类设计 □视觉传达类 □产品设计类";
- }
- }
- return "";
- }
-
- public static String getRoadshow( String projectGroup) {
- if (projectGroup.equals(ProjectType.TECHNOLOGY_INNOVATION_GROUP)) {
- return "□模型展示 □数字化演示" +
- " □PPT演示 □其他";
- } else if (projectGroup.equals(ProjectType.CULTURAL_CREATIVE_GROUP)) {
- return "□物化产品展示 □作品模型展示" +
- " □数字化演示 □PPT演示 □其他";
- }
-
- String[] roadshowT = {"模型展示", "数字化演示", "PPT演示", "其他"};
- String[] roadshowC = {"物化产品展示", "作品模型展示", "数字化演示", "PPT演示", "其他"};
-
-// List str = Arrays.stream(roadshow.split(",")).collect(Collectors.toList());
- String roadshowValue = "";
- if (projectGroup.equals(ProjectType.TECHNOLOGY_INNOVATION_GROUP)) {
- List roadshowTList = Arrays.stream(roadshowT).collect(Collectors.toList());
- for (String s : roadshowTList) {
-// if (str.contains(s)) {
-// roadshowValue += "■" + s + " ";
-// } else {
-// roadshowValue += "□" + s + " ";
-// }
- }
- return roadshowValue;
- } else if (projectGroup.equals(ProjectType.CULTURAL_CREATIVE_GROUP)) {
- List roadshowCList = Arrays.stream(roadshowC).collect(Collectors.toList());
- for (String s : roadshowCList) {
-// if (str.contains(s)) {
-// roadshowValue += "■" + s + " ";
-// } else {
-// roadshowValue += "□" + s + " ";
-// }
- }
- return roadshowValue;
- }
- return "";
- }
-}
diff --git a/src/main/java/com/zhongzhi/common/constant/ProjectProgress.java b/src/main/java/com/zhongzhi/common/constant/ProjectProgress.java
deleted file mode 100644
index 12910d7..0000000
--- a/src/main/java/com/zhongzhi/common/constant/ProjectProgress.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package com.zhongzhi.common.constant;
-
-public class ProjectProgress {
-
- public static final String REGISTERED = "已注册公司";
-
- public static final String UNREGISTERED = "创意设计阶段";
-
-}
diff --git a/src/main/java/com/zhongzhi/common/interceptor/JwtAuthenticationEntryPoint.java b/src/main/java/com/zhongzhi/common/interceptor/JwtAuthenticationEntryPoint.java
new file mode 100644
index 0000000..16ec3bb
--- /dev/null
+++ b/src/main/java/com/zhongzhi/common/interceptor/JwtAuthenticationEntryPoint.java
@@ -0,0 +1,36 @@
+package com.zhongzhi.common.interceptor;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.zhongzhi.common.constant.Code;
+import com.zhongzhi.common.utils.ResponseData;
+import com.zhongzhi.vo.ResponseVO;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.stereotype.Component;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.Serializable;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * @description: 无权限访问
+ * @author DengMin
+ * @date 2025/5/11 16:23
+ * @version 1.0
+ */
+@Component
+public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable {
+
+ @Override
+ public void commence(HttpServletRequest request,
+ HttpServletResponse response,
+ AuthenticationException authException) throws IOException {
+ response.setStatus(200);
+ response.setCharacterEncoding(StandardCharsets.UTF_8.name());
+ response.setContentType("application/json");
+ ObjectMapper objectMapper = new ObjectMapper();
+ ResponseVO responseVO = ResponseData.generateCreatedResponse(Code.ACCESSDENIED.getCode(), Code.ACCESSDENIED.getMessage(), null);
+ response.getWriter().write(objectMapper.writeValueAsString(responseVO));
+ }
+}
diff --git a/src/main/java/com/zhongzhi/common/interceptor/JwtAuthenticationTokenFilter.java b/src/main/java/com/zhongzhi/common/interceptor/JwtAuthenticationTokenFilter.java
new file mode 100644
index 0000000..caf76b4
--- /dev/null
+++ b/src/main/java/com/zhongzhi/common/interceptor/JwtAuthenticationTokenFilter.java
@@ -0,0 +1,62 @@
+package com.zhongzhi.common.interceptor;
+
+import com.auth0.jwt.interfaces.Claim;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.zhongzhi.common.utils.JwtUtil;
+import com.zhongzhi.common.utils.Localstorage;
+import com.zhongzhi.dao.UserMapper;
+import com.zhongzhi.model.base.UserModel;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
+import org.springframework.stereotype.Component;
+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.Map;
+
+/**
+ * @description: Token令牌过滤器
+ * @author DengMin
+ * @date 2025/5/11 16:23
+ * @version 1.0
+ */
+@Component
+public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
+
+ @Autowired
+ private UserMapper userMapper;
+
+ @Override
+ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
+ String token = request.getHeader("Authorization");
+ if (StringUtils.isNotEmpty(token)) {
+ if (token.startsWith("Bearer")) {
+ token = token.replace("Bearer ", "");
+ }
+
+ if (!JwtUtil.isExpired(token) && JwtUtil.verifyToken(token)) {
+ Map claimMap = JwtUtil.getClaims(token);
+ if(claimMap != null && SecurityContextHolder.getContext().getAuthentication() == null) {
+ UserModel userModel = userMapper.selectOne(new QueryWrapper()
+ .lambda()
+ .eq(UserModel::getUsername, claimMap.get("username").asString()));
+ if(userModel != null) {
+ UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userModel, null, userModel.getAuthorities());
+ authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
+ SecurityContextHolder.getContext().setAuthentication(authentication);
+ Localstorage.setUser(userModel);
+ } else {
+ Localstorage.remove();
+ }
+ }
+ }
+ }
+ filterChain.doFilter(request, response);
+ }
+}
diff --git a/src/main/java/com/zhongzhi/common/interceptor/RestAuthenticationAccessDeniedHandler.java b/src/main/java/com/zhongzhi/common/interceptor/RestAuthenticationAccessDeniedHandler.java
new file mode 100644
index 0000000..036720c
--- /dev/null
+++ b/src/main/java/com/zhongzhi/common/interceptor/RestAuthenticationAccessDeniedHandler.java
@@ -0,0 +1,34 @@
+package com.zhongzhi.common.interceptor;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.zhongzhi.common.constant.Code;
+import com.zhongzhi.common.utils.ResponseData;
+import com.zhongzhi.vo.ResponseVO;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.web.access.AccessDeniedHandler;
+import org.springframework.stereotype.Component;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * @description: 身份验证异常
+ * @author DengMin
+ * @date 2025/5/11 16:22
+ * @version 1.0
+ */
+@Component("RestAuthenticationAccessDeniedHandler")
+public class RestAuthenticationAccessDeniedHandler implements AccessDeniedHandler {
+
+ @Override
+ public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException {
+ response.setStatus(200);
+ response.setContentType("application/json");
+ ObjectMapper objectMapper = new ObjectMapper();
+ ResponseVO responseVO = ResponseData.generateCreatedResponse(Code.AUTHENTICATION.getCode(), Code.AUTHENTICATION.getMessage());
+ response.setCharacterEncoding(StandardCharsets.UTF_8.name());
+ response.getWriter().write(objectMapper.writeValueAsString(responseVO));
+ }
+}
diff --git a/src/main/java/com/zhongzhi/common/utils/EncryptUtil.java b/src/main/java/com/zhongzhi/common/utils/EncryptUtil.java
new file mode 100644
index 0000000..c19f936
--- /dev/null
+++ b/src/main/java/com/zhongzhi/common/utils/EncryptUtil.java
@@ -0,0 +1,45 @@
+package com.zhongzhi.common.utils;
+
+import com.amdelamar.jhash.Hash;
+import com.amdelamar.jhash.algorithms.Type;
+import com.amdelamar.jhash.exception.InvalidHashException;
+
+/**
+ * @description: 加密
+ * @author DengMin
+ * @date 2025/5/11 16:19
+ * @version 1.0
+ */
+public class EncryptUtil {
+
+ /**
+ * 设置密文密码
+ *
+ * @param password 原始密码
+ * @return 加密密码
+ */
+ public static String encrypt(String password) {
+ char[] chars = password.toCharArray();
+ return Hash.password(chars).algorithm(Type.PBKDF2_SHA256).create();
+ }
+
+ /**
+ * 验证加密密码
+ *
+ * @param encryptedPassword 密文密码
+ * @param plainPassword 明文密码
+ * @return 验证是否成功
+ */
+ public static boolean verify(String encryptedPassword, String plainPassword) {
+ char[] chars = plainPassword.toCharArray();
+ try {
+ return Hash.password(chars).algorithm(Type.PBKDF2_SHA256).verify(encryptedPassword);
+ } catch (InvalidHashException e) {
+ return false;
+ }
+ }
+
+ public static void main(String[] args) {
+ System.out.println(encrypt("123456"));
+ }
+}
diff --git a/src/main/java/com/zhongzhi/common/utils/JwtUtil.java b/src/main/java/com/zhongzhi/common/utils/JwtUtil.java
index ffe78e5..e642445 100644
--- a/src/main/java/com/zhongzhi/common/utils/JwtUtil.java
+++ b/src/main/java/com/zhongzhi/common/utils/JwtUtil.java
@@ -4,6 +4,7 @@ import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
+import org.springframework.security.core.userdetails.UserDetails;
import java.util.Date;
import java.util.Map;
@@ -25,15 +26,13 @@ public class JwtUtil {
/**
* 生成Token
*
- * @param id
+ * @param userDetails
* @return
*/
- public static String generateToken(Long id, String type) {
+ public static String generateToken(UserDetails userDetails) {
Date expireDate = new Date(System.currentTimeMillis() + EXPIRE_TIME);
return JWT.create()
- .withClaim("id", id)
- .withClaim("type", type)
- .withAudience()
+ .withClaim("username", userDetails.getUsername())
.withExpiresAt(expireDate)
.withIssuedAt(new Date())
.sign(Algorithm.HMAC256(SECRET));
diff --git a/src/main/java/com/zhongzhi/common/utils/Localstorage.java b/src/main/java/com/zhongzhi/common/utils/Localstorage.java
index aee50ad..2fe3696 100644
--- a/src/main/java/com/zhongzhi/common/utils/Localstorage.java
+++ b/src/main/java/com/zhongzhi/common/utils/Localstorage.java
@@ -2,29 +2,23 @@ package com.zhongzhi.common.utils;
import org.springframework.web.bind.annotation.RestController;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-
+/**
+ * @description: 登陆用户信息
+ * @author DengMin
+ * @date 2025/5/11 16:29
+ * @version 1.0
+ */
@RestController
public class Localstorage {
private static final ThreadLocal