Browse Source

1、增加模块权限拦截验证,代码结构调整

master
bjang03 4 months ago
parent
commit
e243f7296d
  1. 5
      win-framework/win-spring-boot-starter-web/src/main/java/com/win/framework/web/config/WinWebAutoConfiguration.java
  2. 40
      win-framework/win-spring-boot-starter-web/src/main/java/com/win/framework/web/core/filter/ModuleAuthenInterceptor.java
  3. 36
      win-framework/win-spring-boot-starter-web/src/main/java/com/win/framework/web/core/util/ModuleAuthenUtils.java
  4. 14
      win-module-eam/win-module-eam-biz/src/main/java/com/win/module/eam/mq/consumer/LicencesConsumer.java
  5. 7
      win-module-eam/win-module-eam-biz/src/main/java/com/win/module/eam/mq/message/LicencesMessage.java
  6. 1
      win-module-eam/win-module-eam-biz/src/main/java/com/win/module/eam/service/licences/LicencesService.java
  7. 73
      win-module-eam/win-module-eam-biz/src/main/java/com/win/module/eam/service/licences/LicencesServiceImpl.java

5
win-framework/win-spring-boot-starter-web/src/main/java/com/win/framework/web/config/WinWebAutoConfiguration.java

@ -5,6 +5,7 @@ import com.win.framework.common.enums.WebFilterOrderEnum;
import com.win.framework.web.constant.Constant;
import com.win.framework.web.core.filter.CacheRequestBodyFilter;
import com.win.framework.web.core.filter.DemoFilter;
import com.win.framework.web.core.filter.ModuleAuthenInterceptor;
import com.win.framework.web.core.filter.MyI18nInterceptor;
import com.win.framework.web.core.handler.GlobalExceptionHandler;
import com.win.framework.web.core.handler.GlobalResponseBodyHandler;
@ -150,11 +151,15 @@ public class WinWebAutoConfiguration implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 模块权限拦截器 张斌 2024-05-15 10:29
// registry.addInterceptor(new ModuleAuthenInterceptor()).addPathPatterns("/**");
// 注册拦截器
MyI18nInterceptor myHandlerInterceptor = new MyI18nInterceptor();
InterceptorRegistration loginRegistry = registry.addInterceptor(myHandlerInterceptor);
// 拦截路径
loginRegistry.addPathPatterns("/**");
}
/**

40
win-framework/win-spring-boot-starter-web/src/main/java/com/win/framework/web/core/filter/ModuleAuthenInterceptor.java

@ -0,0 +1,40 @@
package com.win.framework.web.core.filter;
import cn.hutool.json.JSONObject;
import com.win.framework.web.core.util.ModuleAuthenUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDateTime;
@Slf4j
public class ModuleAuthenInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
LocalDateTime endTime = LocalDateTime.parse(ModuleAuthenUtils.decrypt(ModuleAuthenUtils.moduleExpire.getStr(request.getRequestURI().split("/")[1],null)));
if (endTime == null || endTime.isBefore(LocalDateTime.now())){
throw new Exception("权限到期或没有当前模块使用权限,请联系服务商缴费");
}
return true;
}
/**
* 请求处理之后进行调用但是在视图被渲染之前Controller方法调用之后
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
}
/**
* 在整个请求结束之后被调用也就是在DispatcherServlet 渲染了对应的视图之后执行主要是用于进行资源清理工作
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
}
}

36
win-framework/win-spring-boot-starter-web/src/main/java/com/win/framework/web/core/util/ModuleAuthenUtils.java

@ -0,0 +1,36 @@
package com.win.framework.web.core.util;
import cn.hutool.core.codec.Base64;
import cn.hutool.json.JSONObject;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
public class ModuleAuthenUtils {
private static final String ALGORITHM = "AES";
private static final int KEY_SIZE = 128;
public static String secretKey;
public static JSONObject moduleExpire;
public static String decrypt(String encryptedData) throws Exception {
SecretKeySpec secretKeySpec = new SecretKeySpec(Base64.decode(secretKey), ALGORITHM);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
byte[] decryptedBytes = cipher.doFinal(Base64.decode(encryptedData));
return new String(decryptedBytes, StandardCharsets.UTF_8);
}
public static String encrypt(String data) throws Exception {
SecretKeySpec secretKeySpec = new SecretKeySpec(Base64.decode(secretKey), ModuleAuthenUtils.ALGORITHM);
Cipher cipher = Cipher.getInstance(ModuleAuthenUtils.ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
byte[] encryptedBytes = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
return Base64.encode(encryptedBytes);
}
public static String generateKey() throws NoSuchAlgorithmException {
KeyGenerator keyGenerator = KeyGenerator.getInstance(ModuleAuthenUtils.ALGORITHM);
keyGenerator.init(ModuleAuthenUtils.KEY_SIZE);
return Base64.encode(keyGenerator.generateKey().getEncoded());
}
}

14
win-module-eam/win-module-eam-biz/src/main/java/com/win/module/eam/mq/consumer/LicencesConsumer.java

@ -0,0 +1,14 @@
package com.win.module.eam.mq.consumer;
import com.alibaba.fastjson.JSONObject;
import com.win.framework.mq.core.stream.AbstractStreamMessageListener;
import com.win.module.eam.mq.message.LicencesMessage;
import com.win.module.eam.service.licences.LicencesService;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
@Component
public class LicencesConsumer {
@Resource
private LicencesService licencesService;
}

7
win-module-eam/win-module-eam-biz/src/main/java/com/win/module/eam/mq/message/LicencesMessage.java

@ -1,13 +1,10 @@
package com.win.module.eam.mq.message;
import lombok.Data;
import lombok.ToString;
import java.util.List;
@Data
@ToString(callSuper = true)
public class LicencesMessage {
public class LicencesMessage{
private String secretKey;
private String data;
}
}

1
win-module-eam/win-module-eam-biz/src/main/java/com/win/module/eam/service/licences/LicencesService.java

@ -1,6 +1,7 @@
package com.win.module.eam.service.licences;
import com.win.module.eam.controller.licences.vo.GenerateLicenceReqVO;
import com.win.module.eam.mq.message.LicencesMessage;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;

73
win-module-eam/win-module-eam-biz/src/main/java/com/win/module/eam/service/licences/LicencesServiceImpl.java

@ -4,8 +4,9 @@ import cn.hutool.core.codec.Base64;
import cn.hutool.crypto.digest.MD5;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import cn.hutool.json.JSONObject;
import com.win.framework.web.core.filter.ModuleAuthenInterceptor;
import com.win.framework.web.core.util.ModuleAuthenUtils;
import com.win.module.eam.controller.licences.vo.GenerateLicenceReqVO;
import com.win.module.eam.mq.message.LicencesMessage;
import org.apache.calcite.util.Util;
@ -22,8 +23,6 @@ import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import static com.win.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.win.module.eam.enums.ErrorCodeConstants.ENCRYPTION_STR_FORMAT_IS_ERROR;
@ -31,35 +30,10 @@ import static com.win.module.eam.enums.ErrorCodeConstants.ENCRYPTION_STR_FORMAT_
@Service
@Validated
public class LicencesServiceImpl implements LicencesService {
private static final String ALGORITHM = "AES";
private static final int KEY_SIZE = 128;
private static final String LICENCES_UPDATE = "LICENCES";
public static final String LICENCES_UPDATE = "system.licences";
@Resource
private RedisTemplate<String, String> redisTemplate;
private static String generateKey() throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM);
keyGenerator.init(KEY_SIZE);
SecretKey secretKey = keyGenerator.generateKey();
return Base64.encode(secretKey.getEncoded());
}
private static String encrypt(String data, String key) throws Exception {
SecretKeySpec secretKeySpec = new SecretKeySpec(Base64.decode(key), ALGORITHM);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
byte[] encryptedBytes = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
return Base64.encode(encryptedBytes);
}
private static String decrypt(String encryptedData, String key) throws Exception {
SecretKeySpec secretKeySpec = new SecretKeySpec(Base64.decode(key), ALGORITHM);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
byte[] decryptedBytes = cipher.doFinal(Base64.decode(encryptedData));
return new String(decryptedBytes, StandardCharsets.UTF_8);
}
@Override
public void licencesDiscernByCodeImage(MultipartFile file) throws IOException {
licenceDiscernByCodeStr(QrCodeUtil.decode(file.getInputStream()));
@ -72,22 +46,25 @@ public class LicencesServiceImpl implements LicencesService {
}
try {
//todo 数据校验
JSONObject codeJson = JSONObject.parseObject(encryptionStr);
String secretKey = codeJson.getString("secretKey");
if (Util.isNullOrEmpty(secretKey)) {
JSONObject codeJson = new JSONObject(encryptionStr);
String tmpSecretKey = codeJson.getStr("secretKey");
if (Util.isNullOrEmpty(tmpSecretKey)) {
throw exception(ENCRYPTION_STR_FORMAT_IS_ERROR);
}
String dataStr = codeJson.getString("data");
ModuleAuthenUtils.secretKey = tmpSecretKey;
String dataStr = codeJson.getStr("data");
if (Util.isNullOrEmpty(dataStr)) {
throw exception(ENCRYPTION_STR_FORMAT_IS_ERROR);
}
JSONArray dataJson = JSONArray.parseArray(decrypt(dataStr, secretKey));
if (dataJson.isEmpty()) {
//todo 需迁移至mq订阅逻辑中
JSONObject tmpJson = new JSONObject(ModuleAuthenUtils.decrypt(dataStr));
if (tmpJson.isEmpty()) {
throw exception(ENCRYPTION_STR_FORMAT_IS_ERROR);
}
ModuleAuthenUtils.moduleExpire = tmpJson;
//todo 更新到redis并使用发布订阅通知其他pods拉取过滤路径
redisTemplate.opsForValue().set(LICENCES_UPDATE, dataJson.toJSONString());
redisTemplate.convertAndSend(LICENCES_UPDATE, 1);
redisTemplate.opsForValue().set(LICENCES_UPDATE, ModuleAuthenUtils.moduleExpire.toString());
redisTemplate.convertAndSend(LICENCES_UPDATE, ModuleAuthenUtils.moduleExpire.toString());
} catch (Exception e) {
throw exception(500, e);
}
@ -95,22 +72,20 @@ public class LicencesServiceImpl implements LicencesService {
@Override
public void generateLicence(GenerateLicenceReqVO req, HttpServletResponse response) throws Exception {
//todo 数据准备
LicencesMessage licencesMessage = new LicencesMessage() {{
String secretKey = generateKey();
String secretKey = ModuleAuthenUtils.generateKey();
setSecretKey(secretKey);
List data = new ArrayList();
MD5 md5 = MD5.create();
//todo 从数据库表中取业主各子系统到期时间,路径通过拦截器获取第一层进行MD5验证,时间只能用对称加密解析后做对比
data.add(new JSONObject(){{
put(md5.digestHex("/MES"),encrypt("2025-10-10 00:00:00",secretKey));
}});
data.add(new JSONObject(){{
put(md5.digestHex("/WMS"),encrypt("2025-10-10 00:00:00",secretKey));
}});
setData(encrypt(JSONObject.toJSONString(data),secretKey));
JSONObject modules = new JSONObject(){{
put(md5.digestHex("/MES"),ModuleAuthenUtils.encrypt("2025-10-10 00:00:00"));
put(md5.digestHex("/WMS"),ModuleAuthenUtils.encrypt("2025-10-10 00:00:00"));
}};
setData(ModuleAuthenUtils.encrypt(modules.toString()));
}};
//todo 生成二维码
QrConfig config = new QrConfig(300, 300);
config.setErrorCorrection(com.google.zxing.qrcode.decoder.ErrorCorrectionLevel.M); // 设置纠错级别
QrCodeUtil.generate(JSONObject.toJSONString(licencesMessage), config, "", response.getOutputStream());
QrCodeUtil.generate(new JSONObject(licencesMessage).toString(), config, "", response.getOutputStream());
}
}

Loading…
Cancel
Save