diff --git a/common/pom.xml b/common/pom.xml index 5679795..06bb8e7 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -19,6 +19,24 @@ spring-boot-starter-web provided + + + org.springframework.boot + spring-boot-starter-data-jpa + provided + + + + org.springframework.boot + spring-boot-starter-validation + provided + + + + com.fasterxml.jackson.core + jackson-annotations + provided + io.springfox diff --git a/common/src/main/java/com/usthe/common/support/SpringContextHolder.java b/common/src/main/java/com/usthe/common/support/SpringContextHolder.java new file mode 100644 index 0000000..484215d --- /dev/null +++ b/common/src/main/java/com/usthe/common/support/SpringContextHolder.java @@ -0,0 +1,48 @@ +package com.usthe.common.support; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * Spring的ApplicationContext的持有者,可以用静态方法的方式获取spring容器中的bean + * @author tomsun28 + * @date 21:07 2018/4/18 + */ +@Component +public class SpringContextHolder implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + set(applicationContext); + } + + private static void set(ApplicationContext applicationContext) { + SpringContextHolder.applicationContext = applicationContext; + } + + public static ApplicationContext getApplicationContext() { + assertApplicationContext(); + return applicationContext; + } + + @SuppressWarnings("unchecked") + public static T getBean(String beanName) { + assertApplicationContext(); + return (T) applicationContext.getBean(beanName); + } + + public static T getBean(Class tClass) { + assertApplicationContext(); + return (T) applicationContext.getBean(tClass); + } + + private static void assertApplicationContext() { + if (null == SpringContextHolder.applicationContext) { + throw new RuntimeException("applicationContext为空,请检查是否注入springContextHolder"); + } + } +} diff --git a/common/src/main/java/com/usthe/common/support/valid/EmailParamValidator.java b/common/src/main/java/com/usthe/common/support/valid/EmailParamValidator.java new file mode 100644 index 0000000..748130f --- /dev/null +++ b/common/src/main/java/com/usthe/common/support/valid/EmailParamValidator.java @@ -0,0 +1,20 @@ +package com.usthe.common.support.valid; + +import com.usthe.common.util.CommonUtil; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +/** + * email注解数据自定义校验器 + * @author tomsun28 + * @date 2021/11/17 19:44 + */ +public class EmailParamValidator implements ConstraintValidator { + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + // 判断value是否满足ipv4 ipv5 域名 格式 + return CommonUtil.validateEmail(value); + } +} diff --git a/common/src/main/java/com/usthe/common/support/valid/EmailValid.java b/common/src/main/java/com/usthe/common/support/valid/EmailValid.java new file mode 100644 index 0000000..ee36489 --- /dev/null +++ b/common/src/main/java/com/usthe/common/support/valid/EmailValid.java @@ -0,0 +1,29 @@ +package com.usthe.common.support.valid; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * email注解数据自定义校验器注解 + * @author tomsun28 + * @date 2021/11/17 19:42 + */ +@Target({ FIELD, PARAMETER }) +@Retention(RUNTIME) +@Documented +@Constraint(validatedBy = EmailParamValidator.class) +public @interface EmailValid { + + String message() default "Email value is invalid"; + + Class[] groups() default {}; + + Class[] payload() default {}; +} diff --git a/common/src/main/java/com/usthe/common/support/valid/HostParamValidator.java b/common/src/main/java/com/usthe/common/support/valid/HostParamValidator.java new file mode 100644 index 0000000..70119c2 --- /dev/null +++ b/common/src/main/java/com/usthe/common/support/valid/HostParamValidator.java @@ -0,0 +1,20 @@ +package com.usthe.common.support.valid; + +import com.usthe.common.util.IpDomainUtil; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +/** + * host注解数据自定义校验器 + * @author tomsun28 + * @date 2021/11/17 19:44 + */ +public class HostParamValidator implements ConstraintValidator { + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + // 判断value是否满足ipv4 ipv5 域名 格式 + return IpDomainUtil.validateIpDomain(value); + } +} diff --git a/common/src/main/java/com/usthe/common/support/valid/HostValid.java b/common/src/main/java/com/usthe/common/support/valid/HostValid.java new file mode 100644 index 0000000..68a8b95 --- /dev/null +++ b/common/src/main/java/com/usthe/common/support/valid/HostValid.java @@ -0,0 +1,29 @@ +package com.usthe.common.support.valid; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * host注解数据自定义校验器注解 + * @author tomsun28 + * @date 2021/11/17 19:42 + */ +@Target({ FIELD, PARAMETER }) +@Retention(RUNTIME) +@Documented +@Constraint(validatedBy = HostParamValidator.class) +public @interface HostValid { + + String message() default "Host value is invalid,must ipv4, ipv6 or domain"; + + Class[] groups() default {}; + + Class[] payload() default {}; +} diff --git a/common/src/main/java/com/usthe/common/support/valid/PhoneNumParamValidator.java b/common/src/main/java/com/usthe/common/support/valid/PhoneNumParamValidator.java new file mode 100644 index 0000000..28f1adb --- /dev/null +++ b/common/src/main/java/com/usthe/common/support/valid/PhoneNumParamValidator.java @@ -0,0 +1,20 @@ +package com.usthe.common.support.valid; + +import com.usthe.common.util.CommonUtil; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +/** + * PhoneNum注解数据自定义校验器 + * @author tomsun28 + * @date 2021/11/17 19:44 + */ +public class PhoneNumParamValidator implements ConstraintValidator { + + @Override + public boolean isValid(String value, ConstraintValidatorContext context) { + // 判断value是否满足ipv4 ipv5 域名 格式 + return CommonUtil.validatePhoneNum(value); + } +} diff --git a/common/src/main/java/com/usthe/common/support/valid/PhoneNumValid.java b/common/src/main/java/com/usthe/common/support/valid/PhoneNumValid.java new file mode 100644 index 0000000..f8f374b --- /dev/null +++ b/common/src/main/java/com/usthe/common/support/valid/PhoneNumValid.java @@ -0,0 +1,29 @@ +package com.usthe.common.support.valid; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * phoneNum注解数据自定义校验器注解 + * @author tomsun28 + * @date 2021/11/17 19:42 + */ +@Target({ FIELD, PARAMETER }) +@Retention(RUNTIME) +@Documented +@Constraint(validatedBy = PhoneNumParamValidator.class) +public @interface PhoneNumValid { + + String message() default "Phone num value is invalid"; + + Class[] groups() default {}; + + Class[] payload() default {}; +} diff --git a/common/src/main/java/com/usthe/common/util/AesUtil.java b/common/src/main/java/com/usthe/common/util/AesUtil.java index 5df5507..d6220bd 100644 --- a/common/src/main/java/com/usthe/common/util/AesUtil.java +++ b/common/src/main/java/com/usthe/common/util/AesUtil.java @@ -1,7 +1,6 @@ package com.usthe.common.util; import lombok.extern.slf4j.Slf4j; -import org.apache.tomcat.util.codec.binary.Base64; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; @@ -9,6 +8,7 @@ import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.security.NoSuchAlgorithmException; +import java.util.Base64; /** * AES 对称加密解密工具 @@ -58,7 +58,7 @@ public class AesUtil { //根据密码器的初始化方式--加密:将数据加密 byte[] byteAes = cipher.doFinal(byteEncode); //将加密后的byte[]数据转换为Base64字符串 - return new String(Base64.encodeBase64(byteAes),StandardCharsets.UTF_8); + return new String(Base64.getEncoder().encode(byteAes),StandardCharsets.UTF_8); //将字符串返回 } catch (Exception e) { log.error("密文加密失败"+e.getMessage(),e); @@ -85,27 +85,22 @@ public class AesUtil { //初始化密码器,第一个参数为加密(Encrypt_mode)或者解密(Decrypt_mode)操作,第二个参数为使用的KEY cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(decryptKey.getBytes(StandardCharsets.UTF_8))); //8.将加密并编码base64后的字符串内容base64解码成字节数组 - byte[] bytesContent = Base64.decodeBase64(content); + byte[] bytesContent = Base64.getDecoder().decode(content); /* * 解密 */ byte[] byteDecode = cipher.doFinal(bytesContent); return new String(byteDecode, StandardCharsets.UTF_8); } catch (NoSuchAlgorithmException e) { - log.error("没有指定的加密算法::"+e.getMessage(),e); + log.error("没有指定的加密算法::{}", e.getMessage(),e); } catch (IllegalBlockSizeException e) { - log.error("非法的块大小"+"::"+e.getMessage(),e); - throw new RuntimeException("密文解密失败"); + log.error("非法的块大小::{}", e.getMessage(),e); } catch (NullPointerException e) { - log.error("秘钥解析空指针异常"+"::"+e.getMessage(),e); - throw new RuntimeException("秘钥解析空指针异常"); + log.error("秘钥解析空指针异常::{}", e.getMessage(),e); } catch (Exception e) { - log.error("秘钥AES解析出现未知错误"+"::"+e.getMessage(),e); - throw new RuntimeException("密文解密失败"); + log.error("秘钥AES解析出现未知错误::{}", e.getMessage(),e); } - //如果有错就返null - return null; - + return content; } /** @@ -115,6 +110,6 @@ public class AesUtil { */ public static boolean isCiphertext(String text) { // 根据是否被base64来判断是否已经被加密 - return Base64.isBase64(text); + return Base64Util.isBase64(text); } } diff --git a/common/src/main/java/com/usthe/common/util/Base64Util.java b/common/src/main/java/com/usthe/common/util/Base64Util.java new file mode 100644 index 0000000..bf19514 --- /dev/null +++ b/common/src/main/java/com/usthe/common/util/Base64Util.java @@ -0,0 +1,19 @@ +package com.usthe.common.util; + +import java.util.Base64; + +/** + * base64工具类 + * @author tom + * @date 2022/1/12 12:12 + */ +public class Base64Util { + + public static boolean isBase64(String base64) { + try { + return Base64.getDecoder().decode(base64) != null; + } catch (Exception e) { + return false; + } + } +} diff --git a/common/src/main/java/com/usthe/common/util/CommonConstants.java b/common/src/main/java/com/usthe/common/util/CommonConstants.java index 58a340e..6e6fc35 100644 --- a/common/src/main/java/com/usthe/common/util/CommonConstants.java +++ b/common/src/main/java/com/usthe/common/util/CommonConstants.java @@ -8,10 +8,15 @@ package com.usthe.common.util; public interface CommonConstants { /** - * 响应状态码: 成功 + * 响应状态码: 通用成功 */ byte SUCCESS_CODE = 0x00; + /** + * 响应状态码: 通用失败 + */ + byte FAIL_CODE = 0x0F; + /** * 响应状态码: 参数校验失败 */ @@ -37,6 +42,13 @@ public interface CommonConstants { */ byte MONITOR_LOGIN_FAILED_CODE = 0x05; + /** + * 响应状态码: 注册失败异常 + */ + byte MONITOR_REGISTER_FAILED_CODE = 0x06; + + + /** * 监控状态码: 未管理 */ @@ -126,4 +138,39 @@ public interface CommonConstants { * 可达性对象 */ String REACHABLE = "reachable"; + + /** + * 参数类型 数字 + */ + byte PARAM_TYPE_NUMBER = 0; + + /** + * 参数类型 字符串 + */ + byte PARAM_TYPE_STRING = 1; + + /** + * 参数类型 密码 + */ + byte PARAM_TYPE_PASSWORD = 2; + + /** + * 认证类型 账户密码 + */ + byte AUTH_TYPE_PASSWORD = 1; + + /** + * 认证类型 GITHUB三方登陆 + */ + byte AUTH_TYPE_GITHUB = 2; + + /** + * 认证类型 微信三方登陆 + */ + byte AUTH_TYPE_WEIXIN = 3; + + /** + * 认证类型 GITEE三方登陆 + */ + byte AUTH_TYPE_GITEE = 5; } diff --git a/common/src/main/java/com/usthe/common/util/CommonUtil.java b/common/src/main/java/com/usthe/common/util/CommonUtil.java index ad3bbcb..7b25c28 100644 --- a/common/src/main/java/com/usthe/common/util/CommonUtil.java +++ b/common/src/main/java/com/usthe/common/util/CommonUtil.java @@ -2,6 +2,9 @@ package com.usthe.common.util; import lombok.extern.slf4j.Slf4j; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + /** * 公共工具类 * @author tomsun28 @@ -10,6 +13,12 @@ import lombok.extern.slf4j.Slf4j; @Slf4j public class CommonUtil { + private static final Pattern EMAIL_PATTERN = Pattern.compile("\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*"); + + private static final Pattern PHONE_PATTERN = Pattern.compile("^(((13[0-9])|(15[0-9])|(18[0-9])|(17[0-9]))+\\d{8})?$"); + + private static final int PHONE_LENGTH = 11; + /** * 将字符串str转换为double数字类型 * @param str string @@ -27,4 +36,30 @@ public class CommonUtil { } } + /** + * 邮箱格式校验 + * @param email 邮箱 + * @return 是否校验成功 + */ + public static boolean validateEmail(String email) { + if (email == null || "".equals(email)) { + return false; + } + Matcher m = EMAIL_PATTERN.matcher(email); + return m.find(); + } + + /** + * 手机号格式校验 + * @param phoneNum 手机号 + * @return 是否校验成功 + */ + public static boolean validatePhoneNum(String phoneNum) { + if (phoneNum == null || "".equals(phoneNum) || phoneNum.length() != PHONE_LENGTH) { + return false; + } + Matcher m = PHONE_PATTERN.matcher(phoneNum); + return m.find(); + } + } diff --git a/common/src/main/java/com/usthe/common/util/LruHashMap.java b/common/src/main/java/com/usthe/common/util/LruHashMap.java new file mode 100644 index 0000000..360d59f --- /dev/null +++ b/common/src/main/java/com/usthe/common/util/LruHashMap.java @@ -0,0 +1,25 @@ +package com.usthe.common.util; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * 最近最少使用淘汰算法map + * @author tom + * @date 2021/12/27 14:13 + */ +public class LruHashMap extends LinkedHashMap { + + private int threshold; + + public LruHashMap(int threshold) { + super(16, 0.75f, true); + this.threshold = threshold; + } + + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + return size() > threshold; + } + +} diff --git a/manager/src/main/resources/sureness.yml b/manager/src/main/resources/sureness.yml index 81fb504..18b395d 100644 --- a/manager/src/main/resources/sureness.yml +++ b/manager/src/main/resources/sureness.yml @@ -10,7 +10,7 @@ resourceRole: # load api resource which do not need protected, means them need be excluded. # these api resource can be access by everyone excludedResource: - - /account/auth/form===post + - /account/auth/**===* - /i18n/**===get # web ui 静态资源 - /console/**===get