Эх сурвалжийг харах

Merge branch 'master' of http://124.220.229.80:9093/root/gateway

linxk 1 долоо хоног өмнө
parent
commit
b44cd7b1ec

+ 54 - 32
src/main/java/com/txz/project/filter/AccessGlobalFilter.java

@@ -5,8 +5,10 @@ import com.alibaba.fastjson.JSON;
 import com.txz.cif.dto.UserDTO;
 import com.txz.operating.dto.InterfacesDTO;
 import com.txz.operating.result.Result;
+import com.txz.project.core.ResultGenerator;
 import com.txz.project.dubbo.client.OperatingInterfacesDubboServiceClient;
 import com.txz.project.dubbo.client.UserDubboServiceClient;
+import com.txz.project.util.I18nUtil;
 import io.jsonwebtoken.Claims;
 import io.jsonwebtoken.ExpiredJwtException;
 import io.jsonwebtoken.Jwts;
@@ -42,43 +44,45 @@ import java.util.List;
 
 @Component
 public class AccessGlobalFilter implements GlobalFilter, Ordered {
-
+    
     private static Logger log = LoggerFactory.getLogger(AccessGlobalFilter.class);
-
+    
     // 自定义请求头名称,用于传递用户ID和操作者ID
     private static final String X_CLIENT_TOKEN_USERID = "x-client-token-userId";
     private static final String X_CLIENT_TOKEN_OPERATORID = "x-client-token-operatorId";
-
+    
     // Bearer token 前缀
     private static final String BEARER = "Bearer ";
-
+    
     /**
      * jwt token 密钥,主要用于token解析,签名验证
      */
     @Value("${spring.security.oauth2.jwt.signingKey}")
     private static String signingKey = "txz123456";  // 默认签名密钥,用于JWT token的解析和验证
-
-
+    
+    
     @Value("${signature}")
     private String signature;                                        // 是否启用签名的配置
-
+    
     @Value("${pub.secret}")
     private String pubSecret;                                        // 公钥密钥,用于签名验证
-
+    
     @Value("${interfaces.switch}")
     private String interfacesSwitch;                                // 接口开关配置,控制是否启用接口访问控制
-
+    
     @Resource
     private UserDubboServiceClient userDubboServiceClient;           // 用户服务客户端,用于调用用户相关服务
-
-
+    
+    
     @Resource
     private OperatingInterfacesDubboServiceClient operatingInterfacesDubboServiceClient;  // 接口服务客户端,用于获取接口配置信息
-
+    
     /**
      * 网关过滤器核心方法,处理每个进入网关的请求
+     *
      * @param exchange 当前请求的上下文信息
-     * @param chain 网关过滤器链
+     * @param chain    网关过滤器链
+     *
      * @return 处理结果
      */
     @Override
@@ -89,14 +93,14 @@ public class AccessGlobalFilter implements GlobalFilter, Ordered {
         // 从请求头获取token和请求路径
         String token = request.getHeaders().getFirst("token");
         String servicePath = request.getURI().getPath();
-        
+
         try {
             // 如果是Swagger文档请求,直接放行
-            if (StrUtil.endWith(servicePath,"/v3/api-docs")){
+            if (StrUtil.endWith(servicePath, "/v3/api-docs")) {
                 return chain.filter(exchange);
             }
             // 如果接口开关关闭,直接放行
-            if (StrUtil.equals("off",interfacesSwitch)){
+            if (StrUtil.equals("off", interfacesSwitch)) {
                 return chain.filter(exchange);
             }
             
@@ -104,7 +108,7 @@ public class AccessGlobalFilter implements GlobalFilter, Ordered {
             Result<InterfacesDTO> interfacesDTOResult = operatingInterfacesDubboServiceClient.detailForGateway(servicePath);
             if (!StringUtils.equals("200", interfacesDTOResult.getCode())) {
                 // 接口不存在,返回错误信息
-                return writeErrorResponse(response, "{\"code\":\"512\",\"message\":\"gateway Access Filter -  unknown interfaces :"+servicePath+"\"}");
+                return writeErrorResponse(response, "{\"code\":\"512\",\"message\":\"gateway Access Filter -  unknown interfaces :" + servicePath + "\"}");
             }
             
             InterfacesDTO interfacesDTO = interfacesDTOResult.getData();
@@ -112,24 +116,39 @@ public class AccessGlobalFilter implements GlobalFilter, Ordered {
             if (interfacesDTO.getStatus() != 1) {
                 return writeErrorResponse(response, "{\"code\":\"513\",\"message\":\"gateway Access Filter -  interfaces status is error\"}");
             }
-
+            
             if (interfacesDTO.getAuthorizeType() == 1) {
                 // 登录拦截
-                Triple<Boolean, String, String> tripleUser = getUserIdFromToken(token,request);
-                if(tripleUser.getLeft() == false) {
+                Triple<Boolean, String, String> tripleUser = getUserIdFromToken(token, request);
+                if (tripleUser.getLeft() == false) {
                     log.warn("登录认证失败,请求接口:{},请求IP:{},请求token:{},请求参数:{}", request.getURI().getPath(),
                             getIpAddress(request), token, JSON.toJSONString(request.getQueryParams()));
                     return writeErrorResponse(response, "{\"code\":\"598\",\"message\":\"gateway Access Filter - login validate is false\"}");
                 }
                 
                 UserDTO user = userDubboServiceClient.getUser(Long.parseLong(tripleUser.getMiddle()));
-                if (user == null){
+                if (user == null) {
                     return writeErrorResponse(response, "{\"code\":\"597\",\"message\":\"gateway Access Filter - user is null\"}");
                 }
-                if (user.getStatus() != 1){
+                if (user.getStatus() != 1) {
                     return writeErrorResponse(response, "{\"code\":\"596\",\"message\":\"gateway Access Filter - user status is error\"}");
                 }
                 
+                // 禁止登录
+                if (user.getHasLogin() != 1) {
+                    return writeErrorResponse(response, "{\"code\":\"1062\",\"data\":null,\"message\":\"用户状态异常,请联系管理员\"}");
+                }
+                
+                // 禁止下单
+                if (servicePath.equals("/mall/app/order/add") && user.getHasOrder() != 1) {
+                    return writeErrorResponse(response, "{\"code\":\"1062\",\"data\":null,\"message\":\"用户状态异常,请联系管理员\"}");
+                }
+                
+                // 禁止提现
+                if (servicePath.equals("/cif/api/withdraw/record/add") && user.getHasWithdraw() != 1) {
+                    return writeErrorResponse(response, "{\"code\":\"1062\",\"data\":null,\"message\":\"用户状态异常,请联系管理员\"}");
+                }
+                
                 // 添加请求头
                 ServerHttpRequest mutateRequest = request.mutate()
                         .header(X_CLIENT_TOKEN_USERID, tripleUser.getMiddle())
@@ -137,10 +156,10 @@ public class AccessGlobalFilter implements GlobalFilter, Ordered {
                         .build();
                 ServerWebExchange mutateExchange = exchange.mutate().request(mutateRequest).build();
                 
-                try{
+                try {
                     userDubboServiceClient.updateLastTime(Long.parseLong(tripleUser.getMiddle()));
-                }catch (Exception e){
-                    log.error("更新最后请求时间异常",e);
+                } catch (Exception e) {
+                    log.error("更新最后请求时间异常", e);
                 }
                 
                 if (interfacesDTO.getReturnCodeTranslate() != null) {
@@ -151,7 +170,7 @@ public class AccessGlobalFilter implements GlobalFilter, Ordered {
                 
                 return chain.filter(mutateExchange);
             }
-
+            
             // 设置返回码转换属性
             if (interfacesDTO.getReturnCodeTranslate() != null) {
                 exchange.getAttributes().put("returnCodeTranslate", interfacesDTO.getReturnCodeTranslate());
@@ -166,12 +185,12 @@ public class AccessGlobalFilter implements GlobalFilter, Ordered {
         
         return chain.filter(exchange);
     }
-
+    
     @Override
     public int getOrder() {
         return 0;
     }
-
+    
     private Mono<Void> writeErrorResponse(ServerHttpResponse response, String errorMessage) {
         response.setStatusCode(HttpStatus.OK);
         response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
@@ -179,12 +198,13 @@ public class AccessGlobalFilter implements GlobalFilter, Ordered {
         DataBuffer buffer = response.bufferFactory().wrap(datas);
         return response.writeWith(Mono.just(buffer));
     }
-
+    
     /**
      * 从token中获取用户信息
      *
      * @param token
      * @param request
+     *
      * @return
      */
     private Triple<Boolean, String, String> getUserIdFromToken(String token, ServerHttpRequest request) {
@@ -195,8 +215,8 @@ public class AccessGlobalFilter implements GlobalFilter, Ordered {
             if (token.startsWith(BEARER)) {
                 token = token.substring(6);
             }
-            Claims claims = Jwts.parser().setSigningKey(signingKey).parseClaimsJws(token).getBody();
-            String userId = (String) claims.get("userId");
+            Claims claims = Jwts.parser().setSigningKey(signingKey.getBytes()).parseClaimsJws(token).getBody();
+            String userId = String.valueOf(claims.get("userId"));
             String operatorId = (String) claims.get("operatorId");
             return new ImmutableTriple<>(true, userId, operatorId);
         } catch (ExpiredJwtException eje) {
@@ -207,10 +227,12 @@ public class AccessGlobalFilter implements GlobalFilter, Ordered {
             return new ImmutableTriple<>(false, "", "");
         }
     }
-
+    
     /**
      * 获取Ip地址
+     *
      * @param request
+     *
      * @return
      */
     private String getIpAddress(ServerHttpRequest request) {

+ 45 - 0
src/main/java/com/txz/project/filter/LanguageWebFilter.java

@@ -0,0 +1,45 @@
+package com.txz.project.filter;
+
+
+import com.txz.project.util.LanguageContextHolder;
+import org.springframework.core.Ordered;
+import org.springframework.stereotype.Component;
+import org.springframework.web.server.ServerWebExchange;
+import org.springframework.web.server.WebFilter;
+import org.springframework.web.server.WebFilterChain;
+import reactor.core.publisher.Mono;
+import reactor.util.context.Context;
+
+@Component
+
+public class LanguageWebFilter implements WebFilter,Ordered{
+
+
+    @Override
+    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
+        // 1. 从请求头获取Accept-Language,默认en
+        String acceptLanguage = exchange.getRequest().getHeaders().getFirst("accept-language");
+
+        if (acceptLanguage == null || acceptLanguage.trim().isEmpty()) {
+            acceptLanguage = "en";
+        }
+
+        //        // 1. 设置到ThreadLocal
+        LanguageContextHolder.setLanguage(acceptLanguage);
+
+        // 2. 将语言参数写入Reactor上下文(关键:上下文随异步流传递)
+        return chain.filter(exchange)
+                .contextWrite(Context.of("ACCEPT_LANGUAGE", acceptLanguage))
+                .doFinally(signalType -> {
+                    // 请求结束后清除ThreadLocal
+                    LanguageContextHolder.clear();
+                });
+    }
+
+    @Override
+    public int getOrder() {
+        return Ordered.HIGHEST_PRECEDENCE;
+    }
+}
+
+

+ 2 - 1
src/main/java/com/txz/project/filter/ThrowExceptionFilter.java

@@ -1,5 +1,6 @@
 package com.txz.project.filter;
 
+import com.txz.project.util.I18nUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.cloud.gateway.filter.GatewayFilterChain;
@@ -30,7 +31,7 @@ public class ThrowExceptionFilter implements GlobalFilter, Ordered {
             // 将异常信息放入 exchange attributes 中,供后续处理使用
             exchange.getAttributes().put("error.status_code", HttpStatus.INTERNAL_SERVER_ERROR.value());
             exchange.getAttributes().put("error.exception", e);
-            exchange.getAttributes().put("error.message", "有一些错误发生");
+            exchange.getAttributes().put("error.message", I18nUtil.get("error.message"));
             
             // 继续传递给下一个过滤器处理
             return chain.filter(exchange);

+ 70 - 0
src/main/java/com/txz/project/util/I18nUtil.java

@@ -0,0 +1,70 @@
+package com.txz.project.util;
+
+import org.springframework.context.MessageSource;
+import org.springframework.context.i18n.LocaleContextHolder;
+import org.springframework.stereotype.Component;
+import org.springframework.util.ObjectUtils;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.Resource;
+import java.util.Locale;
+
+/**
+ * 描述: 3、国际化工具类
+ * 版权: Copyright (c) 2020
+ * 公司: XXXX
+ * 作者: yanghj
+ * 版本: 4.0
+ * 创建日期: 2020/9/18 10:31
+ */
+
+@Component
+public class I18nUtil
+{
+
+    @Resource
+    private MessageSource messageSource;
+
+    private static MessageSource staticMessageSource;
+
+    public static String acceptLanguage;
+
+    // 用 @PostConstruct 替代 InitializingBean 接口
+    @PostConstruct
+    public void init() {
+        if (staticMessageSource == null) {
+            I18nUtil.staticMessageSource = this.messageSource;
+        }
+    }
+
+    // 静态 get 方法(同上)
+    public static String get(String msgKey) {
+        try {
+//            ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
+//            String header = sra.getRequest().getHeader("accept-language");
+            String header = LanguageContextHolder.getLanguage();
+          //  String header = acceptLanguage;
+            LocaleContextHolder.setLocale(Locale.US);
+            if(!ObjectUtils.isEmpty(header)) {
+                if ("en".equals(header)) {
+                    LocaleContextHolder.setLocale(Locale.US);
+                } else if ("zh".equals(header)) {
+                    LocaleContextHolder.setLocale(Locale.SIMPLIFIED_CHINESE);
+                } else if ("bd".equals(header)) {
+                    Locale bengaliLocale = new Locale("bn", "BD"); //孟加拉文
+                    LocaleContextHolder.setLocale(bengaliLocale);
+                }
+            }
+
+            return staticMessageSource.getMessage(msgKey, null, LocaleContextHolder.getLocale());
+        } catch (Exception e) {
+            return msgKey;
+        }
+    }
+
+
+
+
+
+
+}

+ 22 - 0
src/main/java/com/txz/project/util/LanguageContextHolder.java

@@ -0,0 +1,22 @@
+package com.txz.project.util;
+
+public class LanguageContextHolder {
+    // ThreadLocal存储当前请求的语言
+    // 存储当前线程的语言参数
+    private static final ThreadLocal<String> LANGUAGE_HOLDER = new ThreadLocal<>();
+
+    // 设置语言(从Reactor上下文同步时调用)
+    public static void setLanguage(String language) {
+        LANGUAGE_HOLDER.set(language);
+    }
+
+    // 获取当前线程的语言
+    public static String getLanguage() {
+        return LANGUAGE_HOLDER.get();
+    }
+
+    // 清除ThreadLocal(必须调用)
+    public static void clear() {
+        LANGUAGE_HOLDER.remove();
+    }
+}

+ 5 - 0
src/main/resources/bootstrap.properties

@@ -102,3 +102,8 @@ spring.cloud.gateway.globalcors.cors-configurations.[/**].allowedMethods[1]=POST
 spring.cloud.gateway.globalcors.cors-configurations.[/**].allowedMethods[2]=PUT
 spring.cloud.gateway.globalcors.cors-configurations.[/**].allowedMethods[3]=OPTIONS
 spring.cloud.gateway.globalcors.cors-configurations.[/**].allowedMethods[4]=DELETE
+
+
+spring.messages.basename=i18n/messages,i18n/messages_zh_CN
+spring.messages.encoding=UTF-8
+spring.messages.cache-duration=0

+ 16 - 0
src/main/resources/i18n/error.properties

@@ -0,0 +1,16 @@
+BUSINESS_ERROR_001=\u8BF7\u68C0\u67E5\u624B\u673A\u53F7\u662F\u5426\u6B63\u786E
+BUSINESS_ERROR_002=\u624B\u673A\u53F7\u548C\u5BC6\u7801\u4E0D\u5339\u914D
+BUSINESS_ERROR_003=APP\u767B\u5F55\u6388\u6743\u5931\u8D25
+BUSINESS_ERROR_004=AccountKit \u767B\u5F55\u5931\u8D25\uFF0C\u8BF7\u91CD\u65B0\u9A8C\u8BC1
+BUSINESS_ERROR_005=\u624B\u673A\u53F7\u5DF2\u6CE8\u518C
+BUSINESS_ERROR_006=\u9A8C\u8BC1\u5DF2\u8FC7\u671F
+BUSINESS_ERROR_007=\u9A8C\u8BC1\u7801\u9519\u8BEF
+BUSINESS_ERROR_008=\u8BBE\u7F6E\u5BC6\u7801\u5931\u8D25
+BUSINESS_ERROR_009=\u8BF7\u91CD\u65B0\u9A8C\u8BC1code
+BUSINESS_ERROR_010=Facebook \u767B\u5F55\u5931\u8D25
+BUSINESS_ERROR_011=\u6B64 Facebook \u5DF2\u88AB\u5176\u4ED6\u8D26\u53F7\u4F7F\u7528
+BUSINESS_ERROR_012=\u8BF7\u60A8\u5148\u767B\u9646
+BUSINESS_ERROR_013=\u7CFB\u7EDF\u5185\u90E8\u5F02\u5E38\uFF0Csource \u8BF7\u6C42\u53C2\u6570\u4E0D\u5408\u6CD5
+BUSINESS_ERROR_014=\u624B\u673A\u53F7\u5DF2\u5173\u8054\u8FC7\u5176\u4ED6 Facebook \u8D26\u53F7\uFF0C\u8BF7\u6362\u4E00\u4E2A\u53F7\u7801\u8BD5\u8BD5
+
+PARAMETER_ERROR_001=\u65E0\u6548\u7684\u53C2\u6570

+ 16 - 0
src/main/resources/i18n/error_in_ID.properties

@@ -0,0 +1,16 @@
+BUSINESS_ERROR_001=Silakan periksa apakah nomor telepon sudah benar
+BUSINESS_ERROR_002=Nomor telepon dan kata sandi tidak cocok
+BUSINESS_ERROR_003=Otorisasi login APP gagal
+BUSINESS_ERROR_004=Login Akun gagal, harap verifikasi ulang
+BUSINESS_ERROR_005=Nomor anda telah diregistrasi
+BUSINESS_ERROR_006=Verifikasi telah kedaluwarsa
+BUSINESS_ERROR_007=Kode verifikasi salah
+BUSINESS_ERROR_008=Gagal mengatur kata sandi
+BUSINESS_ERROR_009=Harap verifikasi ulang kodenya
+BUSINESS_ERROR_010=Verifikasi Facebook gagal
+BUSINESS_ERROR_011=Akun Facebook ini telah digunakan oleh akun lain
+BUSINESS_ERROR_012=Silahkan login
+BUSINESS_ERROR_013=Kesalahan internal sistem
+BUSINESS_ERROR_014=Nomor telepon ini telah terhubung dengan akun Facebook, silahkan ganti nomor untuk mencoba
+
+PARAMETER_ERROR_001=Parameter tidak valid

+ 0 - 0
src/main/resources/i18n/messages.properties


+ 0 - 0
src/main/resources/i18n/messages_bn_BD.properties


+ 14 - 0
src/main/resources/i18n/messages_en_US.properties

@@ -0,0 +1,14 @@
+
+ResultCode.SUCCESS=success
+ResultCode.FAIL=failure
+ResultCode.UNAUTHORIZED=unauthenticated signature error
+ResultCode.NOT_FOUND=interface does not exist
+ResultCode.INTERNAL_SERVER_ERROR=internal server error
+
+success=success
+failure=failure
+unauthenticated.signature.error=unauthenticated signature error
+interface.does.not.exist=interface does not exist
+internal.server.error=internal server error
+
+error.message=some errors have occurred

+ 16 - 0
src/main/resources/i18n/messages_zh_CN.properties

@@ -0,0 +1,16 @@
+
+ResultCode.SUCCESS=\u6210\u529F
+ResultCode.FAIL=\u5931\u8D25
+ResultCode.UNAUTHORIZED=\u672A\u8BA4\u8BC1\uFF08\u7B7E\u540D\u9519\u8BEF\uFF09
+ResultCode.NOT_FOUND=\u63A5\u53E3\u4E0D\u5B58\u5728
+ResultCode.INTERNAL_SERVER_ERROR=\u670D\u52A1\u5668\u5185\u90E8\u9519\u8BEF
+
+
+success=\u6210\u529F
+failure=\u5931\u8D25
+unauthenticated.signature.error=\u672A\u8BA4\u8BC1\uFF08\u7B7E\u540D\u9519\u8BEF\uFF09
+interface.does.not.exist=\u63A5\u53E3\u4E0D\u5B58\u5728
+internal.server.error=\u670D\u52A1\u5668\u5185\u90E8\u9519\u8BEF
+
+error.message=\u6709\u4E00\u4E9B\u9519\u8BEF\u53D1\u751F
+