dengsixing 1 year ago
parent
commit
c5213c9e42
30 changed files with 902 additions and 9 deletions
  1. 1 0
      mybatis-flex.config
  2. 35 2
      pom.xml
  3. 3 0
      src/main/java/com/fdkankan/cloud/acl/Application.java
  4. 10 0
      src/main/java/com/fdkankan/cloud/acl/annotation/CheckSignature.java
  5. 10 0
      src/main/java/com/fdkankan/cloud/acl/annotation/SaveLog.java
  6. 99 0
      src/main/java/com/fdkankan/cloud/acl/aop/CheckSignatureAspect.java
  7. 65 0
      src/main/java/com/fdkankan/cloud/acl/aop/SaveLogAspect.java
  8. 21 0
      src/main/java/com/fdkankan/cloud/acl/bean/StsBean.java
  9. 42 0
      src/main/java/com/fdkankan/cloud/acl/config/AliyunConfig.java
  10. 15 0
      src/main/java/com/fdkankan/cloud/acl/config/MyConfigurationCustomizer.java
  11. 7 0
      src/main/java/com/fdkankan/cloud/acl/constant/RedisKey.java
  12. 33 0
      src/main/java/com/fdkankan/cloud/acl/controller/StsController.java
  13. 18 0
      src/main/java/com/fdkankan/cloud/acl/controller/TestController.java
  14. 81 0
      src/main/java/com/fdkankan/cloud/acl/entity/AppConfig.java
  15. 39 0
      src/main/java/com/fdkankan/cloud/acl/entity/AppKeyConfig.java
  16. 72 0
      src/main/java/com/fdkankan/cloud/acl/entity/Log.java
  17. 3 3
      src/main/java/com/fdkankan/cloud/acl/generate/Codegen.java
  18. 14 0
      src/main/java/com/fdkankan/cloud/acl/mapper/AppConfigMapper.java
  19. 14 0
      src/main/java/com/fdkankan/cloud/acl/mapper/AppKeyConfigMapper.java
  20. 14 0
      src/main/java/com/fdkankan/cloud/acl/mapper/LogMapper.java
  21. 16 0
      src/main/java/com/fdkankan/cloud/acl/service/IAppConfigService.java
  22. 16 0
      src/main/java/com/fdkankan/cloud/acl/service/IAppKeyConfigService.java
  23. 14 0
      src/main/java/com/fdkankan/cloud/acl/service/ILogService.java
  24. 14 0
      src/main/java/com/fdkankan/cloud/acl/service/IStsService.java
  25. 23 0
      src/main/java/com/fdkankan/cloud/acl/service/impl/AppConfigServiceImpl.java
  26. 23 0
      src/main/java/com/fdkankan/cloud/acl/service/impl/AppKeyConfigServiceImpl.java
  27. 18 0
      src/main/java/com/fdkankan/cloud/acl/service/impl/LogServiceImpl.java
  28. 172 0
      src/main/java/com/fdkankan/cloud/acl/service/impl/StsServiceImpl.java
  29. 4 4
      src/main/resources/bootstrap-test.yml
  30. 6 0
      src/main/resources/bootstrap.yml

+ 1 - 0
mybatis-flex.config

@@ -0,0 +1 @@
+processor.enable=false

+ 35 - 2
pom.xml

@@ -151,6 +151,7 @@
             <artifactId>mybatis-flex-spring-boot-starter</artifactId>
             <version>1.7.5</version>
         </dependency>
+
         <dependency>
             <groupId>com.mybatis-flex</groupId>
             <artifactId>mybatis-flex-processor</artifactId>
@@ -183,10 +184,42 @@
         </dependency>
 
         <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
+        </dependency>
+
+        <!--nacos 客户端 配置中心-->
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
+        </dependency>
+
+        <dependency>
             <groupId>com.aliyun</groupId>
-            <artifactId>chatbot20220408</artifactId>
-            <version>1.0.5</version>
+            <artifactId>sts20150401</artifactId>
+            <version>1.1.4</version>
         </dependency>
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>tea-openapi</artifactId>
+            <version>0.3.2</version>
+        </dependency>
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>tea-console</artifactId>
+            <version>0.0.1</version>
+        </dependency>
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>tea-util</artifactId>
+            <version>0.2.21</version>
+        </dependency>
+
+<!--        <dependency>-->
+<!--            <groupId>com.aliyun</groupId>-->
+<!--            <artifactId>chatbot20220408</artifactId>-->
+<!--            <version>1.0.5</version>-->
+<!--        </dependency>-->
 
     </dependencies>
 

+ 3 - 0
src/main/java/com/fdkankan/cloud/acl/Application.java

@@ -1,13 +1,16 @@
 package com.fdkankan.cloud.acl;
 
+import com.mybatisflex.annotation.UseDataSource;
 import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
 import org.springframework.context.annotation.ComponentScan;
 
 @SpringBootApplication
 @ComponentScan(basePackages = {"com.fdkankan.*"})
 @MapperScan("com.fdkankan.cloud.acl.mapper")
+@EnableDiscoveryClient
 public class Application {
     public static void main(String[] args) {
         SpringApplication.run(Application.class, args);

+ 10 - 0
src/main/java/com/fdkankan/cloud/acl/annotation/CheckSignature.java

@@ -0,0 +1,10 @@
+package com.fdkankan.cloud.acl.annotation;
+
+import java.lang.annotation.*;
+
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface CheckSignature {
+    String description() default "";
+}

+ 10 - 0
src/main/java/com/fdkankan/cloud/acl/annotation/SaveLog.java

@@ -0,0 +1,10 @@
+package com.fdkankan.cloud.acl.annotation;
+
+import java.lang.annotation.*;
+
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface SaveLog {
+    String description() default "";
+}

+ 99 - 0
src/main/java/com/fdkankan/cloud/acl/aop/CheckSignatureAspect.java

@@ -0,0 +1,99 @@
+package com.fdkankan.cloud.acl.aop;
+
+import cn.hutool.core.codec.Base64;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.fdkankan.cloud.acl.entity.AppConfig;
+import com.fdkankan.cloud.acl.entity.AppKeyConfig;
+import com.fdkankan.cloud.acl.service.IAppConfigService;
+import com.fdkankan.cloud.acl.service.IAppKeyConfigService;
+import com.fdkankan.common.constant.ErrorCode;
+import com.fdkankan.common.exception.BusinessException;
+import com.fdkankan.common.util.RsaUtil;
+import com.mybatisflex.core.query.QueryWrapper;
+import lombok.extern.log4j.Log4j2;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.annotation.Pointcut;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.crypto.Cipher;
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.security.KeyFactory;
+import java.security.PrivateKey;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.time.Instant;
+import java.util.Objects;
+
+@Log4j2
+@Aspect
+@Component
+@Order(101)
+public class CheckSignatureAspect {
+
+	@Autowired
+	private IAppConfigService appConfigService;
+	@Autowired
+	private IAppKeyConfigService appKeyConfigService;
+
+	@Pointcut("@annotation(com.fdkankan.cloud.acl.annotation.CheckSignature)")
+	public void CheckSignature() {
+	}
+
+	@Before("CheckSignature()")
+	public void doBefore(JoinPoint joinPoint) throws Exception {
+
+		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+		String signature = request.getHeader("signature");
+		if(StrUtil.isEmpty(signature)){
+			throw new BusinessException(ErrorCode.FAILURE_CODE_3003.code(), "请求头必须携带签名");
+		}
+		String appCode = request.getParameter("appCode");
+		if(StrUtil.isEmpty(appCode)){
+			throw new BusinessException(ErrorCode.FAILURE_CODE_3003.code(), "appCode不能为空");
+		}
+		String timestamp = request.getParameter("timestamp");
+		if(StrUtil.isEmpty(timestamp)){
+			throw new BusinessException(ErrorCode.FAILURE_CODE_3003.code(), "timestamp不能为空");
+		}
+		//时间戳有效时间是10秒
+		Instant now = Instant.now();
+		long epochSecond = now.getEpochSecond();
+		long expiraSecond = Long.valueOf(timestamp) + 10 * 60L;
+		if(expiraSecond < epochSecond){
+			throw new BusinessException(ErrorCode.FAILURE_CODE_3003.code(), "签名已失效");
+		}
+
+		AppConfig appConfig = appConfigService.getByAppCode(appCode);
+		if(Objects.isNull(appConfig)){
+			throw new BusinessException(ErrorCode.FAILURE_CODE_3003);
+		}
+
+		AppKeyConfig appKeyConfig = appKeyConfigService.getByAppConfigId(appConfig.getId());
+		if(Objects.isNull(appKeyConfig)){
+			throw new BusinessException(ErrorCode.FAILURE_CODE_3003);
+		}
+
+		signature = RsaUtil.create(appKeyConfig.getPrivateKey(), null).decryptByPrivateKey(signature);
+
+		log.info("解密:{}", signature);
+		String[] split = signature.split("-");
+		if(split.length != 2){
+			throw new BusinessException(ErrorCode.FAILURE_CODE_3003.code(), "签名不匹配");
+		}
+		String signatureAppCode = split[0];
+		String signatureTimestamp = split[1];
+		if(!appCode.equals(signatureAppCode) || !timestamp.equals(signatureTimestamp)){
+			throw new BusinessException(ErrorCode.FAILURE_CODE_3003.code(), "签名不匹配");
+		}
+
+	}
+
+}

+ 65 - 0
src/main/java/com/fdkankan/cloud/acl/aop/SaveLogAspect.java

@@ -0,0 +1,65 @@
+package com.fdkankan.cloud.acl.aop;
+
+import com.alibaba.fastjson.JSON;
+import com.fdkankan.cloud.acl.entity.Log;
+import com.fdkankan.cloud.acl.service.ILogService;
+import com.fdkankan.web.util.WebUtil;
+import lombok.extern.log4j.Log4j2;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.util.Map;
+
+@Log4j2
+@Aspect
+@Component
+@Order(102)
+public class SaveLogAspect {
+
+	@Autowired
+	private ILogService logService;
+
+	@Pointcut("@annotation(com.fdkankan.cloud.acl.annotation.SaveLog)")
+	public void saveEditLogAspect() {
+	}
+
+	/**
+	 * @param joinPoint
+	 *            切点
+	 * @throws IOException
+	 */
+	@Around("saveEditLogAspect()")
+	public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
+		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
+		String signature = request.getHeader("signature");
+		//获取请求参数
+		Map<String, Object> params = WebUtil.getParameter(joinPoint, request);
+
+		Log log = new Log();
+		log.setIp(WebUtil.getIpAddress(request));
+		log.setUri(request.getRequestURI());
+		log.setMethod(request.getMethod());
+		log.setUserAgent(request.getHeader("User-Agent"));
+		log.setSignature(signature);
+		log.setParams(JSON.toJSONString(params));
+		logService.save(log);
+
+		//放行
+		Object proceed = joinPoint.proceed();
+
+		log.setResult(JSON.toJSONString(proceed));
+		logService.updateById(log);
+
+		return proceed;
+	}
+
+}

+ 21 - 0
src/main/java/com/fdkankan/cloud/acl/bean/StsBean.java

@@ -0,0 +1,21 @@
+package com.fdkankan.cloud.acl.bean;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class StsBean {
+
+    private String accessKeyId;
+    private String accessKeySecret;
+    private String securityToken;
+    private String expiration;
+    private Long expirTimestamp;
+
+
+}

+ 42 - 0
src/main/java/com/fdkankan/cloud/acl/config/AliyunConfig.java

@@ -0,0 +1,42 @@
+package com.fdkankan.cloud.acl.config;
+
+import com.fdkankan.cloud.acl.service.IAppConfigService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class AliyunConfig {
+
+    @Value("${aliyun.cloud.sts.accessKeyId}")
+    private String accessKeyId;
+
+    @Value("${aliyun.cloud.sts.accessKeySecret}")
+    private String accessKeySecret;
+
+    @Value("${aliyun.cloud.sts.endpoint}")
+    private String endpoint;
+
+
+    /**
+     * 使用AK&SK初始化账号Client
+     * @return Client
+     * @throws Exception
+     */
+    @Bean("stsClient")
+    public com.aliyun.sts20150401.Client initClient() throws Exception {
+        // 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378657.html。
+        com.aliyun.teaopenapi.models.Config config =
+                new com.aliyun.teaopenapi.models.Config()
+                // 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。
+                .setAccessKeyId(accessKeyId)
+                // 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
+                .setAccessKeySecret(accessKeySecret)
+                .setEndpoint(endpoint);
+        // Endpoint 请参考 https://api.aliyun.com/product/Sts
+        return new com.aliyun.sts20150401.Client(config);
+    }
+
+
+}

+ 15 - 0
src/main/java/com/fdkankan/cloud/acl/config/MyConfigurationCustomizer.java

@@ -0,0 +1,15 @@
+package com.fdkankan.cloud.acl.config;
+
+import com.mybatisflex.core.mybatis.FlexConfiguration;
+import com.mybatisflex.spring.boot.ConfigurationCustomizer;
+import org.apache.ibatis.logging.stdout.StdOutImpl;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class MyConfigurationCustomizer implements ConfigurationCustomizer {
+
+    @Override
+    public void customize(FlexConfiguration configuration) {
+        configuration.setLogImpl(StdOutImpl.class);
+    }
+}

+ 7 - 0
src/main/java/com/fdkankan/cloud/acl/constant/RedisKey.java

@@ -0,0 +1,7 @@
+package com.fdkankan.cloud.acl.constant;
+
+public class RedisKey {
+
+    public static final String STS_KEY  = "sts:%s";
+
+}

+ 33 - 0
src/main/java/com/fdkankan/cloud/acl/controller/StsController.java

@@ -0,0 +1,33 @@
+package com.fdkankan.cloud.acl.controller;
+
+import com.fdkankan.cloud.acl.annotation.CheckSignature;
+import com.fdkankan.cloud.acl.annotation.SaveLog;
+import com.fdkankan.cloud.acl.bean.StsBean;
+import com.fdkankan.cloud.acl.service.IStsService;
+import com.fdkankan.web.response.ResultData;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/sts")
+public class StsController {
+
+    @Autowired
+    private IStsService stsService;
+
+    /**
+     * 获取临时身份凭证(STS Token)
+     * @param appCode
+     * @param timestamp
+     * @return
+     */
+    @CheckSignature
+    @SaveLog
+    @GetMapping("/assumeRole")
+    public ResultData assumeRole(String appCode, Long timestamp){
+        return ResultData.ok(stsService.getAssumeRole(appCode));
+    }
+
+}

+ 18 - 0
src/main/java/com/fdkankan/cloud/acl/controller/TestController.java

@@ -0,0 +1,18 @@
+package com.fdkankan.cloud.acl.controller;
+
+import com.fdkankan.web.response.ResultData;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@RequestMapping("/test")
+public class TestController {
+
+
+    @GetMapping("test")
+    public ResultData test(){
+        return ResultData.ok();
+    }
+
+}

+ 81 - 0
src/main/java/com/fdkankan/cloud/acl/entity/AppConfig.java

@@ -0,0 +1,81 @@
+package com.fdkankan.cloud.acl.entity;
+
+import com.mybatisflex.annotation.Column;
+import com.mybatisflex.annotation.Id;
+import com.mybatisflex.annotation.KeyType;
+import com.mybatisflex.annotation.Table;
+import java.io.Serializable;
+import java.sql.Timestamp;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 应用配置表 实体类。
+ *
+ * @author dsx
+ * @since 2024-03-14
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@Table(value = "t_app_config")
+public class AppConfig implements Serializable {
+
+    @Id(keyType = KeyType.Auto)
+    private Integer id;
+
+    /**
+     * 应用名称
+     */
+    private String appName;
+
+    /**
+     * 应用编号
+     */
+    private String appCode;
+
+    /**
+     * 公钥
+     */
+    private String publicKey;
+
+    /**
+     * 可以开通的权限(为空时,跟随ram角色)
+     */
+    private String policy;
+
+    /**
+     * 要扮演的 RAM 角色 ARN
+     */
+    private String roleArn;
+
+    /**
+     * 角色会话名称
+     */
+    private String roleSessionName;
+
+    /**
+     * token有效期
+     */
+    private Long durationSeconds;
+
+    /**
+     * 是否删除
+     */
+    @Column(isLogicDelete = true)
+    private Boolean isDelete;
+
+    /**
+     * 创建时间
+     */
+    private Timestamp createTime;
+
+    /**
+     * 更新时间
+     */
+    private Timestamp updateTime;
+
+}

+ 39 - 0
src/main/java/com/fdkankan/cloud/acl/entity/AppKeyConfig.java

@@ -0,0 +1,39 @@
+package com.fdkankan.cloud.acl.entity;
+
+import com.mybatisflex.annotation.Id;
+import com.mybatisflex.annotation.KeyType;
+import com.mybatisflex.annotation.Table;
+import java.io.Serializable;
+import java.sql.Timestamp;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 密钥对配置表 实体类。
+ *
+ * @author dsx
+ * @since 2024-03-22
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@Table(value = "t_app_key_config")
+public class AppKeyConfig implements Serializable {
+
+    @Id(keyType = KeyType.Auto)
+    private Integer id;
+
+    private Integer appCofigId;
+
+    private String publicKey;
+
+    private String privateKey;
+
+    private Timestamp createTime;
+
+    private Timestamp updateTime;
+
+}

+ 72 - 0
src/main/java/com/fdkankan/cloud/acl/entity/Log.java

@@ -0,0 +1,72 @@
+package com.fdkankan.cloud.acl.entity;
+
+import com.mybatisflex.annotation.Id;
+import com.mybatisflex.annotation.KeyType;
+import com.mybatisflex.annotation.Table;
+import java.io.Serializable;
+import java.sql.Timestamp;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * 请求日志 实体类。
+ *
+ * @author dsx
+ * @since 2024-03-25
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+@Table(value = "t_log")
+public class Log implements Serializable {
+
+    /**
+     * 主键
+     */
+    @Id(keyType = KeyType.Auto)
+    private Long id;
+
+    /**
+     * ip
+     */
+    private String ip;
+
+    /**
+     * 请求url
+     */
+    private String uri;
+
+    /**
+     * 请求方式
+     */
+    private String method;
+
+    /**
+     * 用户代理信息
+     */
+    private String userAgent;
+
+    /**
+     * 秘钥
+     */
+    private String signature;
+
+    /**
+     * 请求参数
+     */
+    private String params;
+
+    /**
+     * 响应
+     */
+    private String result;
+
+    /**
+     * 创建时间
+     */
+    private Timestamp createTime;
+
+}

+ 3 - 3
src/main/java/com/fdkankan/cloud/acl/generate/Codegen.java

@@ -13,11 +13,11 @@ public class Codegen {
     public static void main(String[] args) {
         //配置数据源
         HikariDataSource dataSource = new HikariDataSource();
-        dataSource.setJdbcUrl("jdbc:mysql://120.24.144.164:3306/4dkankan_center_renderer");
+        dataSource.setJdbcUrl("jdbc:mysql://120.24.144.164:3306/4dkankan_center_cloud_acl");
         dataSource.setUsername("root");
         dataSource.setPassword("4Dage@4Dage#@168");
 
-        String[] tables = new String[]{"t_scene"};//,"t_scene_offline_package_push","t_department_camera"
+        String[] tables = new String[]{"t_log"};//,"t_scene_offline_package_push","t_department_camera"
 
                 //创建配置内容,两种风格都可以。
         GlobalConfig globalConfig = createGlobalConfigUseStyle1(tables);
@@ -37,7 +37,7 @@ public class Codegen {
         globalConfig.setEntityOverwriteEnable(true);
 
         //设置根包
-        globalConfig.setBasePackage("com.fdkankan.renderer");
+        globalConfig.setBasePackage("com.fdkankan.cloud.acl");
 
         //设置表前缀和只生成哪些表
         globalConfig.setTablePrefix("t_");

+ 14 - 0
src/main/java/com/fdkankan/cloud/acl/mapper/AppConfigMapper.java

@@ -0,0 +1,14 @@
+package com.fdkankan.cloud.acl.mapper;
+
+import com.mybatisflex.core.BaseMapper;
+import com.fdkankan.cloud.acl.entity.AppConfig;
+
+/**
+ * 应用配置表 映射层。
+ *
+ * @author dsx
+ * @since 2024-03-14
+ */
+public interface AppConfigMapper extends BaseMapper<AppConfig> {
+
+}

+ 14 - 0
src/main/java/com/fdkankan/cloud/acl/mapper/AppKeyConfigMapper.java

@@ -0,0 +1,14 @@
+package com.fdkankan.cloud.acl.mapper;
+
+import com.mybatisflex.core.BaseMapper;
+import com.fdkankan.cloud.acl.entity.AppKeyConfig;
+
+/**
+ * 密钥对配置表 映射层。
+ *
+ * @author dsx
+ * @since 2024-03-22
+ */
+public interface AppKeyConfigMapper extends BaseMapper<AppKeyConfig> {
+
+}

+ 14 - 0
src/main/java/com/fdkankan/cloud/acl/mapper/LogMapper.java

@@ -0,0 +1,14 @@
+package com.fdkankan.cloud.acl.mapper;
+
+import com.mybatisflex.core.BaseMapper;
+import com.fdkankan.cloud.acl.entity.Log;
+
+/**
+ * 请求日志 映射层。
+ *
+ * @author dsx
+ * @since 2024-03-25
+ */
+public interface LogMapper extends BaseMapper<Log> {
+
+}

+ 16 - 0
src/main/java/com/fdkankan/cloud/acl/service/IAppConfigService.java

@@ -0,0 +1,16 @@
+package com.fdkankan.cloud.acl.service;
+
+import com.mybatisflex.core.service.IService;
+import com.fdkankan.cloud.acl.entity.AppConfig;
+
+/**
+ * 应用配置表 服务层。
+ *
+ * @author dsx
+ * @since 2024-03-14
+ */
+public interface IAppConfigService extends IService<AppConfig> {
+
+    AppConfig getByAppCode(String appCode);
+
+}

+ 16 - 0
src/main/java/com/fdkankan/cloud/acl/service/IAppKeyConfigService.java

@@ -0,0 +1,16 @@
+package com.fdkankan.cloud.acl.service;
+
+import com.mybatisflex.core.service.IService;
+import com.fdkankan.cloud.acl.entity.AppKeyConfig;
+
+/**
+ * 密钥对配置表 服务层。
+ *
+ * @author dsx
+ * @since 2024-03-22
+ */
+public interface IAppKeyConfigService extends IService<AppKeyConfig> {
+
+    AppKeyConfig getByAppConfigId(int appConfigId);
+
+}

+ 14 - 0
src/main/java/com/fdkankan/cloud/acl/service/ILogService.java

@@ -0,0 +1,14 @@
+package com.fdkankan.cloud.acl.service;
+
+import com.mybatisflex.core.service.IService;
+import com.fdkankan.cloud.acl.entity.Log;
+
+/**
+ * 请求日志 服务层。
+ *
+ * @author dsx
+ * @since 2024-03-25
+ */
+public interface ILogService extends IService<Log> {
+
+}

+ 14 - 0
src/main/java/com/fdkankan/cloud/acl/service/IStsService.java

@@ -0,0 +1,14 @@
+package com.fdkankan.cloud.acl.service;
+
+import com.fdkankan.cloud.acl.bean.StsBean;
+
+import java.util.Map;
+
+public interface IStsService {
+
+    StsBean genAssumeRole(String appCode);
+
+    StsBean getAssumeRole(String appCode);
+
+
+}

+ 23 - 0
src/main/java/com/fdkankan/cloud/acl/service/impl/AppConfigServiceImpl.java

@@ -0,0 +1,23 @@
+package com.fdkankan.cloud.acl.service.impl;
+
+import com.mybatisflex.core.query.QueryWrapper;
+import com.mybatisflex.spring.service.impl.ServiceImpl;
+import com.fdkankan.cloud.acl.entity.AppConfig;
+import com.fdkankan.cloud.acl.mapper.AppConfigMapper;
+import com.fdkankan.cloud.acl.service.IAppConfigService;
+import org.springframework.stereotype.Service;
+
+/**
+ * 应用配置表 服务层实现。
+ *
+ * @author dsx
+ * @since 2024-03-14
+ */
+@Service
+public class AppConfigServiceImpl extends ServiceImpl<AppConfigMapper, AppConfig> implements IAppConfigService {
+
+    @Override
+    public AppConfig getByAppCode(String appCode) {
+        return this.getOne(QueryWrapper.create().eq(AppConfig::getAppCode, appCode));
+    }
+}

+ 23 - 0
src/main/java/com/fdkankan/cloud/acl/service/impl/AppKeyConfigServiceImpl.java

@@ -0,0 +1,23 @@
+package com.fdkankan.cloud.acl.service.impl;
+
+import com.mybatisflex.core.query.QueryWrapper;
+import com.mybatisflex.spring.service.impl.ServiceImpl;
+import com.fdkankan.cloud.acl.entity.AppKeyConfig;
+import com.fdkankan.cloud.acl.mapper.AppKeyConfigMapper;
+import com.fdkankan.cloud.acl.service.IAppKeyConfigService;
+import org.springframework.stereotype.Service;
+
+/**
+ * 密钥对配置表 服务层实现。
+ *
+ * @author dsx
+ * @since 2024-03-22
+ */
+@Service
+public class AppKeyConfigServiceImpl extends ServiceImpl<AppKeyConfigMapper, AppKeyConfig> implements IAppKeyConfigService {
+
+    @Override
+    public AppKeyConfig getByAppConfigId(int appConfigId) {
+        return getOne(new QueryWrapper().eq(AppKeyConfig::getAppCofigId, appConfigId));
+    }
+}

+ 18 - 0
src/main/java/com/fdkankan/cloud/acl/service/impl/LogServiceImpl.java

@@ -0,0 +1,18 @@
+package com.fdkankan.cloud.acl.service.impl;
+
+import com.mybatisflex.spring.service.impl.ServiceImpl;
+import com.fdkankan.cloud.acl.entity.Log;
+import com.fdkankan.cloud.acl.mapper.LogMapper;
+import com.fdkankan.cloud.acl.service.ILogService;
+import org.springframework.stereotype.Service;
+
+/**
+ * 请求日志 服务层实现。
+ *
+ * @author dsx
+ * @since 2024-03-25
+ */
+@Service
+public class LogServiceImpl extends ServiceImpl<LogMapper, Log> implements ILogService {
+
+}

+ 172 - 0
src/main/java/com/fdkankan/cloud/acl/service/impl/StsServiceImpl.java

@@ -0,0 +1,172 @@
+package com.fdkankan.cloud.acl.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.thread.ThreadUtil;
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.aliyun.oss.ClientBuilderConfiguration;
+import com.aliyun.oss.OSS;
+import com.aliyun.oss.OSSClient;
+import com.aliyun.oss.OSSClientBuilder;
+import com.aliyun.oss.common.auth.CredentialsProviderFactory;
+import com.aliyun.oss.common.utils.BinaryUtil;
+import com.aliyun.oss.model.MatchMode;
+import com.aliyun.oss.model.PolicyConditions;
+import com.aliyun.sts20150401.Client;
+import com.aliyun.sts20150401.models.AssumeRoleRequest;
+import com.aliyun.sts20150401.models.AssumeRoleResponse;
+import com.aliyun.sts20150401.models.AssumeRoleResponseBody;
+import com.aliyun.teautil.models.RuntimeOptions;
+import com.aliyuncs.auth.EnvironmentVariableCredentialsProvider;
+import com.fdkankan.cloud.acl.bean.StsBean;
+import com.fdkankan.cloud.acl.constant.RedisKey;
+import com.fdkankan.cloud.acl.entity.AppConfig;
+import com.fdkankan.cloud.acl.service.IAppConfigService;
+import com.fdkankan.cloud.acl.service.IStsService;
+import com.fdkankan.common.constant.ErrorCode;
+import com.fdkankan.common.constant.ServerCode;
+import com.fdkankan.common.exception.BusinessException;
+import com.fdkankan.common.util.DateExtUtil;
+import com.fdkankan.redis.util.RedisUtil;
+import com.mybatisflex.core.query.QueryWrapper;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import com.aliyun.tea.*;
+
+import java.io.File;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+import java.util.concurrent.ThreadPoolExecutor;
+
+@Slf4j
+@Service
+public class StsServiceImpl implements IStsService {
+
+    @Autowired
+    private IAppConfigService appConfigService;
+    @Autowired
+    private Client stsClient;
+    @Autowired
+    private RedisUtil redisUtil;
+
+    public static void main(String[] args) throws Exception {
+
+        // 工程代码泄露可能会导致 AccessKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议使用更安全的 STS 方式,更多鉴权访问方式请参见:https://help.aliyun.com/document_detail/378657.html。
+        com.aliyun.teaopenapi.models.Config config =
+                new com.aliyun.teaopenapi.models.Config()
+                        // 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_ID。
+                        .setAccessKeyId("LTAI5tJnqRzcURptuSVnG57Z")
+                        // 必填,请确保代码运行环境设置了环境变量 ALIBABA_CLOUD_ACCESS_KEY_SECRET。
+                        .setAccessKeySecret("1RomdGaoay2ABIUVSHOMG5HclPWw8D")
+                        .setEndpoint("sts.cn-shenzhen.aliyuncs.com");
+        // Endpoint 请参考 https://api.aliyun.com/product/Sts
+        Client stsClient = new Client(config);
+
+        com.aliyun.sts20150401.models.AssumeRoleRequest assumeRoleRequest = new com.aliyun.sts20150401.models.AssumeRoleRequest()
+                .setDurationSeconds(3600L)
+                .setRoleArn("acs:ram::1899912233141089:role/server-sts")
+                .setRoleSessionName("app_user");
+        //设置权限,如果为空,则默认跟随rolearn的权限
+//        if(StrUtil.isNotEmpty(appConfig.getPolicy())){
+//            assumeRoleRequest.setPolicy(appConfig.getPolicy());
+//        }
+
+        for (int i = 0; i < 200; i++){
+            new Thread(new Runnable() {
+                @Override
+                public void run() {
+                    RuntimeOptions runtime = new RuntimeOptions();
+                    AssumeRoleResponse resp = null;
+
+                    while (Objects.isNull(resp)){
+                        resp = get(assumeRoleRequest, runtime);
+                        if(Objects.isNull(resp)){
+                            try {
+                                Thread.sleep(500L);
+                            } catch (InterruptedException e) {
+                                throw new RuntimeException(e);
+                            }
+                        }
+                    }
+                    System.out.println(JSON.toJSONString(resp));
+                }
+                public AssumeRoleResponse get(AssumeRoleRequest assumeRoleRequest, RuntimeOptions runtime){
+                    AssumeRoleResponse assumeRoleResponse = null;
+                    try {
+                        assumeRoleResponse = stsClient.assumeRoleWithOptions(assumeRoleRequest, runtime);
+                    } catch (Exception e) {
+                        System.out.println("请求失败");
+                    }
+                    return assumeRoleResponse;
+                }
+
+            }).start();
+        }
+    }
+
+
+
+    @Override
+    public StsBean genAssumeRole(String appCode) {
+
+        AppConfig appConfig = appConfigService.getByAppCode(appCode);
+
+        com.aliyun.sts20150401.models.AssumeRoleRequest assumeRoleRequest = new com.aliyun.sts20150401.models.AssumeRoleRequest()
+                .setDurationSeconds(appConfig.getDurationSeconds())
+                .setRoleArn(appConfig.getRoleArn())
+                .setRoleSessionName(appConfig.getRoleSessionName());
+        //设置权限,如果为空,则默认跟随rolearn的权限
+        if(StrUtil.isNotEmpty(appConfig.getPolicy())){
+            assumeRoleRequest.setPolicy(appConfig.getPolicy());
+        }
+
+        com.aliyun.teautil.models.RuntimeOptions runtime = new com.aliyun.teautil.models.RuntimeOptions();
+        com.aliyun.sts20150401.models.AssumeRoleResponse resp = null;
+        int index = 1;
+        while (Objects.isNull(resp)){
+            try {
+                resp = stsClient.assumeRoleWithOptions(assumeRoleRequest, runtime);
+            } catch (Exception e) {
+                log.error("请求阿里云sts接口失败", e);
+            }
+            if(++index > 10 || Objects.nonNull(resp)){
+                break;
+            }
+            ThreadUtil.sleep(200L);
+        }
+        if(Objects.isNull(resp)){
+            throw new BusinessException(ErrorCode.SYSTEM_BUSY);
+        }
+
+        String accessKeyId = resp.getBody().getCredentials().getAccessKeyId();
+        String accessKeySecret = resp.getBody().getCredentials().getAccessKeySecret();
+        String securityToken = resp.getBody().getCredentials().getSecurityToken();
+        String expiration =  this.converToBjTime(resp.getBody().getCredentials().getExpiration());
+        long expirTimestamp = DateUtil.parse(expiration, DateExtUtil.dateStyle).getTime()/1000;
+
+        return StsBean.builder().accessKeyId(accessKeyId).accessKeySecret(accessKeySecret).securityToken(securityToken).expiration(expiration).expirTimestamp(expirTimestamp).build();
+
+    }
+
+    public String converToBjTime(String dateStr) {
+        Instant utcTime = Instant.parse(dateStr);
+        ZoneId beijingZoneId = ZoneId.of("Asia/Shanghai");
+        ZonedDateTime beijingTime = utcTime.atZone(beijingZoneId);
+        return beijingTime.format(DateTimeFormatter.ofPattern(DateExtUtil.dateStyle));
+    }
+
+    @Override
+    public StsBean getAssumeRole(String appCode) {
+        //调用阿里云接口生成
+        StsBean stsBean = this.genAssumeRole(appCode);
+        return stsBean;
+    }
+}

+ 4 - 4
src/main/resources/bootstrap-test.yml

@@ -12,10 +12,10 @@ spring:
           - data-id: common-redis-config.yaml
             group: DEFAULT_GROUP
             refresh: true
-
-          - data-id: common-db-config.yaml
-            group: DEFAULT_GROUP
-            refresh: true
+#
+#          - data-id: common-db-config.yaml
+#            group: DEFAULT_GROUP
+#            refresh: true
       discovery:
         namespace: ${spring.cloud.nacos.namespace}
 

+ 6 - 0
src/main/resources/bootstrap.yml

@@ -1,3 +1,9 @@
 spring:
   profiles:
     active: test
+
+jasypt:
+  encryptor:
+    password: xxx #盐
+    algorithm: PBEWithMD5AndDES
+    iv-generator-classname: org.jasypt.iv.NoIvGenerator