Merge branch 'main' of https://git.jsspisoft.com/ry-das
This commit is contained in:
commit
8d9f09dd46
143
das/pom.xml
143
das/pom.xml
@ -3,7 +3,12 @@
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>3.3.0</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>com.das</groupId>
|
||||
<artifactId>das</artifactId>
|
||||
<version>1.0.0-release</version>
|
||||
@ -11,44 +16,17 @@
|
||||
<description>base das project for Spring Boot</description>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||
<java.version>17</java.version>
|
||||
<maven.compiler.source>1.8</maven.compiler.source>
|
||||
<maven.compiler.target>1.8</maven.compiler.target>
|
||||
|
||||
<maven.plugin.version>3.8.1</maven.plugin.version>
|
||||
<!--升级druid版本至1.2.9解决 discard long time none received connection-->
|
||||
<druid.version>1.2.9</druid.version>
|
||||
<bitwalker.version>1.21</bitwalker.version>
|
||||
<kaptcha.version>2.3.2</kaptcha.version>
|
||||
<fastjson.version>1.2.83</fastjson.version>
|
||||
<spring.boot.version>2.7.6</spring.boot.version>
|
||||
<mybatis.plus.spring.boot>3.5.2</mybatis.plus.spring.boot>
|
||||
<mybatis.plus.spring.boot>3.5.5</mybatis.plus.spring.boot>
|
||||
<hutool.version>5.8.18</hutool.version>
|
||||
<!--注意这里 lombok 1.18.10 和 mapstruct 1.3.0.Final 匹配-->
|
||||
<!--注意这里 lombok 1.18.20 和 mapstruct 1.5.2.Final 匹配-->
|
||||
<org.mapstruct.version>1.5.2.Final</org.mapstruct.version>
|
||||
<org.projectlombok.version>1.18.20</org.projectlombok.version>
|
||||
<google.guava.version>29.0-jre</google.guava.version>
|
||||
<apache.commons.text>1.9</apache.commons.text>
|
||||
|
||||
<postgresql.version>42.2.24</postgresql.version>
|
||||
<sa.version>1.34.0</sa.version>
|
||||
<sa.version>1.38.0</sa.version>
|
||||
</properties>
|
||||
|
||||
<!--锁定版本-->
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-dependencies</artifactId>
|
||||
<version>${spring.boot.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
@ -79,24 +57,25 @@
|
||||
<groupId>org.postgresql</groupId>
|
||||
<artifactId>postgresql</artifactId>
|
||||
<version>${postgresql.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-core</artifactId>
|
||||
<artifactId>sa-token-spring-boot3-starter</artifactId>
|
||||
<version>${sa.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-spring-boot-starter</artifactId>
|
||||
<artifactId>sa-token-redis-jackson</artifactId>
|
||||
<version>${sa.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- 提供Redis连接池 -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-dao-redis</artifactId>
|
||||
<version>${sa.version}</version>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-pool2</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 验证码 -->
|
||||
@ -109,7 +88,6 @@
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>${org.projectlombok.version}</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
@ -122,110 +100,47 @@
|
||||
<!--mybatis-plus-->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
|
||||
<version>${mybatis.plus.spring.boot}</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!--mysql 驱动-->
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 阿里数据库连接池 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid-spring-boot-starter</artifactId>
|
||||
<version>${druid.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>${fastjson.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--hutool-->
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<artifactId>hutool-core</artifactId>
|
||||
<version>${hutool.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-text -->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-text</artifactId>
|
||||
<version>${apache.commons.text}</version>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-crypto</artifactId>
|
||||
<version>${hutool.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--注:从springboot-2.3开始,校验包被独立成了一个starter组件,所以需要引入validation和web,
|
||||
而springboot-2.3之前的版本只需要引入 web 依赖就可以了。-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--google工具类-->
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>${google.guava.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!--redis 操作-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
<!--启用redis+lettuce客户端+pool连接池-->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-pool2</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!--aop切面-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-aop</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/java</directory>
|
||||
<includes>
|
||||
<include>**/*.xml</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>${spring.boot.version}</version>
|
||||
<executions>
|
||||
<!-- repackage: 最主要的是要添加 repackage goal,用来重新打包。-->
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>repackage</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<fork>true</fork>
|
||||
<addResources>true</addResources>
|
||||
<excludes>
|
||||
<!--减少打成引入配置提醒类后jar包的大小-->
|
||||
<exclude>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
</exclude>
|
||||
<exclude>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
@ -233,18 +148,6 @@
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>${maven.plugin.version}</version>
|
||||
<configuration>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
<encoding>UTF-8</encoding>
|
||||
<compilerArgs>
|
||||
<arg>-parameters</arg>
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
23
das/src/main/java/com/das/common/config/AesProperties.java
Normal file
23
das/src/main/java/com/das/common/config/AesProperties.java
Normal file
@ -0,0 +1,23 @@
|
||||
package com.das.common.config;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author zb
|
||||
* @Description
|
||||
*/
|
||||
@Component
|
||||
@Getter
|
||||
@Setter
|
||||
@ConfigurationProperties(prefix = "aes")
|
||||
public class AesProperties {
|
||||
|
||||
/**
|
||||
* token 请求头
|
||||
*/
|
||||
private String aeskey;
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package com.das.common.config;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author zb
|
||||
* @Description
|
||||
*/
|
||||
|
||||
@Component
|
||||
@Getter
|
||||
@Setter
|
||||
@ConfigurationProperties(prefix = "sa-token")
|
||||
public class SaTokenProperties {
|
||||
|
||||
/**
|
||||
* token 请求头
|
||||
*/
|
||||
private String tokenHeader;
|
||||
|
||||
/**
|
||||
* token前缀
|
||||
*/
|
||||
private String tokenPrefix;
|
||||
|
||||
/**
|
||||
* token过期时间,单位 秒,默认 2个小时
|
||||
*/
|
||||
private Integer expireTime;
|
||||
|
||||
/**
|
||||
* 刷新token过期时间,单位 秒,默认 7 天
|
||||
*/
|
||||
private Integer refreshExpireTime;
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
package com.das.common.config;
|
||||
|
||||
import com.das.common.interceptor.TokenInterceptor;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@Configuration
|
||||
public class WebConfig implements WebMvcConfigurer {
|
||||
|
||||
@Bean
|
||||
public TokenInterceptor getTokenInterceptor() {
|
||||
return new TokenInterceptor();
|
||||
}
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
// 将Token拦截器添加到注册表中
|
||||
registry.addInterceptor(getTokenInterceptor())
|
||||
// 可以指定拦截哪些路径,例如"/api/**"表示所有以/api开头的路径
|
||||
// .addPathPatterns("/api/**");
|
||||
// 排除不需要拦截的路径
|
||||
.excludePathPatterns("/api/**");
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
package com.das.common.config.redis;
|
||||
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.parser.ParserConfig;
|
||||
import com.alibaba.fastjson.serializer.SerializerFeature;
|
||||
import com.fasterxml.jackson.databind.JavaType;
|
||||
import com.fasterxml.jackson.databind.type.TypeFactory;
|
||||
import org.springframework.data.redis.serializer.RedisSerializer;
|
||||
import org.springframework.data.redis.serializer.SerializationException;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* @author chenhaojie
|
||||
* @Description Redis 使用 FastJson 序列化
|
||||
*/
|
||||
public class FastJson2RedisSerializer<T> implements RedisSerializer<T> {
|
||||
|
||||
public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
|
||||
|
||||
private Class<T> tClass;
|
||||
|
||||
static {
|
||||
// 支持自动类型匹配
|
||||
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
|
||||
}
|
||||
|
||||
public FastJson2RedisSerializer(Class<T> tClass){
|
||||
super();
|
||||
this.tClass = tClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] serialize(T t) throws SerializationException {
|
||||
if (t == null) {
|
||||
return new byte[0];
|
||||
}
|
||||
try {
|
||||
return JSON.toJSONString(t, SerializerFeature.WriteClassName).getBytes(DEFAULT_CHARSET);
|
||||
} catch (Exception e) {
|
||||
throw new SerializationException("Could not serialize: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public T deserialize(byte[] bytes) throws SerializationException {
|
||||
if (bytes == null || bytes.length <= 0){
|
||||
return null;
|
||||
}
|
||||
String str = new String(bytes, DEFAULT_CHARSET);
|
||||
try {
|
||||
return JSON.parseObject(str, tClass);
|
||||
} catch (Exception e) {
|
||||
throw new SerializationException("Could not deserialize: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
protected JavaType getJavaType(Class<?> tClass){
|
||||
return TypeFactory.defaultInstance().constructType(tClass);
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.data.redis.core.RedisTemplate;
|
||||
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
|
||||
/**
|
||||
@ -24,8 +25,8 @@ public class RedisConfig {
|
||||
redisTemplate.setConnectionFactory(redisConnectionFactory);
|
||||
|
||||
// 使用Jackson2JsonRedisSerialize 替换默认序列化
|
||||
// Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
|
||||
FastJson2RedisSerializer<Object> fastJsonRedisSerializer = new FastJson2RedisSerializer<>(Object.class);
|
||||
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
|
||||
// FastJson2RedisSerializer<Object> fastJsonRedisSerializer = new FastJson2RedisSerializer<>(Object.class);
|
||||
// GenericJackson2JsonRedisSerializer genericJackson2JsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
|
||||
|
||||
// ObjectMapper objectMapper = new ObjectMapper();
|
||||
@ -34,11 +35,11 @@ public class RedisConfig {
|
||||
|
||||
// 设置key和value的序列化规则
|
||||
redisTemplate.setKeySerializer(new StringRedisSerializer());
|
||||
redisTemplate.setValueSerializer(fastJsonRedisSerializer);
|
||||
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
|
||||
|
||||
// 设置hashKey和hashValue的序列化规则
|
||||
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
|
||||
redisTemplate.setHashValueSerializer(fastJsonRedisSerializer);
|
||||
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
|
||||
|
||||
// 设置支持事物
|
||||
//redisTemplate.setEnableTransactionSupport(true);
|
||||
|
@ -2,11 +2,11 @@ package com.das.common.constant;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -1,8 +1,8 @@
|
||||
package com.das.common.constant;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -3,6 +3,9 @@ package com.das.common.handler;
|
||||
import com.das.common.constant.AdminConstant;
|
||||
import com.das.common.exceptions.*;
|
||||
import com.das.common.result.R;
|
||||
import jakarta.validation.ConstraintViolation;
|
||||
import jakarta.validation.ConstraintViolationException;
|
||||
import jakarta.validation.ValidationException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.validation.BindException;
|
||||
@ -16,9 +19,6 @@ import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
import org.springframework.web.servlet.NoHandlerFoundException;
|
||||
|
||||
import javax.validation.ConstraintViolation;
|
||||
import javax.validation.ConstraintViolationException;
|
||||
import javax.validation.ValidationException;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,103 @@
|
||||
package com.das.common.interceptor;
|
||||
|
||||
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.crypto.Mode;
|
||||
import cn.hutool.crypto.Padding;
|
||||
import cn.hutool.crypto.symmetric.AES;
|
||||
import com.das.common.config.AesProperties;
|
||||
import com.das.common.utils.AESUtil;
|
||||
import io.micrometer.common.util.StringUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletRequestWrapper;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import jakarta.servlet.*;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
public class DecryptingOncePerRequestFilter extends OncePerRequestFilter {
|
||||
|
||||
// @Autowired
|
||||
// AESUtil aesUtils;
|
||||
//
|
||||
// @Autowired
|
||||
// AesProperties aesProperties;
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
// 读取加密的请求体数据
|
||||
String iv = request.getHeader("v");
|
||||
String encryptedData = readRequestBody(request);
|
||||
if (StringUtils.isNotBlank(encryptedData)) {
|
||||
String key = "b6967ee87b86d85a";
|
||||
AES aes = new AES(Mode.CBC, Padding.ZeroPadding, key.getBytes(), iv.getBytes());
|
||||
encryptedData = aes.decryptStr(Base64.decode(encryptedData), Charset.forName("UTF-8"));
|
||||
|
||||
// 使用自定义的请求包装器替换原始请求
|
||||
filterChain.doFilter(new DecryptingHttpServletRequestWrapper(request, encryptedData), response);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private String readRequestBody(HttpServletRequest request) throws IOException {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
try (BufferedReader reader = request.getReader()) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
stringBuilder.append(line);
|
||||
}
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
|
||||
// 自定义的请求包装器
|
||||
static class DecryptingHttpServletRequestWrapper extends HttpServletRequestWrapper {
|
||||
private final String decryptedData;
|
||||
|
||||
public DecryptingHttpServletRequestWrapper(HttpServletRequest request, String decryptedData) {
|
||||
super(request);
|
||||
this.decryptedData = decryptedData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ServletInputStream getInputStream() throws IOException {
|
||||
final ByteArrayInputStream bais = new ByteArrayInputStream(decryptedData.getBytes("UTF-8"));
|
||||
return new ServletInputStream() {
|
||||
@Override
|
||||
public boolean isFinished() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isReady() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setReadListener(ReadListener listener) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return bais.read();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public BufferedReader getReader() throws IOException {
|
||||
return new BufferedReader(new InputStreamReader(getInputStream()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,25 @@
|
||||
package com.das.common.interceptor;
|
||||
|
||||
|
||||
import com.das.common.config.AesProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @author
|
||||
*/
|
||||
@Configuration
|
||||
public class FilterConfig {
|
||||
|
||||
@Bean
|
||||
public FilterRegistrationBean decryptingFilterRegistration() {
|
||||
FilterRegistrationBean registrationBean = new FilterRegistrationBean();
|
||||
//注册过滤器
|
||||
registrationBean.setFilter(new DecryptingOncePerRequestFilter());
|
||||
registrationBean.addUrlPatterns("/*"); // 设置过滤器应用的URL模式
|
||||
registrationBean.setOrder(1); // 设置过滤器的顺序
|
||||
return registrationBean;
|
||||
}
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
package com.das.common.interceptor;
|
||||
|
||||
import com.das.common.utils.AESUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
public class TokenInterceptor implements HandlerInterceptor {
|
||||
|
||||
@Resource
|
||||
private AESUtil aesUtil;
|
||||
|
||||
private static String key;
|
||||
@Value("${aesKey}")
|
||||
public void setKey(String key){
|
||||
TokenInterceptor.key = key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
|
||||
String param = request.getParameter("param");
|
||||
// 从请求头中获取Token
|
||||
// String token = request.getHeader("token");
|
||||
// 从请求头中获取向量IV
|
||||
String iv = request.getHeader("v");
|
||||
// 先解密token
|
||||
// AESUtil.decrypt(token, iv);
|
||||
// 解密参数
|
||||
aesUtil.decrypt(key, param, iv);
|
||||
System.out.println(aesUtil.decrypt(key ,param, iv));
|
||||
request.setAttribute("param", aesUtil.decrypt(key,param, iv));
|
||||
return true;
|
||||
// if (token != null && validateToken(token)) {
|
||||
// // Token有效,继续处理请求
|
||||
// return true;
|
||||
// } else {
|
||||
// // Token无效,可以设置响应状态并返回错误信息
|
||||
// response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
// response.getWriter().write("Unauthorized");
|
||||
// return false; // 阻止请求继续
|
||||
// }
|
||||
}
|
||||
|
||||
// 示例Token验证方法,需要根据实际情况实现
|
||||
private boolean validateToken(String token) {
|
||||
// 实现Token验证逻辑
|
||||
// ...
|
||||
return true; // 假设Token总是有效的,实际应进行真实验证
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
package com.das.common.log;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.slf4j.MDC;
|
||||
import org.springframework.util.StringUtils;
|
||||
@ -8,8 +10,6 @@ import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
@ -19,22 +19,11 @@ import java.util.UUID;
|
||||
@Slf4j
|
||||
public class RequestLogInterceptor implements HandlerInterceptor {
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
String servletPath = request.getServletPath();
|
||||
// 生成RequestId
|
||||
String requestId = this.getRequestId();
|
||||
// 配置日志文件打印 REQUEST_ID
|
||||
MDC.put("REQUEST_ID", requestId);
|
||||
|
||||
log.info("servletPath:{}", servletPath);
|
||||
log.info("preHandle 前置处理----------");
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
|
||||
log.info("preHandle 处理中----------");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -69,4 +58,17 @@ public class RequestLogInterceptor implements HandlerInterceptor {
|
||||
RequestIdUtils.generateRequestId();
|
||||
return RequestIdUtils.getRequestId().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
String servletPath = request.getServletPath();
|
||||
// 生成RequestId
|
||||
String requestId = this.getRequestId();
|
||||
// 配置日志文件打印 REQUEST_ID
|
||||
MDC.put("REQUEST_ID", requestId);
|
||||
|
||||
log.info("servletPath:{}", servletPath);
|
||||
log.info("preHandle 前置处理----------");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package com.das.common.utils;
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import cn.hutool.core.util.ArrayUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
@ -38,7 +39,7 @@ public class JsonUtils {
|
||||
}
|
||||
|
||||
public static <T> T parseObject(String text, Class<T> clazz) {
|
||||
if (StringUtils.isEmpty(text)) {
|
||||
if (StrUtil.isEmpty(text)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
@ -60,7 +61,7 @@ public class JsonUtils {
|
||||
}
|
||||
|
||||
public static <T> T parseObject(String text, TypeReference<T> typeReference) {
|
||||
if (StringUtils.isBlank(text)) {
|
||||
if (StrUtil.isBlank(text)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
@ -71,7 +72,7 @@ public class JsonUtils {
|
||||
}
|
||||
|
||||
public static Dict parseMap(String text) {
|
||||
if (StringUtils.isBlank(text)) {
|
||||
if (StrUtil.isBlank(text)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
@ -85,7 +86,7 @@ public class JsonUtils {
|
||||
}
|
||||
|
||||
public static List<Dict> parseArrayMap(String text) {
|
||||
if (StringUtils.isBlank(text)) {
|
||||
if (StrUtil.isBlank(text)) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
@ -96,7 +97,7 @@ public class JsonUtils {
|
||||
}
|
||||
|
||||
public static <T> List<T> parseArray(String text, Class<T> clazz) {
|
||||
if (StringUtils.isEmpty(text)) {
|
||||
if (StrUtil.isEmpty(text)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
try {
|
||||
|
@ -1,6 +1,5 @@
|
||||
package com.das.common.utils;
|
||||
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import org.springframework.aop.framework.AopContext;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
@ -1,346 +0,0 @@
|
||||
package com.das.common.utils;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.lang.Validator;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 字符串工具类
|
||||
*
|
||||
* @author Lion Li
|
||||
*/
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class StringUtils extends org.apache.commons.lang3.StringUtils {
|
||||
|
||||
public static final String SEPARATOR = ",";
|
||||
|
||||
/**
|
||||
* 获取参数不为空值
|
||||
*
|
||||
* @param str defaultValue 要判断的value
|
||||
* @return value 返回值
|
||||
*/
|
||||
public static String blankToDefault(String str, String defaultValue) {
|
||||
return StrUtil.blankToDefault(str, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* * 判断一个字符串是否为空串
|
||||
*
|
||||
* @param str String
|
||||
* @return true:为空 false:非空
|
||||
*/
|
||||
public static boolean isEmpty(String str) {
|
||||
return StrUtil.isEmpty(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* * 判断一个字符串是否为非空串
|
||||
*
|
||||
* @param str String
|
||||
* @return true:非空串 false:空串
|
||||
*/
|
||||
public static boolean isNotEmpty(String str) {
|
||||
return !isEmpty(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* 去空格
|
||||
*/
|
||||
public static String trim(String str) {
|
||||
return StrUtil.trim(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* 截取字符串
|
||||
*
|
||||
* @param str 字符串
|
||||
* @param start 开始
|
||||
* @return 结果
|
||||
*/
|
||||
public static String substring(final String str, int start) {
|
||||
return substring(str, start, str.length());
|
||||
}
|
||||
|
||||
/**
|
||||
* 截取字符串
|
||||
*
|
||||
* @param str 字符串
|
||||
* @param start 开始
|
||||
* @param end 结束
|
||||
* @return 结果
|
||||
*/
|
||||
public static String substring(final String str, int start, int end) {
|
||||
return StrUtil.sub(str, start, end);
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化文本, {} 表示占位符<br>
|
||||
* 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
|
||||
* 如果想输出 {} 使用 \\转义 { 即可,如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
|
||||
* 例:<br>
|
||||
* 通常使用:format("this is {} for {}", "a", "b") -> this is a for b<br>
|
||||
* 转义{}: format("this is \\{} for {}", "a", "b") -> this is {} for a<br>
|
||||
* 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
|
||||
*
|
||||
* @param template 文本模板,被替换的部分用 {} 表示
|
||||
* @param params 参数值
|
||||
* @return 格式化后的文本
|
||||
*/
|
||||
public static String format(String template, Object... params) {
|
||||
return StrUtil.format(template, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为http(s)://开头
|
||||
*
|
||||
* @param link 链接
|
||||
* @return 结果
|
||||
*/
|
||||
public static boolean ishttp(String link) {
|
||||
return Validator.isUrl(link);
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串转set
|
||||
*
|
||||
* @param str 字符串
|
||||
* @param sep 分隔符
|
||||
* @return set集合
|
||||
*/
|
||||
public static Set<String> str2Set(String str, String sep) {
|
||||
return new HashSet<>(str2List(str, sep, true, false));
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串转list
|
||||
*
|
||||
* @param str 字符串
|
||||
* @param sep 分隔符
|
||||
* @param filterBlank 过滤纯空白
|
||||
* @param trim 去掉首尾空白
|
||||
* @return list集合
|
||||
*/
|
||||
public static List<String> str2List(String str, String sep, boolean filterBlank, boolean trim) {
|
||||
List<String> list = new ArrayList<>();
|
||||
if (isEmpty(str)) {
|
||||
return list;
|
||||
}
|
||||
|
||||
// 过滤空白字符串
|
||||
if (filterBlank && isBlank(str)) {
|
||||
return list;
|
||||
}
|
||||
String[] split = str.split(sep);
|
||||
for (String string : split) {
|
||||
if (filterBlank && isBlank(string)) {
|
||||
continue;
|
||||
}
|
||||
if (trim) {
|
||||
string = trim(string);
|
||||
}
|
||||
list.add(string);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写
|
||||
*
|
||||
* @param cs 指定字符串
|
||||
* @param searchCharSequences 需要检查的字符串数组
|
||||
* @return 是否包含任意一个字符串
|
||||
*/
|
||||
public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences) {
|
||||
return StrUtil.containsAnyIgnoreCase(cs, searchCharSequences);
|
||||
}
|
||||
|
||||
/**
|
||||
* 驼峰转下划线命名
|
||||
*/
|
||||
public static String toUnderScoreCase(String str) {
|
||||
return StrUtil.toUnderlineCase(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否包含字符串
|
||||
*
|
||||
* @param str 验证字符串
|
||||
* @param strs 字符串组
|
||||
* @return 包含返回true
|
||||
*/
|
||||
public static boolean inStringIgnoreCase(String str, String... strs) {
|
||||
return StrUtil.equalsAnyIgnoreCase(str, strs);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld
|
||||
*
|
||||
* @param name 转换前的下划线大写方式命名的字符串
|
||||
* @return 转换后的驼峰式命名的字符串
|
||||
*/
|
||||
public static String convertToCamelCase(String name) {
|
||||
return StrUtil.upperFirst(StrUtil.toCamelCase(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* 驼峰式命名法 例如:user_name->userName
|
||||
*/
|
||||
public static String toCamelCase(String s) {
|
||||
return StrUtil.toCamelCase(s);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
|
||||
*
|
||||
* @param str 指定字符串
|
||||
* @param strs 需要检查的字符串数组
|
||||
* @return 是否匹配
|
||||
*/
|
||||
public static boolean matches(String str, List<String> strs) {
|
||||
if (isEmpty(str) || CollUtil.isEmpty(strs)) {
|
||||
return false;
|
||||
}
|
||||
for (String pattern : strs) {
|
||||
if (isMatch(pattern, str)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断url是否与规则配置:
|
||||
* ? 表示单个字符;
|
||||
* * 表示一层路径内的任意字符串,不可跨层级;
|
||||
* ** 表示任意层路径;
|
||||
*
|
||||
* @param pattern 匹配规则
|
||||
* @param url 需要匹配的url
|
||||
*/
|
||||
public static boolean isMatch(String pattern, String url) {
|
||||
AntPathMatcher matcher = new AntPathMatcher();
|
||||
return matcher.match(pattern, url);
|
||||
}
|
||||
|
||||
/**
|
||||
* 数字左边补齐0,使之达到指定长度。注意,如果数字转换为字符串后,长度大于size,则只保留 最后size个字符。
|
||||
*
|
||||
* @param num 数字对象
|
||||
* @param size 字符串指定长度
|
||||
* @return 返回数字的字符串格式,该字符串为指定长度。
|
||||
*/
|
||||
public static String padl(final Number num, final int size) {
|
||||
return padl(num.toString(), size, '0');
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串左补齐。如果原始字符串s长度大于size,则只保留最后size个字符。
|
||||
*
|
||||
* @param s 原始字符串
|
||||
* @param size 字符串指定长度
|
||||
* @param c 用于补齐的字符
|
||||
* @return 返回指定长度的字符串,由原字符串左补齐或截取得到。
|
||||
*/
|
||||
public static String padl(final String s, final int size, final char c) {
|
||||
final StringBuilder sb = new StringBuilder(size);
|
||||
if (s != null) {
|
||||
final int len = s.length();
|
||||
if (s.length() <= size) {
|
||||
for (int i = size - len; i > 0; i--) {
|
||||
sb.append(c);
|
||||
}
|
||||
sb.append(s);
|
||||
} else {
|
||||
return s.substring(len - size, len);
|
||||
}
|
||||
} else {
|
||||
for (int i = size; i > 0; i--) {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 切分字符串(分隔符默认逗号)
|
||||
*
|
||||
* @param str 被切分的字符串
|
||||
* @return 分割后的数据列表
|
||||
*/
|
||||
public static List<String> splitList(String str) {
|
||||
return splitTo(str, Convert::toStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* 切分字符串
|
||||
*
|
||||
* @param str 被切分的字符串
|
||||
* @param separator 分隔符
|
||||
* @return 分割后的数据列表
|
||||
*/
|
||||
public static List<String> splitList(String str, String separator) {
|
||||
return splitTo(str, separator, Convert::toStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* 切分字符串自定义转换(分隔符默认逗号)
|
||||
*
|
||||
* @param str 被切分的字符串
|
||||
* @param mapper 自定义转换
|
||||
* @return 分割后的数据列表
|
||||
*/
|
||||
public static <T> List<T> splitTo(String str, Function<? super Object, T> mapper) {
|
||||
return splitTo(str, SEPARATOR, mapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 切分字符串自定义转换
|
||||
*
|
||||
* @param str 被切分的字符串
|
||||
* @param separator 分隔符
|
||||
* @param mapper 自定义转换
|
||||
* @return 分割后的数据列表
|
||||
*/
|
||||
public static <T> List<T> splitTo(String str, String separator, Function<? super Object, T> mapper) {
|
||||
if (isBlank(str)) {
|
||||
return new ArrayList<>(0);
|
||||
}
|
||||
return StrUtil.split(str, separator)
|
||||
.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.map(mapper)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/*
|
||||
* 首字母变大写
|
||||
*
|
||||
* */
|
||||
public static String capitalizeFirstLetter(String str) {
|
||||
char[] chars = str.toCharArray();
|
||||
chars[0] = toUpperCase(chars[0]);
|
||||
return String.valueOf(chars);
|
||||
}
|
||||
|
||||
/*
|
||||
* 字母变大写
|
||||
*
|
||||
* */
|
||||
public static char toUpperCase(char c) {
|
||||
if (97 <= c && c <= 122) {
|
||||
c ^= 32;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
package com.das.common.utils;
|
||||
|
||||
import cn.hutool.core.io.resource.ResourceUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import org.apache.logging.log4j.util.Strings;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.Key;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* @author Administrator
|
||||
*/
|
||||
public class TokenUtils {
|
||||
private static final String TOKEN_NAME = "token";
|
||||
|
||||
public static final String getToken(HttpServletRequest request) {
|
||||
String token = request.getHeader(TOKEN_NAME);
|
||||
if (StrUtil.isNotBlank(token)) {
|
||||
return token;
|
||||
}
|
||||
token = request.getParameter(TOKEN_NAME);
|
||||
if (StrUtil.isNotBlank(token)) {
|
||||
return token;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static final String decodePassword(String encPassword) {
|
||||
try{
|
||||
String privateKeyText = ResourceUtil.readStr("classpath:rsakey/usp_private_pkcs8.pem", Charset.defaultCharset());
|
||||
byte[] keyBytes = Base64.getDecoder().decode(privateKeyText);
|
||||
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
|
||||
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
|
||||
Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
|
||||
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
|
||||
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||
byte[] buffer = Base64.getMimeDecoder().decode(encPassword);
|
||||
byte[] rawBytes = cipher.doFinal(buffer);
|
||||
String rawText = new String(rawBytes, "UTF-8");
|
||||
return rawText;
|
||||
}
|
||||
catch (Exception ex){
|
||||
return Strings.EMPTY;
|
||||
}
|
||||
}
|
||||
}
|
@ -6,29 +6,21 @@ import com.das.common.captcha.CaptchaUtil;
|
||||
import com.das.common.captcha.CaptchaVO;
|
||||
import com.das.common.result.R;
|
||||
import com.das.common.utils.AdminRedisTemplate;
|
||||
import com.das.modules.auth.domain.LoginUserDetails;
|
||||
import com.das.modules.auth.domain.vo.LoginVO;
|
||||
import com.das.modules.auth.service.ILoginService;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.google.code.kaptcha.Producer;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
/**
|
||||
* @author chenhaojie
|
||||
* @Description 获取验证码
|
||||
*/
|
||||
@Slf4j
|
||||
@RequestMapping("/api")
|
||||
@RequestMapping("/api/captcha")
|
||||
@RestController
|
||||
public class CaptchaImageController {
|
||||
@Resource
|
||||
@ -36,7 +28,7 @@ public class CaptchaImageController {
|
||||
@Resource
|
||||
private CaptchaProperties captchaProperties;
|
||||
|
||||
@Value("${aesKey}")
|
||||
@Value("${aes.Key}")
|
||||
String key;
|
||||
@Resource
|
||||
private AdminRedisTemplate adminRedisTemplate;
|
||||
|
@ -2,20 +2,19 @@ package com.das.modules.auth.controller;
|
||||
|
||||
import com.das.common.result.R;
|
||||
import com.das.modules.auth.domain.LoginUserDetails;
|
||||
import com.das.modules.auth.domain.request.LoginRequest;
|
||||
import com.das.modules.auth.domain.vo.LoginVO;
|
||||
import com.das.modules.auth.service.ILoginService;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import io.micrometer.common.util.StringUtils;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
|
||||
/**
|
||||
* @author chenhaojie
|
||||
@ -27,7 +26,7 @@ import javax.validation.constraints.NotEmpty;
|
||||
public class LoginController {
|
||||
@Resource
|
||||
private ILoginService loginService;
|
||||
@Value("${aesKey}")
|
||||
@Value("${aes.Key}")
|
||||
String key;
|
||||
|
||||
|
||||
@ -36,9 +35,13 @@ public class LoginController {
|
||||
* @return 退出结果提示信息
|
||||
*/
|
||||
@PostMapping("/login")
|
||||
public R<LoginUserDetails> login(@RequestParam String param, HttpServletRequest request, HttpServletResponse response) throws JsonProcessingException {
|
||||
LoginUserDetails loginInfo = loginService.login(param,request, response);
|
||||
public R<LoginUserDetails> login(@RequestBody LoginRequest loginRequest, HttpServletRequest request, HttpServletResponse response) throws JsonProcessingException {
|
||||
LoginUserDetails loginInfo = loginService.login(loginRequest,request, response);
|
||||
if (StringUtils.isNotEmpty(loginInfo.getMsg())){
|
||||
return R.fail(loginInfo.getMsg());
|
||||
}
|
||||
return R.success(loginInfo);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -57,7 +60,7 @@ public class LoginController {
|
||||
@PostMapping("/refreshToken")
|
||||
public R<LoginVO> refreshToken(@NotEmpty(message = "刷新token不允许为空") @RequestParam("refreshToken")String refreshToken){
|
||||
LoginVO loginVO = loginService.refreshToken(refreshToken);
|
||||
return R.data(loginVO);
|
||||
return R.success(loginVO);
|
||||
}
|
||||
|
||||
|
||||
|
@ -6,7 +6,7 @@ import lombok.Data;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author zb
|
||||
* @author chenhaojie
|
||||
* @Description
|
||||
*/
|
||||
@Data
|
||||
@ -16,6 +16,9 @@ public class LoginUserDetails implements Serializable {
|
||||
|
||||
private SysUserVo sysUser;
|
||||
|
||||
private String msg;
|
||||
|
||||
private String refreshToken;
|
||||
|
||||
private String token;
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
package com.das.modules.auth.domain.request;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* @author chenhaojie
|
||||
|
@ -23,6 +23,9 @@ public class LoginVO implements Serializable {
|
||||
*/
|
||||
private String refreshToken;
|
||||
|
||||
private String msg;
|
||||
|
||||
|
||||
/**
|
||||
*过期时间 秒
|
||||
*/
|
||||
@ -30,6 +33,13 @@ public class LoginVO implements Serializable {
|
||||
|
||||
public LoginVO(){}
|
||||
|
||||
public LoginVO(String accessToken, String refreshToken , Integer expire, String msg){
|
||||
this.refreshToken = refreshToken;
|
||||
this.accessToken = accessToken;
|
||||
this.expire = expire;
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public LoginVO(String accessToken, String refreshToken , Integer expire){
|
||||
this.refreshToken = refreshToken;
|
||||
this.accessToken = accessToken;
|
||||
|
@ -1,13 +1,13 @@
|
||||
package com.das.modules.auth.service;
|
||||
|
||||
|
||||
import com.das.common.result.R;
|
||||
import com.das.modules.auth.domain.LoginUserDetails;
|
||||
import com.das.modules.auth.domain.request.LoginRequest;
|
||||
import com.das.modules.auth.domain.vo.LoginVO;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* @author chenhaojie
|
||||
@ -21,7 +21,7 @@ public interface ILoginService {
|
||||
* @param data 登录请求
|
||||
* @return 登录成功
|
||||
*/
|
||||
LoginUserDetails login(String data, HttpServletRequest request, HttpServletResponse response) throws JsonProcessingException;
|
||||
LoginUserDetails login(LoginRequest loginRequest, HttpServletRequest request, HttpServletResponse response) throws JsonProcessingException;
|
||||
|
||||
/**
|
||||
* 退出登录
|
||||
|
@ -1,31 +1,32 @@
|
||||
package com.das.modules.auth.service.impl;
|
||||
|
||||
import cn.dev33.satoken.secure.BCrypt;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.das.common.captcha.CaptchaUtil;
|
||||
import com.das.common.config.SaTokenProperties;
|
||||
import com.das.common.exceptions.ServiceException;
|
||||
import com.das.common.result.R;
|
||||
import com.das.common.result.ResultCode;
|
||||
import com.das.common.utils.AESUtil;
|
||||
import com.das.common.utils.AdminRedisTemplate;
|
||||
import com.das.modules.auth.domain.LoginUserDetails;
|
||||
import com.das.modules.auth.domain.request.LoginRequest;
|
||||
import com.das.modules.auth.domain.vo.LoginVO;
|
||||
import com.das.modules.auth.domain.vo.SysUserVo;
|
||||
import com.das.modules.auth.entity.SysUser;
|
||||
import com.das.modules.auth.mapper.SysUserMapper;
|
||||
import com.das.modules.auth.service.ILoginService;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
//import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import com.das.modules.auth.domain.vo.LoginVO;
|
||||
import com.das.modules.auth.service.ILoginService;
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.time.Duration;
|
||||
|
||||
/**
|
||||
* @author chenhaojie
|
||||
@ -33,6 +34,9 @@ import javax.servlet.http.HttpServletResponse;
|
||||
*/
|
||||
@Service
|
||||
public class LoginServiceImpl implements ILoginService {
|
||||
|
||||
@Resource
|
||||
private SaTokenProperties saTokenProperties;
|
||||
@Resource
|
||||
private SysUserMapper sysUserMapper;
|
||||
|
||||
@ -42,54 +46,43 @@ public class LoginServiceImpl implements ILoginService {
|
||||
@Resource
|
||||
private AESUtil aesUtil;
|
||||
|
||||
@Value("${aesKey}")
|
||||
@Value("${aes.Key}")
|
||||
private String key;
|
||||
|
||||
// @Override
|
||||
// public String login(LoginRequest loginRequest) {
|
||||
// String captcha = loginRequest.getUsername();
|
||||
// String account = loginRequest.getUsername();
|
||||
// String password = loginRequest.getPassword();
|
||||
// String uuid = loginRequest.getPassword();
|
||||
//
|
||||
// // 验证码验证逻辑(这里省略,需根据实际情况实现)
|
||||
// if (CaptchaUtil.checkVerificationCode(uuid, captcha, adminRedisTemplate)) {
|
||||
// return "验证码错误";
|
||||
// }
|
||||
// // 用户名密码验证
|
||||
//// if (isValidUser(account, password)) {
|
||||
// // 登录成功,使用Sa-Token生成Token
|
||||
// StpUtil.login(account);
|
||||
// // 返回Token给客户端
|
||||
// return StpUtil.getTokenValue();
|
||||
//// } else {
|
||||
//// return "用户名或密码错误";
|
||||
//
|
||||
// }
|
||||
|
||||
@Override
|
||||
public LoginUserDetails login(String param, HttpServletRequest request, HttpServletResponse response) throws JsonProcessingException {
|
||||
String iv = request.getHeader("v");
|
||||
System.out.println("iv:" + iv);
|
||||
param = aesUtil.decrypt(key, param, iv);
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
LoginRequest loginRequest = objectMapper.readValue(param, LoginRequest.class);
|
||||
public LoginUserDetails login(LoginRequest loginRequest, HttpServletRequest request, HttpServletResponse response) throws JsonProcessingException {
|
||||
// String iv = request.getHeader("v");
|
||||
// System.out.println("iv:" + iv);
|
||||
// param = aesUtil.decrypt(key, param, iv);
|
||||
// ObjectMapper objectMapper = new ObjectMapper();
|
||||
// LoginRequest loginRequest = objectMapper.readValue(param, LoginRequest.class);
|
||||
String name = loginRequest.getUsername();
|
||||
String password = loginRequest.getPassword();
|
||||
String code = loginRequest.getCode();
|
||||
String uuid = loginRequest.getUuid();
|
||||
|
||||
|
||||
LoginUserDetails loginInfo = new LoginUserDetails();
|
||||
LambdaQueryWrapper<SysUser> wrapper = Wrappers.lambdaQuery();
|
||||
wrapper.eq(SysUser::getAccount, loginRequest.getUsername());
|
||||
wrapper.eq(SysUser::getAccount, name);
|
||||
SysUser sysUser = sysUserMapper.selectOne(wrapper);
|
||||
if (sysUser == null) {
|
||||
throw new ServiceException("无账号信息");
|
||||
loginInfo.setMsg("无账号信息");
|
||||
return loginInfo;
|
||||
}
|
||||
if (!CaptchaUtil.checkVerificationCode(uuid, code, adminRedisTemplate)) {
|
||||
throw new ServiceException("验证码不正确");
|
||||
loginInfo.setMsg("验证码不正确");
|
||||
return loginInfo;
|
||||
}
|
||||
StpUtil.login(sysUser.getId()); // 执行登录,这里username为用户唯一标识
|
||||
if (!BCrypt.checkpw(password, sysUser.getPassword())) {
|
||||
loginInfo.setMsg("账号密码错误");
|
||||
return loginInfo;
|
||||
}
|
||||
StpUtil.login(sysUser.getAccount());// 执行登录,这里username为用户唯一标识
|
||||
String refreshTokenUuid = IdUtil.fastSimpleUUID();
|
||||
String token = StpUtil.getTokenValue();
|
||||
String refreshToken = "refresh:" + refreshTokenUuid;
|
||||
|
||||
SysUserVo sysUserVo = new SysUserVo();
|
||||
sysUserVo.setId(sysUser.getId());
|
||||
sysUserVo.setAccount(sysUser.getAccount());
|
||||
@ -97,9 +90,12 @@ public class LoginServiceImpl implements ILoginService {
|
||||
sysUserVo.setPhone(sysUser.getPhone());
|
||||
sysUserVo.setEmail(sysUser.getEmail());
|
||||
sysUserVo.setOrgId(sysUser.getOrgId());
|
||||
LoginUserDetails loginInfo = new LoginUserDetails();
|
||||
|
||||
loginInfo.setSysUser(sysUserVo); // 存储用户信息到会话
|
||||
loginInfo.setToken(StpUtil.getTokenValue());
|
||||
loginInfo.setRefreshToken(refreshTokenUuid);
|
||||
adminRedisTemplate.setEx(token, loginInfo, Duration.ofSeconds(saTokenProperties.getExpireTime()));
|
||||
adminRedisTemplate.setEx(refreshToken, loginInfo, Duration.ofSeconds(saTokenProperties.getRefreshExpireTime()));
|
||||
return loginInfo;
|
||||
}
|
||||
|
||||
@ -116,24 +112,29 @@ public class LoginServiceImpl implements ILoginService {
|
||||
|
||||
@Override
|
||||
public LoginVO refreshToken(String refreshToken) {
|
||||
// Claims claim = tokenService.getClaim(refreshToken);
|
||||
// String uuid = (String) claim.get("uuid");
|
||||
// String username = (String) claim.get("username");
|
||||
// String refresh = (String) claim.get("refresh");
|
||||
// if (StrUtil.isEmpty(refresh)) {
|
||||
// throw new BusinessException("非法token");
|
||||
// }
|
||||
// LoginUserDetails loginUserDetails = adminRedisTemplate.get(username + ":refresh:" + uuid);
|
||||
// if (loginUserDetails == null) {
|
||||
// throw new BusinessException("token过期,请重新登录");
|
||||
// }
|
||||
// String token = tokenService.createToken(loginUserDetails);
|
||||
// String newRefreshToken = tokenService.createRefreshToken(loginUserDetails);
|
||||
// String tokenPrefix = jwtProperties.getTokenPrefix();
|
||||
// // 删除原有刷新token
|
||||
// adminRedisTemplate.del(username + ":refresh:" + uuid);
|
||||
// return new LoginVO(tokenPrefix + " " + token, newRefreshToken, jwtProperties.getExpireTime());
|
||||
return new LoginVO();
|
||||
LoginUserDetails loginUserDetails = adminRedisTemplate.get(refreshToken);
|
||||
LoginVO loginInfo = new LoginVO();
|
||||
if (loginUserDetails == null) {
|
||||
loginInfo.setMsg("token过期,请重新登录");
|
||||
return loginInfo;
|
||||
}
|
||||
StpUtil.login(loginUserDetails.getSysUser().getAccount());// 执行登录,这里username为用户唯一标识
|
||||
String newToken = StpUtil.getTokenValue();
|
||||
String newRefreshTokenUuid = IdUtil.fastSimpleUUID();
|
||||
String newRefreshToken = "refresh:" + newRefreshTokenUuid;
|
||||
loginInfo.setAccessToken(newToken);
|
||||
|
||||
loginUserDetails.setToken(newToken);
|
||||
loginUserDetails.setRefreshToken(newRefreshTokenUuid);
|
||||
String oldRefreshToken = loginUserDetails.getRefreshToken();
|
||||
|
||||
adminRedisTemplate.setEx(newToken, loginUserDetails, Duration.ofSeconds(saTokenProperties.getExpireTime()));
|
||||
adminRedisTemplate.setEx(refreshToken, loginUserDetails, Duration.ofSeconds(saTokenProperties.getRefreshExpireTime()));
|
||||
// 删除原有刷新token
|
||||
adminRedisTemplate.del("refresh:" + oldRefreshToken);
|
||||
|
||||
return new LoginVO(newToken, newRefreshToken, saTokenProperties.getRefreshExpireTime());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,34 +0,0 @@
|
||||
spring:
|
||||
autoconfigure:
|
||||
exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
|
||||
datasource:
|
||||
url: jdbc:postgresql://192.168.109.102:5432/das
|
||||
# url: jdbc:p6spy:mysql://81.69.43.78:3306/cloud-demo?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8
|
||||
username: das
|
||||
password: qwaszx12
|
||||
driver-class-name: org.postgresql.Driver
|
||||
#使用Druid
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
|
||||
# # redis相关配置
|
||||
redis:
|
||||
host: 127.0.0.1
|
||||
database: 0
|
||||
port: 6379
|
||||
password:
|
||||
lettuce:
|
||||
pool:
|
||||
# 连接池最大连接数,负值表示没有限制
|
||||
max-active: 100
|
||||
# 连接池最大阻塞等待时间 -1 表示没有限制
|
||||
max-wait: -1ms
|
||||
# 连接池中最大空闲连接
|
||||
max-idle: 10
|
||||
# 连接池中最小空闲连接
|
||||
min-idle: 5
|
||||
# 连接超时时间(毫秒)
|
||||
timeout: 5000
|
||||
# 指定客户端
|
||||
client-type: lettuce
|
||||
|
||||
aesKey: b6967ee87b86d85a
|
@ -1,33 +0,0 @@
|
||||
spring:
|
||||
autoconfigure:
|
||||
exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
|
||||
datasource:
|
||||
url: jdbc:postgresql://192.168.109.102:5432/das
|
||||
# url: jdbc:p6spy:mysql://81.69.43.78:3306/cloud-demo?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8
|
||||
username: das
|
||||
password: qwaszx12
|
||||
driver-class-name: org.postgresql.Driver
|
||||
#使用Druid
|
||||
type: com.alibaba.druid.pool.DruidDataSource
|
||||
|
||||
# # redis相关配置
|
||||
redis:
|
||||
host: 127.0.0.1
|
||||
database: 0
|
||||
port: 6379
|
||||
password:
|
||||
lettuce:
|
||||
pool:
|
||||
# 连接池最大连接数,负值表示没有限制
|
||||
max-active: 100
|
||||
# 连接池最大阻塞等待时间 -1 表示没有限制
|
||||
max-wait: -1ms
|
||||
# 连接池中最大空闲连接
|
||||
max-idle: 10
|
||||
# 连接池中最小空闲连接
|
||||
min-idle: 5
|
||||
# 连接超时时间(毫秒)
|
||||
timeout: 5000
|
||||
# 指定客户端
|
||||
client-type: lettuce
|
||||
|
@ -19,17 +19,17 @@ sa-token:
|
||||
# 是否开启Sa-Token全局拦截器,默认为true
|
||||
enabled: true
|
||||
# token名称
|
||||
token-name: token
|
||||
tokenHeader: token
|
||||
# token前缀
|
||||
token-prefix: Bearer
|
||||
tokenPrefix: Bearer
|
||||
# token有效期,单位秒
|
||||
timeout: 7200
|
||||
expireTime: 7200
|
||||
refreshExpireTime: 604800
|
||||
# 是否允许同一账号多终端登录,默认为true
|
||||
is-concurrent: true
|
||||
|
||||
|
||||
spring:
|
||||
profiles:
|
||||
active: dev
|
||||
application:
|
||||
name: das
|
||||
#json格式化全局配置,相当于@JsonFormat
|
||||
@ -38,27 +38,6 @@ spring:
|
||||
date-format: yyyy-MM-dd HH:mm:ss
|
||||
# 指定默认包含的熟悉,NON_NULL表示只序列化非空属性
|
||||
default-property-inclusion: non_null
|
||||
|
||||
# Failed to start bean 'documentationPluginsBootstrapper'; nested exception is java.lang.NullPointerException
|
||||
# 因为Springfox 使用的路径匹配是基于AntPathMatcher的,而Spring Boot 2.6.X使用的是PathPatternMatcher
|
||||
mvc:
|
||||
pathmatch:
|
||||
matching-strategy: ant_path_matcher
|
||||
# 相当于 @DateTimeFormat
|
||||
format:
|
||||
date: yyyy-MM-dd
|
||||
date-time: yyyy-MM-dd HH:mm:ss
|
||||
# 允许mvc抛出404异常
|
||||
throw-exception-if-no-handler-found: true
|
||||
# 关闭spring自带的映射,会导致swagger也不能访问,需指定swagger的静态资源处理
|
||||
web:
|
||||
resources:
|
||||
add-mappings: false
|
||||
# 资源信息
|
||||
messages:
|
||||
# 国际化资源文件路径
|
||||
basename: i18n.messages
|
||||
encoding: UTF-8
|
||||
# 配置文件上传大小限制
|
||||
servlet:
|
||||
multipart:
|
||||
@ -66,6 +45,18 @@ spring:
|
||||
max-file-size: 1024MB
|
||||
# 多个文件总大小
|
||||
max-request-size: 2048MB
|
||||
datasource:
|
||||
url: jdbc:postgresql://192.168.109.102:5432/das
|
||||
username: das
|
||||
password: qwaszx12
|
||||
# # redis相关配置
|
||||
data:
|
||||
redis:
|
||||
host: 127.0.0.1
|
||||
database: 0
|
||||
port: 6379
|
||||
password:
|
||||
client-type: lettuce
|
||||
|
||||
|
||||
# 配置 xml 文件所在位置 配置全局的 主键策略,默认为 ASSIGN_ID 默认为 【雪花算法】 , atuo 自增
|
||||
@ -100,3 +91,5 @@ captcha:
|
||||
verify-type: calculate
|
||||
expire: 120
|
||||
|
||||
aes:
|
||||
Key: b6967ee87b86d85a
|
@ -1,13 +1,23 @@
|
||||
# 概述
|
||||
|
||||
## 接口约定
|
||||
|
||||
系统中的所有接口均遵循以下约定。
|
||||
|
||||
1. 除了与文件上传/下载相关的接口外,都是`POST`请求,请求报文使用`JSON`格式。
|
||||
2. 文件下载使用GET请求(此种类型,加解密再讨论下)。
|
||||
3. 文件上传使用POST请求,请求报文使用`multipart/form-data`格式。
|
||||
|
||||
## 加密/解密
|
||||
|
||||
请求报文,Header中需要添加参数
|
||||
|
||||
| 参数名称 | 说明 | |
|
||||
| 参数名称 | 说明 | 备注 |
|
||||
| -------- | -------- | --- |
|
||||
| Token | 令牌 | |
|
||||
| V | 加密向量 | |
|
||||
|
||||
| Token | 令牌 | 需要鉴权的API 才需要添加此参数 |
|
||||
| V | 加密向量 | 必须添加 |
|
||||
|
||||
加密采用AES/CBC/ZeroPadding加密方式,密钥长度为16位。,IV长度为16位(每次请求时随机生成)。
|
||||
|
||||
# 登录模块API接口
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user