Browse Source

feat: 增加系统锁定功能

zengweijie 3 years ago
parent
commit
89e06fa137

+ 2 - 5
src/main/java/com/inspur/smsb/gateway/SmsbGatewayApplication.java

@@ -3,12 +3,8 @@ package com.inspur.smsb.gateway;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration;
-import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
-import org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient;
-import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.scheduling.annotation.EnableScheduling;
 import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.server.WebSession;
-import reactor.core.publisher.Mono;
 
 /**
  * 网关服务
@@ -17,6 +13,7 @@ import reactor.core.publisher.Mono;
  */
 @SpringBootApplication(exclude = ReactiveUserDetailsServiceAutoConfiguration.class)
 @RestController
+@EnableScheduling
 public class SmsbGatewayApplication {
     public static void main(String[] args) {
         SpringApplication.run(SmsbGatewayApplication.class, args);

+ 21 - 0
src/main/java/com/inspur/smsb/gateway/dto/license/LicenseDto.java

@@ -0,0 +1,21 @@
+package com.inspur.smsb.gateway.dto.license;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * @author zengweijie
+ * @version 1.0
+ * @date 2022/7/27 13:37
+ **/
+@Data
+public class LicenseDto implements Serializable {
+    private static final long serialVersionUID = 460738581763959036L;
+    Integer duration;
+    Integer account;
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    LocalDateTime lastUpdate;
+}

+ 108 - 0
src/main/java/com/inspur/smsb/gateway/filter/LicenseFilter.java

@@ -0,0 +1,108 @@
+package com.inspur.smsb.gateway.filter;
+
+import com.alibaba.cola.dto.Response;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.inspur.smsb.gateway.dto.license.LicenseDto;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+import org.springframework.cloud.gateway.filter.GlobalFilter;
+import org.springframework.core.Ordered;
+import org.springframework.core.io.buffer.DataBufferFactory;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.MediaType;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Mono;
+
+import javax.annotation.Resource;
+import java.io.*;
+import java.time.LocalDateTime;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * @author zengweijie
+ * @version 1.0
+ * @date 2022/7/27 11:20
+ **/
+@Slf4j
+@Component
+public class LicenseFilter implements GlobalFilter, Ordered {
+    @Resource
+    private ObjectMapper objectMapper;
+    private final AtomicBoolean sysLocked = new AtomicBoolean(false);
+    private final AtomicBoolean timeRollBack = new AtomicBoolean(false);
+    private static final int DEFAULT_DURATION = 60;
+    private static final int STEP = 5;
+    @Value("${license-dir}")
+    private String licenseDir = "D:\\workStation\\工作文件\\测试";
+
+    @Override
+    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+        if (sysLocked.get() || timeRollBack.get()) {
+            ServerHttpResponse response = exchange.getResponse();
+            response.setStatusCode(HttpStatus.UNAUTHORIZED);
+            response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
+            String msg = sysLocked.get() ? "系统已锁定" : "发现时间回退,系统已锁定";
+            return response.writeWith(Mono.fromSupplier(() -> {
+                DataBufferFactory bufferFactory = response.bufferFactory();
+                try {
+                    return bufferFactory.wrap(objectMapper.writeValueAsBytes(Response.buildFailure("401", msg)));
+                } catch (JsonProcessingException e) {
+                    log.error("Error writing response", e);
+                    return bufferFactory.wrap(new byte[0]);
+                }
+            }));
+        }
+        return chain.filter(exchange);
+    }
+
+    @Scheduled(fixedRate = 5, timeUnit = TimeUnit.MINUTES)
+    public void checkSysLocked() throws IOException {
+        if (sysLocked.get() || timeRollBack.get()) {
+            return;
+        }
+        File directory = new File(licenseDir);
+        if (!directory.exists() && !directory.mkdirs()) {
+            return;
+        }
+        File licenseFile = new File(directory.getAbsolutePath() + File.separator + "license.json");
+        if (!licenseFile.exists()) {
+            return;
+        }
+        LicenseDto licenseDto = new LicenseDto();
+        try (BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream(licenseFile))) {
+            if (inputStream.available() > 0) {
+                licenseDto = objectMapper.readValue(inputStream.readAllBytes(), LicenseDto.class);
+            }
+        }
+        LocalDateTime now = LocalDateTime.now();
+        if (Objects.nonNull(licenseDto.getLastUpdate()) && licenseDto.getLastUpdate().isAfter(now)) {
+            timeRollBack.set(true);
+            return;
+        }
+        int duration = Optional.ofNullable(licenseDto.getDuration()).orElse(DEFAULT_DURATION);
+        int account = Optional.ofNullable(licenseDto.getAccount()).orElse(0);
+        if (duration <= account) {
+            sysLocked.set(true);
+            return;
+        }
+        licenseDto.setDuration(duration);
+        licenseDto.setAccount(account + STEP);
+        licenseDto.setLastUpdate(now);
+        try (BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(licenseFile))) {
+            outputStream.write(objectMapper.writeValueAsBytes(licenseDto));
+        }
+    }
+
+    @Override
+    public int getOrder() {
+        return HIGHEST_PRECEDENCE;
+    }
+}