lixing 4 роки тому
батько
коміт
c70b22d893

+ 18 - 0
fm-common/pom.xml

@@ -74,5 +74,23 @@
             <artifactId>TinyPinyin</artifactId>
             <version>2.0.3.RELEASE</version>
         </dependency>
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-spi</artifactId>
+            <version>2.9.2</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.swagger</groupId>
+            <artifactId>swagger-annotations</artifactId>
+            <version>1.5.22</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger-common</artifactId>
+            <version>2.9.2</version>
+            <scope>compile</scope>
+        </dependency>
     </dependencies>
 </project>

+ 112 - 0
fm-common/src/main/java/com/persagy/fm/common/config/SwaggerDisplayConfig.java

@@ -0,0 +1,112 @@
+package com.persagy.fm.common.config;
+
+import com.fasterxml.classmate.ResolvedType;
+import com.google.common.base.Optional;
+import com.persagy.fm.common.model.annotation.SwaggerDisplayEnum;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.context.annotation.Primary;
+import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.stereotype.Component;
+import springfox.documentation.builders.ModelPropertyBuilder;
+import springfox.documentation.schema.Annotations;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spi.schema.ModelPropertyBuilderPlugin;
+import springfox.documentation.spi.schema.contexts.ModelPropertyContext;
+import springfox.documentation.swagger.schema.ApiModelProperties;
+
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+/**
+ * 类说明
+ *
+ * @author lixing
+ * @version V1.0 2021/4/12 10:43 上午
+ **/
+@Component
+@Primary
+@Slf4j
+public class SwaggerDisplayConfig implements ModelPropertyBuilderPlugin {
+
+
+    @Override
+    public void apply(ModelPropertyContext context) {
+        //获取当前字段的类型
+        final Class fieldType = context.getBeanPropertyDefinition().get().getField().getRawType();
+
+        //为枚举字段设置注释
+        descForEnumFields(context, fieldType);
+    }
+
+    /**
+     * 为枚举字段设置注释
+     */
+    private void descForEnumFields(ModelPropertyContext context, Class fieldType) {
+        Optional<ApiModelProperty> annotation = Optional.absent();
+
+        if (context.getAnnotatedElement().isPresent()) {
+            annotation = annotation
+                    .or(ApiModelProperties.findApiModePropertyAnnotation(context.getAnnotatedElement().get()));
+        }
+        if (context.getBeanPropertyDefinition().isPresent()) {
+            annotation = annotation.or(Annotations.findPropertyAnnotation(
+                    context.getBeanPropertyDefinition().get(),
+                    ApiModelProperty.class));
+        }
+
+        //没有@ApiModelProperty 或者 notes 属性没有值,直接返回
+        if (!annotation.isPresent() || StringUtils.isBlank((annotation.get()).notes())) {
+            return;
+        }
+
+        //@ApiModelProperties中的notes指定的class类型
+        Class rawPrimaryType;
+        try {
+            rawPrimaryType = Class.forName((annotation.get()).notes());
+        } catch (ClassNotFoundException e) {
+            //如果指定的类型无法转化,直接忽略
+            return;
+        }
+
+        //如果对应的class是一个@SwaggerDisplayEnum修饰的枚举类,获取其中的枚举值
+        Object[] subItemRecords = null;
+        SwaggerDisplayEnum swaggerDisplayEnum = AnnotationUtils
+                .findAnnotation(rawPrimaryType, SwaggerDisplayEnum.class);
+        if (null != swaggerDisplayEnum && Enum.class.isAssignableFrom(rawPrimaryType)) {
+            subItemRecords = rawPrimaryType.getEnumConstants();
+        }
+        if (null == subItemRecords) {
+            return;
+        }
+
+
+        final List<String> displayValues = Arrays.stream(subItemRecords).filter(Objects::nonNull).map(item -> {
+            return item.toString() ;
+        }).filter(Objects::nonNull).collect(Collectors.toList());
+
+        String joinText = " (" + String.join("; ", displayValues) + ")";
+        try {
+            Field mField = ModelPropertyBuilder.class.getDeclaredField("description");
+            mField.setAccessible(true);
+            joinText = mField.get(context.getBuilder()) + joinText;
+        } catch (Exception e) {
+            log.error(e.getMessage());
+        }
+
+        final ResolvedType resolvedType = context.getResolver().resolve(fieldType);
+        context.getBuilder().description(joinText).type(resolvedType);
+    }
+
+
+
+    @Override
+    public boolean supports(DocumentationType documentationType) {
+        return true;
+    }
+
+}

+ 8 - 1
fm-common/src/main/java/com/persagy/fm/common/handler/AppContextHandler.java

@@ -5,12 +5,14 @@ import com.persagy.fm.common.constant.AppContextConstants;
 import com.persagy.fm.common.context.AppContext;
 import com.persagy.fm.common.context.DefaultAppContext;
 import com.persagy.fm.common.utils.SecureAES;
+import com.persagy.security.exception.AESDecryptException;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.web.servlet.ModelAndView;
 import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import java.io.UnsupportedEncodingException;
 
 /**
  * @description:
@@ -41,7 +43,12 @@ public class AppContextHandler extends HandlerInterceptorAdapter {
     private void ensureContextInfo(String token){
         // 从token中解析数据
         SecureAES aes = new SecureAES("63499E35378AE1B0733E3FED7F780B68", "C0E7BD39B52A15C7");
-        JSONObject tokenObj = aes.decrypt(token);
+        JSONObject tokenObj = null;
+        try {
+            tokenObj = aes.decryptToken(token);
+        } catch (UnsupportedEncodingException e) {
+            throw new AESDecryptException("token解析异常");
+        }
         // 获取值
         String accountId = tokenObj.getString(AppContextConstants.ACCOUNT_ID);
         String groupCode = tokenObj.getString(AppContextConstants.GROUP_CODE);

+ 19 - 0
fm-common/src/main/java/com/persagy/fm/common/model/annotation/SwaggerDisplayEnum.java

@@ -0,0 +1,19 @@
+package com.persagy.fm.common.model.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * swagger枚举类注解
+ *
+ * @author lixing
+ * @version V1.0 2021/4/12 10:39 上午
+ **/
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface SwaggerDisplayEnum {
+    String type() default "type";
+    String desc() default "desc";
+}

+ 41 - 24
fm-common/src/main/java/com/persagy/fm/common/utils/SecureAES.java

@@ -6,9 +6,11 @@ import cn.hutool.crypto.SecureUtil;
 import cn.hutool.crypto.symmetric.AES;
 import com.alibaba.fastjson.JSONObject;
 import com.persagy.common.utils.StringUtil;
-import com.persagy.fm.common.constant.AppContextConstants;
 import com.persagy.security.exception.AESDecryptException;
 
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
 import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
 
@@ -16,16 +18,19 @@ import java.nio.charset.StandardCharsets;
  * 借助于hutool工具类实现 AES 128/256加密,全局编码UTF-8
  * 
  * @version 1.0.0
+ * @company persagy 
  * @author zhangqiankun
  * @date 2021-03-13 15:29:50
  */
 public class SecureAES {
 	
-	public static void main(String[] args) {
+	public static void main(String[] args) throws UnsupportedEncodingException {
 		SecureAES aes = new SecureAES("63499E35378AE1B0733E3FED7F780B68", "C0E7BD39B52A15C7");
-		String encryptAccount = aes.encrypt("TEST", "PC", "AC123456789");
+		JSONObject object = new JSONObject();
+		object.put("groupCode", "TEST");
+		String encryptAccount = aes.encryptAccount(object);
 		System.out.println("account info encrypt: " + encryptAccount);
-		JSONObject decrypt = aes.decrypt(encryptAccount + ".FSD45SSD1B5D56GB5DFBD");
+		JSONObject decrypt = aes.decryptToken(encryptAccount + ".FSD45SSD1B5D56GB5DFBD");
 		System.out.println("header token decrypt: " + decrypt.toJSONString());
 		JSONObject account = aes.decryptAccount(encryptAccount);
 		System.out.println("account info decrypt: " + account.toJSONString());
@@ -75,28 +80,42 @@ public class SecureAES {
 	}
 	
 	/**
-	 * 加密为16进制,参数组装为json格式数据
+	 * 解密
 	 * 
-	 * @param groupCode
-	 * @param appId
-	 * @param accountId
+	 * @param content
 	 * @return
+	 * @throws UnsupportedEncodingException 
 	 */
-	public String encrypt(String groupCode, String appId, String accountId) {
-		JSONObject object = new JSONObject();
-		object.put(AppContextConstants.GROUP_CODE, groupCode);
-		object.put(AppContextConstants.APP_ID, appId);
-		object.put(AppContextConstants.ACCOUNT_ID, accountId);
-		return aes.encryptHex(object.toJSONString(), CHARSET_UTF_8);
+	public String decryptFromBase64(String content) throws UnsupportedEncodingException {
+		String decode = URLDecoder.decode(content, CHARSET_UTF_8.toString());
+		return aes.decryptStr(decode, CHARSET_UTF_8);
 	}
 	
 	/**
-	 * 解密
+	 * 加密为16进制,参数组装为json格式数据
+	 */
+	public String encryptToBase64(JSONObject object) throws UnsupportedEncodingException {
+		String encryptHex = aes.encryptHex(object.toJSONString(), CHARSET_UTF_8);
+		return URLEncoder.encode(encryptHex, CHARSET_UTF_8.toString());
+	}
+	
+	/**
+	 * 加密为16进制,参数组装为json格式数据,且经过URLEncoder编码
+	 * 
+	 * @throws UnsupportedEncodingException
+	 */
+	public String encryptAccount(JSONObject object) throws UnsupportedEncodingException {
+		String encryptHex = aes.encryptHex(object.toJSONString(), CHARSET_UTF_8);
+		return URLEncoder.encode(encryptHex, CHARSET_UTF_8.toString());
+	}
+	
+	/**
+	 * 解密,且经过URLDecoder编码
 	 * 
-	 * @param headerToken token字符串
-	 * @return token内容,json格式
+	 * @return
+	 * @throws UnsupportedEncodingException 
 	 */
-	public JSONObject decrypt(String headerToken) {
+	public JSONObject decryptToken(String headerToken) throws UnsupportedEncodingException {
 		if (StringUtil.isBlank(headerToken)) {
 			throw new AESDecryptException("token is null");
 		}
@@ -104,19 +123,17 @@ public class SecureAES {
 		if (tokens.length != 2) {
 			throw new AESDecryptException("token invalid parameter");
 		}
-		// 加密的账号信息
-		String encryptAccount = tokens[0];
+		String encryptAccount = tokens[0];			// 加密的账号信息
 		return this.decryptAccount(encryptAccount);
 	}
 	
 	/**
 	 * 解密
 	 * 
-	 * @param encryptAccount
-	 * @return token内容,json格式
+	 * @throws UnsupportedEncodingException
 	 */
-	public JSONObject decryptAccount(String encryptAccount) {
-		String decryptStr = this.decryptStr(encryptAccount);
+	public JSONObject decryptAccount(String encryptAccount) throws UnsupportedEncodingException {
+		String decryptStr = this.decryptFromBase64(encryptAccount);
 		if (StringUtil.isBlank(decryptStr)) {
 			throw new AESDecryptException("AES decrypt failure");
 		}