Commit 5fc1be21 authored by zhouxudong's avatar zhouxudong

添加请求认证

parent 76ce5d2b
package com.lyy.user.config.auth;
import com.lyy.user.config.exception.AuthException;
import com.lyy.user.config.exception.ServiceException;
import com.lyy.user.config.other.BaseContextHandler;
import com.lyy.user.constant.Constants;
import com.lyy.user.constant.RedisConstants;
......@@ -10,6 +9,7 @@ import com.lyy.user.util.jwt.JwtTokenUtil;
import com.lyy.user.util.redis.RedisUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.AsyncHandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
......@@ -17,6 +17,7 @@ import javax.servlet.http.HttpServletResponse;
import java.util.concurrent.TimeUnit;
/** 服务拦截器,根据配置的请求路径,进行请求的拦截,执行preHandle方法 */
@Configuration
public class CurrentUserInterceptor implements AsyncHandlerInterceptor {
@Override
......
package com.lyy.user.config.auth;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.crypto.symmetric.AES;
import cn.hutool.json.JSONUtil;
import com.lyy.user.config.exception.ServiceException;
import com.lyy.user.constant.Constants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.AsyncHandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.Map;
/** 服务拦截器,根据配置的请求路径,进行请求的拦截,执行preHandle方法 */
@Configuration
@Slf4j
public class Signterceptor implements AsyncHandlerInterceptor {
@Value("${sign.privateKey}")
private String privateKey;
@Value("${sign.publicKey}")
private String publicKey;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 格式 sign: secretKey=aaaa;timer=bbbb timer 加密前: {"time":"1701660590583","uuid":"123abcdef"}
String sign = request.getHeader(Constants.sign);
try {
String[] split = sign.split(";");
Map<String, Object> value = new HashMap<>();
String[] key1 = split[0].split("=");
String[] key2 = split[1].split("=");
value.put(key1[0].trim(), key1[1].trim());
value.put(key2[0].trim(), key2[1].trim());
Object secretKey = value.get(Constants.secretKey);
Object timer = value.get(Constants.timer);
// 私钥解密获取uuid(对称加密的key)
RSA rsa = new RSA(privateKey, null);
// 注: 对称加密 的key长度应该为16
String decrypt = rsa.decryptStr(secretKey.toString(), KeyType.PrivateKey);
// 使用 对称加密的key进行解密 AES的默认模式是:AES/ECB/PKCS5Padding
AES aes = SecureUtil.aes(decrypt.getBytes());
String infoDetail = aes.decryptStr(timer.toString());
Map<String, Object> map =
JSONUtil.toBean(infoDetail, new TypeReference<Map<String, Object>>() {}, false);
Object time = map.get("time");
DateTime sendTime = DateUtil.date(Long.parseLong(time.toString()));
long between = DateUtil.between(sendTime, DateUtil.date(), DateUnit.SECOND);
if (between > 10) {
log.error("签名时间超时,请重试:{}", between);
throw new ServiceException("签名时间超时,请重试");
}
log.info("签名通过");
} catch (Exception e) {
log.error("签名有误,请重试:{},异常信息:{}", sign,e);
throw new ServiceException("签名有误,请重试");
}
return true;
}
}
package com.lyy.user.config.auth;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
......@@ -9,9 +10,9 @@ import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
......@@ -19,38 +20,46 @@ import java.util.List;
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Autowired private CurrentUserInterceptor currentUserInterceptor;
@Autowired private Signterceptor signterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
/*registry
.addInterceptor(signterceptor)
.addPathPatterns(getIncludePathPatterns())
.excludePathPatterns(Arrays.asList(swagger()));*/
// 添加需要拦截的路径,以及处理拦截的拦截器
registry
.addInterceptor(getCurrentUserInterceptor())
// 拦截器
.addInterceptor(currentUserInterceptor)
// 拦截路径
.addPathPatterns(getIncludePathPatterns())
// 白名单
.excludePathPatterns(getExcludePathPatterns());
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").
addResourceLocations("classpath:/static/");
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("doc.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
registry
.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry
.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
//Spring Boot使用UTF-8编码来对字符串进行处理
// Spring Boot使用UTF-8编码来对字符串进行处理
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));
}
@Bean
/*@Bean
CurrentUserInterceptor getCurrentUserInterceptor() {
return new CurrentUserInterceptor();
}
}*/
/** 需要拦截的信息 */
private ArrayList<String> getIncludePathPatterns() {
......@@ -60,31 +69,31 @@ public class WebConfig implements WebMvcConfigurer {
return list;
}
private String[] swagger() {
return new String[] {
"/swagger-resources/**",
"/swagger-ui.html",
"/webjars/**",
"/v3/**",
"/v2/**",
"/error",
"/swagger**/**",
"/swagger-ui/index.html",
"/swagger-ui/index.html/**",
"/doc.html",
"doc.html/**",
"/doc.html#/**",
"/**/login",
"/favicon.ico",
"/favicon.ico/**",
"/swagger-ui.html/**"
};
}
/** 不需要任何用户信息 白名单 */
private ArrayList<String> getExcludePathPatterns() {
ArrayList<String> list = new ArrayList<>();
list.add("/pc/**");
String[] excludeSwagger = new String[]{
"/swagger-resources/**",
"/swagger-ui.html",
"/webjars/**",
"/v3/**",
"/v2/**",
"/error",
"/swagger**/**",
"/swagger-ui/index.html",
"/swagger-ui/index.html/**",
"/doc.html",
"doc.html/**",
"/doc.html#/**",
"/**/login",
"/favicon.ico",
"/favicon.ico/**",
"/swagger-ui.html/**"
};
Collections.addAll(list, excludeSwagger);
Collections.addAll(list, swagger());
return list;
}
}
......@@ -116,13 +116,21 @@ public class Constants {
public static final String TOKEN_HEADER = "Authorization";
//--------------请求头签名--------------------------
public static final String sign = "sign";
public static final String timer = "timer";
public static final String secretKey = "secretKey";
//短信过期时间
//-----------------------------------------
//短信过期时间 5分钟
public static final int EXPIRE_TIME =5;
//秒
//秒 再次发送短信时间间隔
public static final int INTERVAL_TIME =4*60;
//token 过期时间
public static Long expireTime = 86400L;
//token 续期时间 12小时
public static Long addTime = 43200L;
}
package com.lyy.user.util;
import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.symmetric.AES;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
/**
* @Author:zhouxudong
*
* @version: 1.0 @Date: 2023/12/4 15:14 @Description: aes 加解密
*/
public class AesUtils {
private static final String KEY_ALGORITHM = "AES";
/**
* @description: 加密 AES的默认模式是:AES/ECB/PKCS5Padding
* @date: 2023/12/4 15:19
* @param: [data 加密数据, padding : Padding.PKCS5Padding, key 密钥]
* @return: java.lang.String
*/
public static String encryptAES(String data, Padding padding, String key) {
AES aes = new AES(Mode.ECB, padding, new SecretKeySpec(key.getBytes(), KEY_ALGORITHM));
return aes.encryptBase64(data, StandardCharsets.UTF_8);
}
/**
* @description:
* @date: 2023/12/4 15:19
* @param: [data 加密数据, padding, key 密钥]
* @return: java.lang.String
*/
public static String decryptAES(String data, Padding padding, String key) {
AES aes = new AES(Mode.ECB, padding, new SecretKeySpec(key.getBytes(), KEY_ALGORITHM));
byte[] decryptDataBase64 = aes.decrypt(data);
return new String(decryptDataBase64, StandardCharsets.UTF_8);
}
/*
private static final String KEY_ALGORITHM = "AES";
public static final String RSA_TYPE = "AES/ECB/PKCS5Padding";
private static final int KEY_SIZE = 128;
public static final String SIGNATURE_ALGORITHM = "SHA1PRNG";
@SneakyThrows
public static String encryptAES(String plainText, String secretKey) {
Cipher cipher = Cipher.getInstance(RSA_TYPE);
// cipher.init(Cipher.ENCRYPT_MODE, getKey(secretKey));
cipher.init(
Cipher.ENCRYPT_MODE,
new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), KEY_ALGORITHM));
byte[] encryptedBytes = cipher.doFinal(plainText.getBytes(StandardCharsets.UTF_8));
return Base64.getEncoder().encodeToString(encryptedBytes);
}
@SneakyThrows
public static String decryptAES(String encryptedText, String secretKey) {
Cipher cipher = Cipher.getInstance(RSA_TYPE);
// cipher.init(Cipher.DECRYPT_MODE, getKey(secretKey));
cipher.init(
Cipher.ENCRYPT_MODE,
new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), KEY_ALGORITHM));
byte[] decryptedBytes = cipher.doFinal(new BASE64Decoder().decodeBuffer(encryptedText));
return new String(decryptedBytes, StandardCharsets.UTF_8);
}
private static SecretKeySpec getKey(String secretKey) throws NoSuchAlgorithmException {
KeyGenerator gen = KeyGenerator.getInstance(KEY_ALGORITHM);
SecureRandom secureRandom = SecureRandom.getInstance(SIGNATURE_ALGORITHM);
secureRandom.setSeed(secretKey.getBytes());
gen.init(KEY_SIZE, secureRandom);
SecretKey key = gen.generateKey();
return new SecretKeySpec(key.getEncoded(), KEY_ALGORITHM);
}*/
}
......@@ -48,3 +48,7 @@ sms:
#短信时间间隔(每天限制次数) 单位 天
intervalTime: 1
#RSA 前后端交互需要的私钥
sign:
privateKey: MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAKD7/ttjvwciRa5hTneK5v2LaoMDOzcCuD60WcpA55crsfK4JP9xhmck6J2pbY+v5LCj9PJCqQZqJqA/MPre+GkDaFXvrd5ElX3l1XZ/6pLH0g95aon1gK/gKNatVs0yxS2EVMfeCUzn8kWS0GLQZYcCwdRX0vhrb6ANTFogOk9RAgMBAAECgYBInGD/o6XuGc9EMC+sS8KUaeXI4hQ7Y8amwcIeL9hFnzfMOrK1ZQcyTrt9IYaBYNzNr6Yz/00tz4NMlDQLc7anL6ByRjQs9FNXkZPqCJzWuW5l9j4nDE2bM7YUicyEF/UBgl3/LZP2bL0thGXHUATte6BMxE693ZhND10koOPq4QJBANfRqsLq45AoxVoY9bkqZ1tB19lnkq0WjE9KLWdcjGpKwQJHf1nQf+fC51XdoMS2wHcHRWtpuRaLXE8jsPrRZncCQQC+9M66hxdz63mGcNCeyMQ1KXnjdRkkEfI5obCwClhM7/vtynszV3VaFTqc8hoxRD1/5oyqoZ/xjlS4Ueswj0J3AkAQTP/O1Rr3Cn1NftEgeTlxRRnei9oiRK+4VWv0gKMCbD8Dww61Y/AlOy1p6OF5uivzUZNGt6eJMmF4gMOfTi2lAkArkxuVjvw4FJTfq+C/SxsS8osA75i0FXBL3GzATywFKoI3qgvhFGUQEGYWqFx3v5W1GPwid81SxuLoSLE9nINTAkBtcqXLpYTGs5OUtDMTQMQpX+EJUr1YJ9E9F5wIib/yPSjSP79fV0/A8M2BqXgVM7X4Mh6AL9kW8s0jirlGDNQD
publicKey: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCg+/7bY78HIkWuYU53iub9i2qDAzs3Arg+tFnKQOeXK7HyuCT/cYZnJOidqW2Pr+Swo/TyQqkGaiagPzD63vhpA2hV763eRJV95dV2f+qSx9IPeWqJ9YCv4CjWrVbNMsUthFTH3glM5/JFktBi0GWHAsHUV9L4a2+gDUxaIDpPUQIDAQAB
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment