diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..c6c3316
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,26 @@
+.idea/
+target/
+maven
+*.bak
+*.iml
+*.log
+/logs
+# BlueJ files
+*.ctxt
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+.DS_Store
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+*node_modules
diff --git a/chsm-common/pom.xml b/chsm-common/pom.xml
new file mode 100644
index 0000000..c868223
--- /dev/null
+++ b/chsm-common/pom.xml
@@ -0,0 +1,44 @@
+
+
+ 4.0.0
+
+ com.sunyard.chsm
+ chsm
+ 1.0-SNAPSHOT
+
+
+ chsm-common
+
+
+ 8
+ 8
+ UTF-8
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-validation
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
+ com.baomidou
+ mybatis-plus-boot-starter
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/chsm-common/src/main/java/com/sunyard/utils/DateFormatPattern.java b/chsm-common/src/main/java/com/sunyard/utils/DateFormatPattern.java
new file mode 100644
index 0000000..44e1c02
--- /dev/null
+++ b/chsm-common/src/main/java/com/sunyard/utils/DateFormatPattern.java
@@ -0,0 +1,35 @@
+package com.sunyard.utils;
+
+/**
+ * @author liulu
+ * @version V1.0
+ * @since 2022/12/6
+ */
+public abstract class DateFormatPattern {
+
+ public static final String YYYY = "yyyy";
+ public static final String YYYYMMDD = "yyyyMMdd";
+ public static final String YYYY_MM_DD = "yyyy-MM-dd";
+ public static final String YYYYIMMIDD = "yyyy/MM/dd";
+ public static final String YYYYMMDDHHMM = "yyyyMMddHHmm";
+ public static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
+ public static final String YYYYMMDD_HHMMSS = "yyyyMMdd HHmmss";
+ public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
+ public static final String YYYY_MM_DD_HH_MM = "yyyy-MM-dd HH:mm";
+ public static final String YYYYMMDDHHMMSS_SS = "yyyyMMddHHmmssSSS";
+ public static final String HHMMSS_TIME_FORMAT = "HHmmss";
+ public static final String YYYY_MM_DD_T_HH_MM_SS_Z = "yyyy-MM-dd'T'HH:mm:ss'Z'";
+ public static final String YYYY_MM_DD_HH24_MM_SS = "yyyy-MM-d hh24:mm:ss";
+ public static final String HH_MM = "HH:mm";
+ public static final String HHMM = "HHmm";
+ public static final String HH_MM_SS = "HH:mm:ss";
+ public static final String ZERO_HH_MM_SS = " 00:00:00";
+ public static final String YYMMDD = "yyMMdd";
+ public static final String YYYY_CN_MM_CN_DD_CN = "yyyy年 MM 月 dd 日";
+ public static final String MM_CN_DD_CN = "MM 月 dd 日";
+ public static final String BEGIN_OF_DAY = "yyyy-MM-dd 00:00:00";
+ public static final String END_OF_DAY = "yyyy-MM-dd 23:59:59";
+ public static final String YYYYIMMIDDHHMMSS = "yyyy/MM/dd HH:mm:ss";
+
+
+}
diff --git a/chsm-common/src/main/java/com/sunyard/utils/JsonUtils.java b/chsm-common/src/main/java/com/sunyard/utils/JsonUtils.java
new file mode 100644
index 0000000..3f7de11
--- /dev/null
+++ b/chsm-common/src/main/java/com/sunyard/utils/JsonUtils.java
@@ -0,0 +1,97 @@
+package com.sunyard.utils;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
+
+import java.io.IOException;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.format.DateTimeFormatter;
+
+
+/**
+ * @author liulu
+ * @version V1.0
+ * @since 2020/11/25
+ */
+public abstract class JsonUtils {
+
+ private JsonUtils() {
+ }
+
+ private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+
+ static {
+ JavaTimeModule javaTimeModule = new JavaTimeModule();
+ javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DateFormatPattern.HH_MM_SS)));
+ javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DateFormatPattern.YYYY_MM_DD)));
+ javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DateFormatPattern.YYYY_MM_DD_HH_MM_SS)));
+
+ javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DateFormatPattern.HH_MM_SS)));
+ javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DateFormatPattern.YYYY_MM_DD)));
+ javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DateFormatPattern.YYYY_MM_DD_HH_MM_SS)));
+
+ OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
+ OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ OBJECT_MAPPER.registerModules(javaTimeModule);
+ }
+
+ public static ObjectMapper objectMapper() {
+ return OBJECT_MAPPER;
+ }
+
+ public static String toJsonString(Object obj) {
+ try {
+ return OBJECT_MAPPER.writeValueAsString(obj);
+ } catch (JsonProcessingException e) {
+ //
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ public static byte[] toJsonBytes(Object obj) {
+ try {
+ return OBJECT_MAPPER.writeValueAsBytes(obj);
+ } catch (JsonProcessingException e) {
+ //
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+
+ public static T parse(String jsonStr, Class type) {
+ if (jsonStr == null || jsonStr.isEmpty()) {
+ return null;
+ }
+ try {
+ return OBJECT_MAPPER.readValue(jsonStr, type);
+ } catch (JsonProcessingException e) {
+ //
+ throw new IllegalArgumentException("json格式错误");
+ }
+ }
+
+ public static T parse(byte[] json, Class type) {
+ if (json == null || json.length == 0) {
+ return null;
+ }
+ try {
+ return OBJECT_MAPPER.readValue(json, type);
+ } catch (IOException e) {
+ //
+ throw new IllegalArgumentException("json格式错误");
+ }
+ }
+
+
+}
diff --git a/chsm-common/src/main/java/com/sunyard/utils/ThrowableUtils.java b/chsm-common/src/main/java/com/sunyard/utils/ThrowableUtils.java
new file mode 100644
index 0000000..379023b
--- /dev/null
+++ b/chsm-common/src/main/java/com/sunyard/utils/ThrowableUtils.java
@@ -0,0 +1,41 @@
+package com.sunyard.utils;
+
+/**
+ * @author liulu
+ * @version V1.0
+ * @since 2020/11/16
+ */
+public abstract class ThrowableUtils {
+
+ private ThrowableUtils() {
+ }
+
+
+ public static String buildErrorMessage(Throwable ex) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(ex.getMessage());
+ StackTraceElement[] stackTrace = ex.getStackTrace();
+ int i = 0;
+ for (StackTraceElement stackTraceElement : stackTrace) {
+ if (i++ >= 5) {
+ break;
+ }
+ sb.append("\n\t").append(stackTraceElement.toString());
+ }
+ return sb.toString();
+ }
+
+
+ public static T findException(Class exClass, Throwable ex) {
+ for (int i = 0; ex != null && i < 3; i++) {
+ if (exClass.isAssignableFrom(ex.getClass())) {
+ //noinspection unchecked
+ return (T) ex;
+ }
+ ex = ex.getCause();
+ }
+ return null;
+ }
+
+
+}
diff --git a/chsm-model/pom.xml b/chsm-model/pom.xml
new file mode 100644
index 0000000..bbc9399
--- /dev/null
+++ b/chsm-model/pom.xml
@@ -0,0 +1,20 @@
+
+
+ 4.0.0
+
+ com.sunyard.chsm
+ chsm
+ 1.0-SNAPSHOT
+
+
+ chsm-model
+
+
+ 8
+ 8
+ UTF-8
+
+
+
\ No newline at end of file
diff --git a/chsm-web-manage/pom.xml b/chsm-web-manage/pom.xml
new file mode 100644
index 0000000..cfd4180
--- /dev/null
+++ b/chsm-web-manage/pom.xml
@@ -0,0 +1,144 @@
+
+
+ 4.0.0
+
+ com.sunyard.chsm
+ chsm
+ 1.0-SNAPSHOT
+
+
+ chsm-web-manage
+
+
+ 8
+ 8
+ UTF-8
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-security
+
+
+ org.springframework.boot
+ spring-boot-starter-data-redis
+
+
+
+ io.lettuce
+ lettuce-core
+
+
+
+
+
+ redis.clients
+ jedis
+
+
+
+ com.sunyard.chsm
+ chsm-common
+ ${project.version}
+
+
+
+ org.bouncycastle
+ bcprov-jdk15on
+
+
+
+ org.bouncycastle
+ bcpkix-jdk15on
+
+
+
+ com.dm
+ DmJdbcDriver
+ 1.8
+
+
+
+
+ com.sunyard
+ ssp.javasdk
+ 1.0-SNAPSHOT
+
+
+ com.sunyard
+ sdf1418
+ 1.0-SNAPSHOT
+
+
+ com.sunyard
+ sydapi4j
+ 1.13.20221010
+
+
+ *
+ groovy-all
+
+
+
+
+
+
+ org.apache.commons
+ commons-pool2
+
+
+ org.apache.commons
+ commons-lang3
+
+
+ commons-codec
+ commons-codec
+
+
+
+ net.java.dev.jna
+ jna
+ 4.5.2
+
+
+ io.swagger
+ swagger-annotations
+ 1.5.13
+
+
+
+
+ com.googlecode.protobuf-java-format
+ protobuf-java-format
+ 1.2
+
+
+ com.google.protobuf
+ protobuf-java
+ 3.17.3
+
+
+
+ com.google.code.gson
+ gson
+
+
+
+ io.jsonwebtoken
+ jjwt
+ 0.9.1
+
+
+ javax.persistence
+ javax.persistence-api
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/chsm-web-manage/src/main/java/com/sunyard/WebManageApp.java b/chsm-web-manage/src/main/java/com/sunyard/WebManageApp.java
new file mode 100644
index 0000000..9cc8dd7
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/WebManageApp.java
@@ -0,0 +1,22 @@
+package com.sunyard;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+/**
+ * @author liulu
+ * @since 2024/10/25
+ */
+@SpringBootApplication
+//@ComponentScan(basePackages={"com.sunyard"})
+@EnableScheduling
+@EnableAsync
+public class WebManageApp {
+
+ public static void main(String[] args) {
+ SpringApplication.run(WebManageApp.class, args);
+ }
+
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/CorsFilter.java b/chsm-web-manage/src/main/java/com/sunyard/config/CorsFilter.java
new file mode 100644
index 0000000..d98fbcc
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/config/CorsFilter.java
@@ -0,0 +1,37 @@
+package com.sunyard.config;
+
+import org.springframework.stereotype.Component;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * @author:tsz
+ * @date:2020/3/9
+ * @description: 跨域问题
+ */
+@Component
+public class CorsFilter implements Filter {
+ @Override
+ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
+ HttpServletResponse response = (HttpServletResponse) res;
+
+ // response.setHeader("Access-Control-Allow-Origin",reqs.getHeader("Origin"));
+ response.setHeader("Access-Control-Allow-Origin", "*");
+ response.setHeader("Access-Control-Allow-Credentials", "true");
+ response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, HEAD, DELETE");
+ response.setHeader("Access-Control-Max-Age", "3600");
+ response.setHeader("access-control-allow-headers", "Content-Type,Accept,Authorization,accesstoken");
+ if (((HttpServletRequest) req).getMethod().equals("OPTIONS")) {
+ response.setStatus(200);
+ return;
+ }
+ chain.doFilter(req, res);
+ }
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/WebConfig.java b/chsm-web-manage/src/main/java/com/sunyard/config/WebConfig.java
new file mode 100644
index 0000000..e315c20
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/config/WebConfig.java
@@ -0,0 +1,66 @@
+package com.sunyard.config;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
+import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
+import com.sunyard.utils.DateFormatPattern;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * @author liulu
+ * @since 2024/10/25
+ */
+@Configuration
+@MapperScan("com.sunyard.ssp.**.mapper")
+public class WebConfig {
+
+ /**
+ * 添加分页插件
+ */
+ @Bean
+ public MybatisPlusInterceptor mybatisPlusInterceptor() {
+ MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
+ // 如果配置多个插件, 切记分页最后添加
+ // 如果有多数据源可以不配具体类型, 否则都建议配上具体的 DbType
+ interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.DM));
+ return interceptor;
+ }
+
+
+ @Bean
+ public Jackson2ObjectMapperBuilderCustomizer objectMapperBuilderCustomizer() {
+ return builder -> {
+ JavaTimeModule javaTimeModule = new JavaTimeModule();
+ javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ofPattern(DateFormatPattern.HH_MM_SS)));
+ javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern(DateFormatPattern.YYYY_MM_DD)));
+ javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DateFormatPattern.YYYY_MM_DD_HH_MM_SS)));
+
+ javaTimeModule.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DateFormatPattern.HH_MM_SS)));
+ javaTimeModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ofPattern(DateFormatPattern.YYYY_MM_DD)));
+ javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DateFormatPattern.YYYY_MM_DD_HH_MM_SS)));
+
+ builder.modules(javaTimeModule);
+ builder.serializerByType(Long.class, ToStringSerializer.instance);
+ builder.serializationInclusion(JsonInclude.Include.NON_NULL);
+ builder.failOnUnknownProperties(false);
+ };
+ }
+
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/security/CaptchaProperties.java b/chsm-web-manage/src/main/java/com/sunyard/config/security/CaptchaProperties.java
new file mode 100644
index 0000000..3f5acc6
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/config/security/CaptchaProperties.java
@@ -0,0 +1,25 @@
+package com.sunyard.config.security;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Exrickx
+ */
+@Data
+@Configuration
+@ConfigurationProperties(prefix = "captcha")
+public class CaptchaProperties {
+
+ private List image = new ArrayList<>();
+
+ private List sms = new ArrayList<>();
+
+ private List vaptcha = new ArrayList<>();
+
+ private List email = new ArrayList<>();
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/security/IgnoredUrlsProperties.java b/chsm-web-manage/src/main/java/com/sunyard/config/security/IgnoredUrlsProperties.java
new file mode 100644
index 0000000..506df41
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/config/security/IgnoredUrlsProperties.java
@@ -0,0 +1,19 @@
+package com.sunyard.config.security;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Exrickx
+ */
+@Data
+@Configuration
+@ConfigurationProperties(prefix = "ignored")
+public class IgnoredUrlsProperties {
+
+ private List urls = new ArrayList<>();
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/security/SM3PasswordEncoder.java b/chsm-web-manage/src/main/java/com/sunyard/config/security/SM3PasswordEncoder.java
new file mode 100644
index 0000000..208bd28
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/config/security/SM3PasswordEncoder.java
@@ -0,0 +1,66 @@
+package com.sunyard.config.security;
+
+import cn.hutool.core.util.RandomUtil;
+import cn.hutool.core.util.StrUtil;
+import com.sunyard.ssp.common.constant.CommonConstant;
+import com.sunyard.ssp.utils.sm3.SM3Digest;
+import org.springframework.security.crypto.password.PasswordEncoder;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+
+/**
+ * @Auther: wp
+ * @Date: 2021/12/16 10:47
+ * @Description:
+ */
+public class SM3PasswordEncoder implements PasswordEncoder {
+
+ @Override
+ public String encode(CharSequence rawPassword) {
+ String salt = RandomUtil.randomString(CommonConstant.SALT_NUMBER);
+ String encode = SM3Digest.encode(salt + rawPassword.toString());
+ return new StringBuilder().append(encode).append("@").append(salt).toString();
+ }
+
+ @Override
+ public boolean matches(CharSequence rawPassword, String encodedPassword) {
+ if(StrUtil.isBlank(encodedPassword)){
+ return false;
+ }
+ //先从encodedPassword提取salt
+ String salt = encodedPassword.split("@")[1];
+ String encode = SM3Digest.encode(salt + rawPassword.toString());
+ String origin = new StringBuilder().append(encode).append("@").append(salt).toString();
+
+ return MessageDigest.isEqual(origin.getBytes(StandardCharsets.UTF_8), encodedPassword.getBytes(StandardCharsets.UTF_8));
+ }
+
+ @Override
+ public boolean upgradeEncoding(String encodedPassword) {
+ return false;
+ }
+
+// public static void main(String[] args) {
+//// String rawPassword="wp123456.";
+//// String encode1 = SM3Digest.encode(rawPassword);
+//// System.out.println(encode1);
+//// String salt = RandomUtil.randomString(CommonConstant.SALT_NUMBER);
+//// String encode = SM3Digest.encode(salt + encode1);
+//// String s = new StringBuilder().append(encode).append("@").append(salt).toString();
+//// System.out.println(s);
+//
+// String encodedPassword="00513D5AC7477E6E8FD33A2A6EAAB2F6C04B260DA91E7E6648E8472E914939EB@2sszbadwg5";
+// //AE2B659E60E130E47D18F95387B599E7C261275902020F1D942BD69C2840F28F@tpgb0tfqxc
+// //先从encodedPassword提取salt
+// String salt = encodedPassword.split("@")[1];
+// String rawPassword="3160FD1B6DAEA5A455C7F6C2DC48BEA3A2B9DA73270960791FDBFD60B57A95EA";
+// String encode = SM3Digest.encode(salt + rawPassword.toString());
+// String origin = new StringBuilder().append(encode).append("@").append(salt).toString();
+//
+// boolean equal = MessageDigest.isEqual(origin.getBytes(StandardCharsets.UTF_8), encodedPassword.getBytes(StandardCharsets.UTF_8));
+// System.out.println(equal);
+// }
+
+}
+
diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/security/SecurityUserDetails.java b/chsm-web-manage/src/main/java/com/sunyard/config/security/SecurityUserDetails.java
new file mode 100644
index 0000000..6ff2074
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/config/security/SecurityUserDetails.java
@@ -0,0 +1,98 @@
+package com.sunyard.config.security;
+
+import cn.hutool.core.util.StrUtil;
+import com.sunyard.ssp.common.constant.CommonConstant;
+import com.sunyard.ssp.modules.user.entity.ScPermission;
+import com.sunyard.ssp.modules.user.entity.ScUser;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author Exrickx
+ */
+@Slf4j
+public class SecurityUserDetails extends ScUser implements UserDetails {
+
+ private static final long serialVersionUID = 1L;
+
+ public SecurityUserDetails(ScUser user) {
+
+ if(user!=null) {
+ this.setUsername(user.getUsername());
+ this.setPassword(user.getPassword());
+ this.setStatus(user.getStatus()==null?0:user.getStatus());
+ this.setRoles(user.getRoles());
+ this.setPermissions(user.getPermissions());
+ }
+ }
+
+ /**
+ * 添加用户拥有的权限和角色
+ * @return
+ */
+ @Override
+ public Collection extends GrantedAuthority> getAuthorities() {
+
+
+ List authorityList = new ArrayList<>();
+ List permissions = this.getPermissions();
+ // 添加请求权限
+ if(permissions!=null&&permissions.size()>0){
+ for (ScPermission permission : permissions) {
+ if(CommonConstant.PERMISSION_OPERATION.equals(permission.getPType())
+ &&StrUtil.isNotBlank(permission.getTitle())
+ &&StrUtil.isNotBlank(permission.getPath())) {
+
+ authorityList.add(new SimpleGrantedAuthority(permission.getTitle()));
+ }
+ }
+ }
+ return authorityList;
+ }
+
+ /**
+ * 账户是否过期
+ * @return
+ */
+ @Override
+ public boolean isAccountNonExpired() {
+
+ return true;
+ }
+
+ /**
+ * 是否禁用
+ * @return
+ */
+ @Override
+ public boolean isAccountNonLocked() {
+
+ return CommonConstant.USER_STATUS_LOCK.equals(this.getStatus()) ? false : true;
+ }
+
+ /**
+ * 密码是否过期
+ * @return
+ */
+ @Override
+ public boolean isCredentialsNonExpired() {
+
+ return true;
+ }
+
+ /**
+ * 是否启用
+ * @return
+ */
+ @Override
+ public boolean isEnabled() {
+
+ return CommonConstant.USER_STATUS_NORMAL.equals(this.getStatus()) ? true : false;
+ }
+}
\ No newline at end of file
diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/security/UserDetailsServiceImpl.java b/chsm-web-manage/src/main/java/com/sunyard/config/security/UserDetailsServiceImpl.java
new file mode 100644
index 0000000..f295993
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/config/security/UserDetailsServiceImpl.java
@@ -0,0 +1,76 @@
+package com.sunyard.config.security;
+
+import cn.hutool.core.util.StrUtil;
+import com.sunyard.ssp.common.constant.CommonConstant;
+import com.sunyard.ssp.common.exception.LoginFailLimitException;
+import com.sunyard.ssp.modules.user.entity.ScUser;
+import com.sunyard.ssp.modules.user.service.IScPermissionService;
+import com.sunyard.ssp.modules.user.service.IScUserService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDateTime;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author Exrickx
+ */
+@Slf4j
+@Component
+public class UserDetailsServiceImpl implements UserDetailsService{
+
+ @Autowired
+ private StringRedisTemplate redisTemplate;
+
+ @Autowired
+ private IScUserService userService;
+
+ @Autowired
+ private IScPermissionService permissionService;
+
+ @Value("${ssp.passMaxDays}")
+ private Integer passMaxDays;
+
+ @Override
+ public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+ long begin = System.currentTimeMillis();
+ String flagKey = "loginFailFlag:" + username;
+ String value = redisTemplate.opsForValue().get(flagKey);
+
+ if(StrUtil.isBlank(username)){
+ return new SecurityUserDetails(null);
+ }
+
+ //通过用户名登陆
+ ScUser user = userService.findByUsername(username);
+
+ if(user == null){
+ return new SecurityUserDetails(null);
+ }
+
+ //admin特殊处理
+ if(CommonConstant.DEFAULT_USER_ROOT_ID.equals(user.getId())){
+ Long timeRest = redisTemplate.getExpire(flagKey, TimeUnit.SECONDS);
+ Double minutes = Math.ceil(Double.valueOf(timeRest)/60);
+ if(StrUtil.isNotBlank(value)){
+ //超过限制次数
+ throw new LoginFailLimitException("登录错误次数超过限制,请"+minutes.intValue()+"分钟后再试");
+ }
+ return new SecurityUserDetails(user);
+ }
+
+ //密码过期日
+ LocalDateTime passLimitDate = LocalDateTime.now().minusDays(passMaxDays);
+ if(passLimitDate.isAfter(user.getPassUpdateTime())){
+ throw new LoginFailLimitException("密码已过期,请联系管理员修改后重试");
+ }
+
+ return new SecurityUserDetails(user);
+ }
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/security/WebSecurityConfig.java b/chsm-web-manage/src/main/java/com/sunyard/config/security/WebSecurityConfig.java
new file mode 100644
index 0000000..00af282
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/config/security/WebSecurityConfig.java
@@ -0,0 +1,119 @@
+package com.sunyard.config.security;
+
+import com.sunyard.config.security.jwt.AuthenticationFailHandler;
+import com.sunyard.config.security.jwt.AuthenticationSuccessHandler;
+import com.sunyard.config.security.jwt.JWTAuthenticationFilter;
+import com.sunyard.config.security.jwt.RestAccessDeniedHandler;
+import com.sunyard.config.security.permission.MyFilterSecurityInterceptor;
+import com.sunyard.config.security.validate.ImageValidateFilter;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+
+/**
+ * Security 核心配置类
+ * 开启注解控制权限至Controller
+ * @author Exrickx
+ */
+@Slf4j
+@Configuration
+@EnableGlobalMethodSecurity(prePostEnabled=true)
+public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
+
+ @Value("${ssp.token.redis}")
+ private Boolean tokenRedis;
+
+ @Value("${ssp.tokenExpireTime}")
+ private Integer tokenExpireTime;
+
+ @Autowired
+ private IgnoredUrlsProperties ignoredUrlsProperties;
+
+ @Autowired
+ private UserDetailsServiceImpl userDetailsService;
+
+ @Autowired
+ private AuthenticationSuccessHandler successHandler;
+
+ @Autowired
+ private AuthenticationFailHandler failHandler;
+
+ @Autowired
+ private RestAccessDeniedHandler accessDeniedHandler;
+
+ @Autowired
+ private MyFilterSecurityInterceptor myFilterSecurityInterceptor;
+
+ @Autowired
+ private StringRedisTemplate redisTemplate;
+
+ @Autowired
+ private ImageValidateFilter imageValidateFilter;
+
+ @Override
+ protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+ auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
+ }
+
+ @Override
+ protected void configure(HttpSecurity http) throws Exception {
+
+ ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry registry = http
+ .authorizeRequests();
+
+ //除配置文件忽略路径其它所有请求都需经过认证和授权
+ for(String url:ignoredUrlsProperties.getUrls()){
+ registry.antMatchers(url).permitAll();
+ }
+
+ registry.and()
+ //表单登录方式
+ .formLogin()
+ .loginPage("/needLogin")
+ //登录请求url
+ .loginProcessingUrl("/login")
+ .permitAll()
+ //成功处理类
+ .successHandler(successHandler)
+ //失败
+ .failureHandler(failHandler)
+ .and()
+ //允许网页iframe
+ .headers().frameOptions().disable()
+ .and()
+ .logout()
+ .permitAll()
+ .and()
+ .authorizeRequests()
+ //任何请求
+ .anyRequest()
+ //需要身份认证
+ .authenticated()
+ .and()
+ //关闭跨站请求防护
+ .csrf().disable()
+ //前后端分离采用JWT 不需要session
+ .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
+ .and()
+ //自定义权限拒绝处理类
+ .exceptionHandling().accessDeniedHandler(accessDeniedHandler)
+ .and()
+ // 图形验证码过滤器
+ .addFilterBefore(imageValidateFilter, UsernamePasswordAuthenticationFilter.class)
+ //添加自定义权限过滤器
+ .addFilterBefore(myFilterSecurityInterceptor, FilterSecurityInterceptor.class)
+ //添加JWT过滤器 除已配置的其它请求都需经过此过滤器
+ .addFilter(new JWTAuthenticationFilter(authenticationManager(), tokenRedis, tokenExpireTime, redisTemplate));
+ }
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/security/jwt/AuthenticationFailHandler.java b/chsm-web-manage/src/main/java/com/sunyard/config/security/jwt/AuthenticationFailHandler.java
new file mode 100644
index 0000000..935541f
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/config/security/jwt/AuthenticationFailHandler.java
@@ -0,0 +1,114 @@
+package com.sunyard.config.security.jwt;
+
+import cn.hutool.core.util.StrUtil;
+import com.sunyard.ssp.common.constant.CommonConstant;
+import com.sunyard.ssp.common.exception.LoginFailLimitException;
+import com.sunyard.ssp.modules.user.entity.ScUser;
+import com.sunyard.ssp.modules.user.service.IScUserService;
+import com.sunyard.ssp.utils.ResponseUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authentication.DisabledException;
+import org.springframework.security.authentication.LockedException;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author Exrickx
+ */
+@Slf4j
+@Component
+public class AuthenticationFailHandler extends SimpleUrlAuthenticationFailureHandler {
+
+ @Value("${ssp.loginTimeLimit}")
+ private Integer loginTimeLimit;
+
+ @Value("${ssp.loginAfterTime}")
+ private Integer loginAfterTime;
+
+ @Autowired
+ private StringRedisTemplate redisTemplate;
+
+ @Autowired
+ private IScUserService userService;
+
+ @Override
+ public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
+
+ String username = request.getParameter("username");
+
+ if (e instanceof UsernameNotFoundException || e instanceof BadCredentialsException) {
+
+ recordLoginTime(username);
+ String key = "loginTimeLimit:" + username;
+ String value = redisTemplate.opsForValue().get(key);
+ if (StrUtil.isBlank(value)) {
+ value = "0";
+ }
+ //获取已登录错误次数
+ int loginFailTime = Integer.parseInt(value);
+ int restLoginTime = loginTimeLimit - loginFailTime;
+ log.info("用户" + username + "登录失败,还有" + restLoginTime + "次机会");
+ if (restLoginTime <= 3 && restLoginTime > 0) {
+ ResponseUtil.out(response, ResponseUtil.resultMap(false, 500, "用户名或密码错误,还有" + restLoginTime + "次尝试机会"));
+ } else if (restLoginTime <= 0) {
+ ScUser user = userService.findByUsername(username);
+ if (user != null && !CommonConstant.DEFAULT_USER_ROOT_ID.equals(user.getId())) {
+ user.setStatus(CommonConstant.USER_STATUS_LOCK);
+ userService.updateById(user);
+ ResponseUtil.out(response, ResponseUtil.resultMap(false, 500, "登录错误次数超过限制,用户已被锁定,请联系管理员解锁后重试"));
+ } else {
+ ResponseUtil.out(response, ResponseUtil.resultMap(false, 500, "登录错误次数超过限制,请" + loginAfterTime + "分钟后再试"));
+ }
+ } else {
+ ResponseUtil.out(response, ResponseUtil.resultMap(false, 500, "用户名或密码错误"));
+ }
+ } else if (e instanceof DisabledException){
+ ResponseUtil.out(response, ResponseUtil.resultMap(false,500,"用户不存在"));
+ } else if (e instanceof LockedException) {
+ ResponseUtil.out(response, ResponseUtil.resultMap(false,500,"用户被禁用,请联系管理员"));
+ } else if (e instanceof LoginFailLimitException){
+ ScUser user = userService.findByUsername(username);
+ if (user != null && !CommonConstant.DEFAULT_USER_ROOT_ID.equals(user.getId())) {
+ user.setStatus(CommonConstant.USER_STATUS_LOCK);
+ userService.updateById(user);
+ }
+ ResponseUtil.out(response, ResponseUtil.resultMap(false,500,((LoginFailLimitException) e).getMsg()));
+ } else {
+ ResponseUtil.out(response, ResponseUtil.resultMap(false,500,"登录失败,其他内部错误"));
+ }
+ }
+
+ /**
+ * 判断用户登陆错误次数
+ */
+ public boolean recordLoginTime(String username){
+
+ String key = "loginTimeLimit:"+username;
+ String flagKey = "loginFailFlag:"+username;
+ String value = redisTemplate.opsForValue().get(key);
+ if(StrUtil.isBlank(value)){
+ value = "0";
+ }
+ //获取已登录错误次数
+ int loginFailTime = Integer.parseInt(value) + 1;
+ redisTemplate.opsForValue().set(key, String.valueOf(loginFailTime), loginAfterTime, TimeUnit.MINUTES);
+ if(loginFailTime>=loginTimeLimit){
+
+ redisTemplate.opsForValue().set(flagKey, "fail", loginAfterTime, TimeUnit.MINUTES);
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/security/jwt/AuthenticationSuccessHandler.java b/chsm-web-manage/src/main/java/com/sunyard/config/security/jwt/AuthenticationSuccessHandler.java
new file mode 100644
index 0000000..d1f7cf6
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/config/security/jwt/AuthenticationSuccessHandler.java
@@ -0,0 +1,144 @@
+package com.sunyard.config.security.jwt;
+
+import cn.hutool.core.util.StrUtil;
+import com.google.gson.Gson;
+import com.sunyard.ssp.common.constant.SecurityConstant;
+import com.sunyard.ssp.modules.user.entity.ScUser;
+import com.sunyard.ssp.modules.user.service.IScUserService;
+import com.sunyard.ssp.utils.ResponseUtil;
+import com.sunyard.ssp.utils.SecurityUtil;
+import com.sunyard.ssp.vo.TokenUser;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 登录成功处理类
+ * @author Exrickx
+ */
+@Slf4j
+@Component
+public class AuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {
+
+ @Value("${ssp.token.redis}")
+ private Boolean tokenRedis;
+
+ @Value("${ssp.tokenExpireTime}")
+ private Integer tokenExpireTime;
+
+ @Value("${ssp.saveLoginTime}")
+ private Integer saveLoginTime;
+
+ @Value("${ssp.passMaxDays}")
+ private Integer passMaxDays;
+
+ @Value("${ssp.passWarnAge}")
+ private Integer passWarnAge;
+
+ @Autowired
+ private StringRedisTemplate redisTemplate;
+
+ @Autowired
+ private SecurityUtil securityUtil;
+
+ @Autowired
+ private IScUserService scUserService;
+
+ @Override
+ public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
+
+ long beginTime = System.currentTimeMillis();
+ //用户选择保存登录状态几天
+ String saveLogin = request.getParameter(SecurityConstant.SAVE_LOGIN);
+ Boolean saved = false;
+ String msg = "登录成功";
+ if(StrUtil.isNotBlank(saveLogin) && Boolean.valueOf(saveLogin)){
+ saved = true;
+ if(!tokenRedis){
+ tokenExpireTime = saveLoginTime * 60 * 24;
+ }
+ }
+ String username = ((UserDetails)authentication.getPrincipal()).getUsername();
+ System.out.println("loginSuccess username:" + username + "begin:" + (beginTime - System.currentTimeMillis()));
+ List authorities = (List) ((UserDetails)authentication.getPrincipal()).getAuthorities();
+ List list = new ArrayList<>();
+ for(GrantedAuthority g : authorities){
+ list.add(g.getAuthority());
+ }
+ System.out.println("loginSuccess username:" + username + "getCurrUser begin:" + (beginTime - System.currentTimeMillis()));
+ ScUser scuser = securityUtil.getCurrUser();
+ //ipInfoUtil.getUrl(request);
+ System.out.println("loginSuccess username:" + username + "getCurrUser end:" + (beginTime - System.currentTimeMillis()));
+ // 登陆成功生成token
+ String token;
+ if(tokenRedis){
+ // redis
+ token = UUID.randomUUID().toString().replace("-", "");
+ TokenUser user = new TokenUser(username, list, saved);
+ // 单点登录 之前的token失效
+ String oldToken = redisTemplate.opsForValue().get(SecurityConstant.USER_TOKEN + username);
+ if(StrUtil.isNotBlank(oldToken)){
+ redisTemplate.delete(SecurityConstant.TOKEN_PRE + oldToken);
+ }
+
+ //清空失败次数
+ String key = "loginTimeLimit:" + username;
+ redisTemplate.delete(key);
+
+ if(saved){
+ redisTemplate.opsForValue().set(SecurityConstant.USER_TOKEN + username, token, saveLoginTime, TimeUnit.DAYS);
+ redisTemplate.opsForValue().set(SecurityConstant.TOKEN_PRE + token, new Gson().toJson(user), saveLoginTime, TimeUnit.DAYS);
+ }else{
+ redisTemplate.opsForValue().set(SecurityConstant.USER_TOKEN + username, token, tokenExpireTime, TimeUnit.MINUTES);
+ redisTemplate.opsForValue().set(SecurityConstant.TOKEN_PRE + token, new Gson().toJson(user), tokenExpireTime, TimeUnit.MINUTES);
+ }
+ }else{
+ // jwt
+ token = SecurityConstant.TOKEN_SPLIT + Jwts.builder()
+ //主题 放入用户名
+ .setSubject(username)
+ //自定义属性 放入用户拥有请求权限
+ .claim(SecurityConstant.AUTHORITIES, new Gson().toJson(list))
+ //失效时间
+ .setExpiration(new Date(System.currentTimeMillis() + tokenExpireTime * 60 * 1000))
+ //签名算法和密钥
+ .signWith(SignatureAlgorithm.HS512, SecurityConstant.JWT_SIGN_KEY)
+ .compact();
+ }
+
+ LocalDateTime limitDate = scuser.getPassUpdateTime().plusDays(passMaxDays);
+
+ DateTimeFormatter sdf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ if(limitDate.isBefore(LocalDateTime.now().plusDays(passWarnAge))){
+ msg = "密码将于" + sdf.format(limitDate) + "过期,请及时修改";
+ }
+
+ /*sunyard*/
+ response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, HEAD, DELETE");
+ response.setHeader("Access-Control-Allow-Origin", "*");
+ response.setHeader("access-control-allow-headers", "Content-Type,Accept,Authorization,accesstoken");
+ /*sunyard end*/
+ System.out.println("loginSuccess username:" + username + "end:" + (beginTime - System.currentTimeMillis()));
+ ResponseUtil.out(response, ResponseUtil.resultMap(true,200,msg, token));
+ }
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/security/jwt/JWTAuthenticationFilter.java b/chsm-web-manage/src/main/java/com/sunyard/config/security/jwt/JWTAuthenticationFilter.java
new file mode 100644
index 0000000..13ddf15
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/config/security/jwt/JWTAuthenticationFilter.java
@@ -0,0 +1,163 @@
+package com.sunyard.config.security.jwt;
+
+import cn.hutool.core.util.StrUtil;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import com.sunyard.ssp.common.constant.SecurityConstant;
+import com.sunyard.ssp.utils.ResponseUtil;
+import com.sunyard.ssp.vo.TokenUser;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.ExpiredJwtException;
+import io.jsonwebtoken.Jwts;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author Exrickx
+ */
+@Slf4j
+public class JWTAuthenticationFilter extends BasicAuthenticationFilter {
+
+ private Boolean tokenRedis;
+
+ private Integer tokenExpireTime;
+
+ private StringRedisTemplate redisTemplate;
+
+ public JWTAuthenticationFilter(AuthenticationManager authenticationManager, Boolean tokenRedis, Integer tokenExpireTime, StringRedisTemplate redisTemplate) {
+ super(authenticationManager);
+ this.tokenRedis = tokenRedis;
+ this.tokenExpireTime = tokenExpireTime;
+ this.redisTemplate = redisTemplate;
+ }
+
+ public JWTAuthenticationFilter(AuthenticationManager authenticationManager, AuthenticationEntryPoint authenticationEntryPoint) {
+ super(authenticationManager, authenticationEntryPoint);
+ }
+
+ @Override
+ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
+
+ /*sunyard*/
+ String method = request.getMethod();
+ System.out.println( method );
+ System.out.println( request.getRequestURI() );
+
+
+ response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, HEAD, DELETE");
+ response.setHeader("Access-Control-Allow-Origin", "*");
+ response.setHeader("access-control-allow-headers", "Content-Type,Accept,Authorization,accesstoken,auth-token");
+
+
+
+ if ("options".equalsIgnoreCase(method)){
+ response.setStatus(200);
+ return;
+ }
+ /*sunyard end*/
+
+ String header = request.getHeader(SecurityConstant.HEADER);
+ if(StrUtil.isBlank(header)){
+ header = request.getParameter(SecurityConstant.HEADER);
+ }
+
+ if(StrUtil.isBlank(header) && request.getCookies()!=null){
+ Cookie cookie = Arrays.stream(request.getCookies()).filter(tmpCookie -> SecurityConstant.HEADER.equals(tmpCookie.getName())).findAny().orElse(null);
+ header = cookie == null?null: cookie.getValue();
+ }
+
+ Boolean notValid = StrUtil.isBlank(header) || (!tokenRedis && !header.startsWith(SecurityConstant.TOKEN_SPLIT));
+ if (notValid) {
+ chain.doFilter(request, response);
+ return;
+ }
+ try {
+ UsernamePasswordAuthenticationToken authentication = getAuthentication(header, response, request);
+ SecurityContextHolder.getContext().setAuthentication(authentication);
+ }catch (Exception e){
+ e.toString();
+ }
+
+ chain.doFilter(request, response);
+ }
+
+ private UsernamePasswordAuthenticationToken getAuthentication(String header, HttpServletResponse response, HttpServletRequest request) {
+
+ // 用户名
+ String username = null;
+ // 权限
+ List authorities = new ArrayList<>();
+
+ if(tokenRedis){
+ // redis
+ String v = redisTemplate.opsForValue().get(SecurityConstant.TOKEN_PRE + header);
+ if(StrUtil.isBlank(v)){
+ ResponseUtil.out(response, ResponseUtil.resultMap(false,401,"登录已失效,请重新登录"));
+ return null;
+ }
+ TokenUser user = new Gson().fromJson(v, TokenUser.class);
+ username = user.getUsername();
+ for(String ga : user.getPermissions()){
+ authorities.add(new SimpleGrantedAuthority(ga));
+ }
+ if(!user.getSaveLogin()){
+ // 若未保存登录状态重新设置失效时间
+ redisTemplate.opsForValue().set(SecurityConstant.USER_TOKEN + username, header, tokenExpireTime, TimeUnit.MINUTES);
+ redisTemplate.opsForValue().set(SecurityConstant.TOKEN_PRE + header, v, tokenExpireTime, TimeUnit.MINUTES);
+ }
+ }else{
+ // JWT
+ try {
+ // 解析token
+ Claims claims = Jwts.parser()
+ .setSigningKey(SecurityConstant.JWT_SIGN_KEY)
+ .parseClaimsJws(header.replace(SecurityConstant.TOKEN_SPLIT, ""))
+ .getBody();
+
+ //获取用户名
+ username = claims.getSubject();
+ //获取权限
+ String authority = claims.get(SecurityConstant.AUTHORITIES).toString();
+
+ if(StrUtil.isNotBlank(authority)){
+ List list = new Gson().fromJson(authority, new TypeToken>(){}.getType());
+ for(String ga : list){
+ authorities.add(new SimpleGrantedAuthority(ga));
+ }
+ }
+ } catch (ExpiredJwtException e) {
+ ResponseUtil.out(response, ResponseUtil.resultMap(false,401,"登录已失效,请重新登录"));
+ } catch (Exception e){
+ log.error(e.toString());
+ ResponseUtil.out(response, ResponseUtil.resultMap(false,500,"解析token错误"));
+ }
+ }
+
+ if(StrUtil.isNotBlank(username)) {
+ //Exrick踩坑提醒 此处password不能为null
+ User principal = new User(username, "", authorities);
+ return new UsernamePasswordAuthenticationToken(principal, null, authorities);
+ }
+ return null;
+ }
+}
+
diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/security/jwt/RestAccessDeniedHandler.java b/chsm-web-manage/src/main/java/com/sunyard/config/security/jwt/RestAccessDeniedHandler.java
new file mode 100644
index 0000000..42d16f1
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/config/security/jwt/RestAccessDeniedHandler.java
@@ -0,0 +1,29 @@
+package com.sunyard.config.security.jwt;
+
+
+import com.sunyard.ssp.utils.ResponseUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.web.access.AccessDeniedHandler;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * @author Exrickx
+ */
+@Component
+@Slf4j
+public class RestAccessDeniedHandler implements AccessDeniedHandler {
+
+ @Override
+ public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException)
+ throws IOException, ServletException {
+
+ ResponseUtil.out(response,ResponseUtil.resultMap(false,403,"抱歉,您没有访问权限"));
+ }
+
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/security/permission/MyAccessDecisionManager.java b/chsm-web-manage/src/main/java/com/sunyard/config/security/permission/MyAccessDecisionManager.java
new file mode 100644
index 0000000..772eafd
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/config/security/permission/MyAccessDecisionManager.java
@@ -0,0 +1,54 @@
+package com.sunyard.config.security.permission;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.security.access.AccessDecisionManager;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.access.ConfigAttribute;
+import org.springframework.security.authentication.InsufficientAuthenticationException;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.stereotype.Component;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+/**
+ * 权限管理决断器
+ * 判断用户拥有的权限或角色是否有资源访问权限
+ * @author Exrickx
+ */
+@Slf4j
+@Component
+public class MyAccessDecisionManager implements AccessDecisionManager {
+
+ @Override
+ public void decide(Authentication authentication, Object o, Collection configAttributes) throws AccessDeniedException, InsufficientAuthenticationException {
+
+ if(configAttributes==null){
+ return;
+ }
+ Iterator iterator = configAttributes.iterator();
+ while (iterator.hasNext()){
+ ConfigAttribute c = iterator.next();
+ String needPerm = c.getAttribute();
+ for(GrantedAuthority ga : authentication.getAuthorities()) {
+ // 匹配用户拥有的ga 和 系统中的needPerm
+ if(needPerm.trim().equals(ga.getAuthority())) {
+
+ return;
+ }
+ }
+ }
+ throw new AccessDeniedException("抱歉,您没有访问权限");
+ }
+
+ @Override
+ public boolean supports(ConfigAttribute configAttribute) {
+ return true;
+ }
+
+ @Override
+ public boolean supports(Class> aClass) {
+ return true;
+ }
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/security/permission/MyFilterSecurityInterceptor.java b/chsm-web-manage/src/main/java/com/sunyard/config/security/permission/MyFilterSecurityInterceptor.java
new file mode 100644
index 0000000..71b1e0d
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/config/security/permission/MyFilterSecurityInterceptor.java
@@ -0,0 +1,73 @@
+package com.sunyard.config.security.permission;
+
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.SecurityMetadataSource;
+import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
+import org.springframework.security.access.intercept.InterceptorStatusToken;
+import org.springframework.security.web.FilterInvocation;
+import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
+import org.springframework.stereotype.Component;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import java.io.IOException;
+
+/**
+ * 权限管理过滤器
+ * 监控用户行为
+ * @author Exrickx
+ */
+@Slf4j
+@Component
+public class MyFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {
+
+ @Autowired
+ private FilterInvocationSecurityMetadataSource securityMetadataSource;
+
+ @Autowired
+ public void setMyAccessDecisionManager(MyAccessDecisionManager myAccessDecisionManager) {
+ super.setAccessDecisionManager(myAccessDecisionManager);
+ }
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+
+ }
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
+
+ FilterInvocation fi = new FilterInvocation(request, response, chain);
+ invoke(fi);
+ }
+
+ public void invoke(FilterInvocation fi) throws IOException, ServletException {
+
+ InterceptorStatusToken token = super.beforeInvocation(fi);
+ try {
+ fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
+ } finally {
+ super.afterInvocation(token, null);
+ }
+ }
+
+ @Override
+ public void destroy() {
+
+ }
+
+ @Override
+ public Class> getSecureObjectClass() {
+ return FilterInvocation.class;
+ }
+
+ @Override
+ public SecurityMetadataSource obtainSecurityMetadataSource() {
+ return this.securityMetadataSource;
+ }
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/security/permission/MyRequestVo.java b/chsm-web-manage/src/main/java/com/sunyard/config/security/permission/MyRequestVo.java
new file mode 100644
index 0000000..19d9712
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/config/security/permission/MyRequestVo.java
@@ -0,0 +1,44 @@
+package com.sunyard.config.security.permission;
+
+import java.util.Objects;
+
+public class MyRequestVo {
+ private String url;
+ private String method;
+
+ public MyRequestVo(String url, String method) {
+ this.url = url;
+ this.method = method;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public String getMethod() {
+ return method;
+ }
+
+ public void setMethod(String method) {
+ this.method = method;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ MyRequestVo that = (MyRequestVo) o;
+ return Objects.equals(url, that.url) &&
+ Objects.equals(method, that.method);
+ }
+
+ @Override
+ public int hashCode() {
+
+ return Objects.hash(url, method);
+ }
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/security/permission/MySecurityMetadataSource.java b/chsm-web-manage/src/main/java/com/sunyard/config/security/permission/MySecurityMetadataSource.java
new file mode 100644
index 0000000..cd9cb3a
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/config/security/permission/MySecurityMetadataSource.java
@@ -0,0 +1,121 @@
+package com.sunyard.config.security.permission;
+
+import cn.hutool.core.util.StrUtil;
+import com.sunyard.ssp.common.constant.CommonConstant;
+import com.sunyard.ssp.modules.user.entity.ScPermission;
+import com.sunyard.ssp.modules.user.service.IScPermissionService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.ConfigAttribute;
+import org.springframework.security.access.SecurityConfig;
+import org.springframework.security.web.FilterInvocation;
+import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
+import org.springframework.stereotype.Component;
+import org.springframework.util.AntPathMatcher;
+import org.springframework.util.PathMatcher;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 权限资源管理器
+ * 为权限决断器提供支持
+ * @author Exrickx
+ */
+@Slf4j
+@Component
+public class MySecurityMetadataSource implements FilterInvocationSecurityMetadataSource {
+
+ @Autowired
+ private IScPermissionService permissionService;
+
+ private Map> map = null;
+
+ private Map needVerifyMap = null;
+
+ /**
+ *
+ */
+ public void loadResourceDefine(){
+
+ map = new HashMap<>(16);
+ needVerifyMap = new HashMap<>(16);
+ Collection configAttributes;
+ ConfigAttribute cfg;
+ // 获取启用的权限操作请求
+ List permissions = permissionService.findByTypeAndStatusOrderBySortOrder(CommonConstant.PERMISSION_OPERATION, CommonConstant.STATUS_NORMAL);
+ for(ScPermission permission : permissions) {
+ if(StrUtil.isNotBlank(permission.getTitle())&&StrUtil.isNotBlank(permission.getPath())){
+ configAttributes = new ArrayList<>();
+ cfg = new SecurityConfig(permission.getTitle());
+ //作为MyAccessDecisionManager类的decide的第三个参数
+ configAttributes.add(cfg);
+ //用权限的path作为map的key,用ConfigAttribute的集合作为value
+ map.put(permission.getPath(), configAttributes);
+ needVerifyMap.put(permission.getPath(), permission.getNeedVerify());
+ }
+ }
+ }
+
+ public boolean needVerify(String url){
+ if(map == null){
+ loadResourceDefine();
+ }
+
+ PathMatcher pathMatcher = new AntPathMatcher();
+ Iterator iterator = map.keySet().iterator();
+ while (iterator.hasNext()) {
+ String path = iterator.next();
+ if (path != null &&
+ StrUtil.isNotBlank(path) &&
+ pathMatcher.match(path,url)) {
+
+ return needVerifyMap.get(path);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 判定用户请求的url是否在权限表中
+ * 如果在权限表中,则返回给decide方法,用来判定用户是否有此权限
+ * 如果不在权限表中则放行
+ * @param o
+ * @return
+ * @throws IllegalArgumentException
+ */
+ @Override
+ public Collection getAttributes(Object o) throws IllegalArgumentException {
+
+ if(map == null){
+ loadResourceDefine();
+ }
+ //Object中包含用户请求request
+ String url = ((FilterInvocation) o).getRequestUrl();
+ PathMatcher pathMatcher = new AntPathMatcher();
+ Iterator iterator = map.keySet().iterator();
+ while (iterator.hasNext()) {
+ String path = iterator.next();
+ if (path != null &&
+ StrUtil.isNotBlank(path) &&
+ pathMatcher.match(path,url) ) {
+ return map.get(path);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Collection getAllConfigAttributes() {
+ return null;
+ }
+
+ @Override
+ public boolean supports(Class> aClass) {
+ return true;
+ }
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/config/security/validate/ImageValidateFilter.java b/chsm-web-manage/src/main/java/com/sunyard/config/security/validate/ImageValidateFilter.java
new file mode 100644
index 0000000..c6a4ad9
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/config/security/validate/ImageValidateFilter.java
@@ -0,0 +1,83 @@
+package com.sunyard.config.security.validate;
+
+import cn.hutool.core.util.StrUtil;
+import com.sunyard.config.security.CaptchaProperties;
+import com.sunyard.ssp.utils.ResponseUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.core.StringRedisTemplate;
+import org.springframework.util.PathMatcher;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * 图形验证码过滤器
+ * @author Exrick
+ */
+@Slf4j
+@Configuration
+public class ImageValidateFilter extends OncePerRequestFilter {
+
+ @Autowired
+ private CaptchaProperties captchaProperties;
+
+ @Autowired
+ private StringRedisTemplate redisTemplate;
+
+ @Autowired
+ private PathMatcher pathMatcher;
+
+ @Override
+ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
+
+ // 判断URL是否需要验证
+ Boolean flag = false;
+ String requestUrl = request.getRequestURI();
+ for(String url : captchaProperties.getImage()){
+ if(pathMatcher.match(url, requestUrl)){
+ flag = true;
+ break;
+ }
+ }
+ if(flag){
+ //todo 假u盾登录无需验证码
+ String sn = request.getParameter("sn");
+ if(StringUtils.isNotBlank(sn)){
+ chain.doFilter(request, response);
+ return;
+ }
+
+ String captchaId = request.getParameter("captchaId");
+ String code = request.getParameter("code");
+ if(StrUtil.isBlank(captchaId)||StrUtil.isBlank(code)){
+ ResponseUtil.out(response, ResponseUtil.resultMap(false,500,"请传入图形验证码所需参数captchaId或code"));
+ return;
+ }
+ String redisCode = redisTemplate.opsForValue().get(captchaId);
+ if(StrUtil.isBlank(redisCode)){
+ ResponseUtil.out(response, ResponseUtil.resultMap(false,500,"验证码已过期,请重新获取"));
+ return;
+ }
+
+ if(!redisCode.toLowerCase().equals(code.toLowerCase())) {
+ log.info("验证码错误:code:"+ code +",redisCode:"+redisCode);
+ ResponseUtil.out(response, ResponseUtil.resultMap(false,500,"图形验证码输入错误"));
+ return;
+ }
+ // 已验证清除key
+ redisTemplate.delete(captchaId);
+ // 验证成功 放行
+ chain.doFilter(request, response);
+ return;
+ }
+ // 无需验证 放行
+ chain.doFilter(request, response);
+ }
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/PageVo.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/PageVo.java
new file mode 100644
index 0000000..0a10b70
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/PageVo.java
@@ -0,0 +1,43 @@
+package com.sunyard.ssp.common;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @author Exrickx
+ */
+@Data
+public class PageVo implements Serializable{
+
+ private static final long serialVersionUID = 1L;
+
+ @TableField(exist = false)
+ private int pageNumber = 1;
+
+ @TableField(exist = false)
+ private int pageSize = 10;
+
+ @TableField(exist = false)
+ private String sort;
+
+ @TableField(exist = false)
+ private String order = "desc";
+
+ public PageVo(){
+
+ }
+
+ /**
+ * 分页构造
+ * @param pageNumber
+ * @param pageSize
+ */
+ public PageVo(Integer pageNumber,Integer pageSize){
+ this.pageNumber = pageNumber;
+ this.pageSize = pageSize;
+ }
+
+
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/Result.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/Result.java
new file mode 100644
index 0000000..959fbe6
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/Result.java
@@ -0,0 +1,41 @@
+package com.sunyard.ssp.common;
+
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @author Exrickx
+ * 前后端交互数据标准
+ */
+@Data
+public class Result implements Serializable{
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 成功标志
+ */
+ private boolean success;
+
+ /**
+ * 失败消息
+ */
+ private String message;
+
+ /**
+ * 返回代码
+ */
+ private Integer code;
+
+ /**
+ * 时间戳
+ */
+ private long timestamp = System.currentTimeMillis();
+
+ /**
+ * 结果对象
+ */
+ private T result;
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/annotation/AuditControllerLog.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/annotation/AuditControllerLog.java
new file mode 100644
index 0000000..1cf990d
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/annotation/AuditControllerLog.java
@@ -0,0 +1,20 @@
+package com.sunyard.ssp.common.annotation;
+
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @author fyc
+ * @des 审计日志注解
+ */
+@Target({ElementType.PARAMETER, ElementType.METHOD})//作用在参数和方法上
+@Retention(RetentionPolicy.RUNTIME)//运行时注解
+@Documented//表明这个注解应该被 javadoc工具记录
+public @interface AuditControllerLog {
+ String description() default "";
+ String operateType() default "";
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/CertificateConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/CertificateConstant.java
new file mode 100644
index 0000000..36ec983
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/CertificateConstant.java
@@ -0,0 +1,18 @@
+package com.sunyard.ssp.common.constant;
+
+/**
+ * @author:tsz
+ * @date:2020/4/3
+ * @description:
+ */
+public interface CertificateConstant {
+
+ //属性字段名 公钥
+ String PUB_KEY ="PUB_KEY";
+
+ //属性字段名 证书原文件
+ String CERTIFICATE_CONTENT ="CERTIFICATE_CONTENT";
+
+ Integer GROUP_SIGN =0;
+
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ChannelConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ChannelConstant.java
new file mode 100644
index 0000000..51e09c9
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ChannelConstant.java
@@ -0,0 +1,52 @@
+package com.sunyard.ssp.common.constant;
+
+/**
+ * @author:tsz
+ * @date:2020/3/13
+ * @description:
+ */
+public interface ChannelConstant {
+
+ /********************************************************
+ @author :tsz
+ @date :2020/03/13 16:57
+ @description : 实施中
+ ********************************************************/
+ Integer PUBLISH_STATUS_ONE = 1;
+ /********************************************************
+ @author :tsz
+ @date :2020/03/13 16:57
+ @description : 已发布
+ ********************************************************/
+ Integer PUBLISH_STATUS_TWO = 2;
+
+ /**
+ *@author :tsz
+ *@date :2020/03/23 16:46
+ *@description : 启用
+ */
+ Integer ENABLED = 0;
+
+ /**
+ *@author :tsz
+ *@date :2020/03/23 16:46
+ *@description : 禁用
+ */
+ Integer DISABLED = 1;
+
+ /**
+ *@author :tsz
+ *@date :2020/03/23 17:15
+ *@description : 方案验证可用
+ */
+ Integer VERIFICATION_ENABLED = 0;
+
+ /**
+ *@author :tsz
+ *@date :2020/03/23 17:15
+ *@description : 方案验证不可用
+ */
+ Integer VERIFICATION_DISABLED = 1;
+
+ Integer VERIFICATION_NOT = 2;
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ChannelSolutionConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ChannelSolutionConstant.java
new file mode 100644
index 0000000..26ed29c
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ChannelSolutionConstant.java
@@ -0,0 +1,10 @@
+package com.sunyard.ssp.common.constant;
+
+/**
+ * @author:tsz
+ * @date:2020/4/1
+ * @description:
+ */
+public interface ChannelSolutionConstant {
+
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/CommonConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/CommonConstant.java
new file mode 100644
index 0000000..6329235
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/CommonConstant.java
@@ -0,0 +1,227 @@
+package com.sunyard.ssp.common.constant;
+
+/**
+ * 常量
+ * @author Exrickx
+ */
+public interface CommonConstant {
+
+ /**
+ * 用户默认头像
+ */
+ String USER_DEFAULT_AVATAR = "https://s1.ax1x.com/2018/05/19/CcdVQP.png";
+
+ /**
+ * 用户正常状态
+ */
+ Integer USER_STATUS_NORMAL = 0;
+
+ /**
+ * 用户禁用状态
+ */
+ Integer USER_STATUS_LOCK = -1;
+
+ /**
+ * 普通用户
+ */
+ Integer USER_TYPE_NORMAL = 0;
+
+ /**
+ * 极光聊天状态
+ */
+ Integer USER_JMESSAGE_NORMAL = 0;
+
+ /**
+ * 管理员
+ */
+ Integer USER_TYPE_ADMIN = 1;
+
+ /**
+ * 全部数据权限
+ */
+ Integer DATA_TYPE_ALL = 0;
+
+ /**
+ * 自定义数据权限
+ */
+ Integer DATA_TYPE_CUSTOM = 1;
+
+ /**
+ * 正常状态
+ */
+ Integer STATUS_NORMAL = 0;
+
+ /**
+ * 禁用状态
+ */
+ Integer STATUS_DISABLE = -1;
+
+ /**
+ * 删除标志
+ */
+ Integer DEL_FLAG = 1;
+
+ /**
+ * 限流标识
+ */
+ String LIMIT_ALL = "KEEPER_LIMIT_ALL";
+
+ /**
+ * 页面类型权限
+ */
+ Integer PERMISSION_PAGE = 0;
+
+ /**
+ * 操作类型权限
+ */
+ Integer PERMISSION_OPERATION = 1;
+
+ /**
+ * 1级菜单父id
+ */
+ Long PARENT_ID = 0L;
+
+ /**
+ * 1级菜单父title
+ */
+ String PARENT_TITLE = "一级节点";
+
+ /**
+ * 默认分类redis缓存key
+ */
+ String DEFAULT_CATEGORY_REDIS_KEY = "actCategory:userDefaultCateGory:";
+
+ /**
+ * 事务审批title
+ */
+ String DEFAULT_CATEGORY_BUSINESS_TITLE = "事务审批";
+
+ /**
+ * 事务审批id
+ */
+ String DEFAULT_CATEGORY_BUSINESS_ID = "1";
+
+ /**
+ * 支付审批title
+ */
+ String DEFAULT_CATEGORY_PAYMENT_TITLE = "支付审批";
+
+ /**
+ * 支付审批id
+ */
+ String DEFAULT_CATEGORY_PAYMENT_ID = "2";
+ /**
+ * 1级菜单
+ */
+ Integer LEVEL_ONE = 1;
+
+ /**
+ * 2级菜单
+ */
+ Integer LEVEL_TWO = 2;
+
+ /**
+ * 3级菜单
+ */
+ Integer LEVEL_THREE = 3;
+
+ /**
+ * 消息发送范围
+ */
+ Integer MESSAGE_RANGE_ALL = 0;
+
+ /**
+ * 未读
+ */
+ Integer MESSAGE_STATUS_UNREAD = 0;
+
+ /**
+ * 已读
+ */
+ Integer MESSAGE_STATUS_READ = 1;
+
+ /**
+ * github登录
+ */
+ Integer SOCIAL_TYPE_GITHUB = 0;
+
+ /**
+ * qq登录
+ */
+ Integer SOCIAL_TYPE_QQ = 1;
+
+ /**
+ * 微博登录
+ */
+ Integer SOCIAL_TYPE_WEIBO = 2;
+
+ /**
+ * 短信验证码key前缀
+ */
+ String PRE_SMS = "KEEPER_PRE_SMS:";
+
+ /**
+ * 邮件验证码key前缀
+ */
+ String PRE_EMAIL = "KEEPER_PRE_EMAIL:";
+
+ /**
+ * 本地文件存储
+ */
+ Integer OSS_LOCAL = 0;
+
+ /**
+ * 七牛云OSS存储
+ */
+ Integer OSS_QINIU = 1;
+
+ /**
+ * 阿里云OSS存储
+ */
+ Integer OSS_ALI = 2;
+
+ /**
+ * 腾讯云COS存储
+ */
+ Integer OSS_TENCENT = 3;
+
+ /**
+ * 部门负责人类型 主负责人
+ */
+ Integer HEADER_TYPE_MAIN = 0;
+
+ /**
+ * 部门负责人类型 副负责人
+ */
+ Integer HEADER_TYPE_VICE = 1;
+
+ /**
+ * 部门负责人类型 不是负责人
+ */
+ Integer HEADER_TYPE_NONE = -1;
+
+ /**
+ * 邮箱字段隐藏时显示的值
+ */
+ String HIDE_EMAIL_STR = "******@***.com";
+
+ /**
+ * 手机字段隐藏时显示的值
+ */
+ String HIDE_MOBILE_STR = "****";
+
+ String PATH_SEPARATOR = "/";
+
+ Long DEPARTMENT_ROOT_ID = 0L;
+
+ Long DEFAULT_USER_ROOT_ID = 1L;
+
+ /**
+ * @author wp
+ * @Description:盐值位数
+ * @date 2021/12/16
+ * @param null
+ * @return
+ */
+ Integer SALT_NUMBER =10;
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/DeviceConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/DeviceConstant.java
new file mode 100644
index 0000000..332143e
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/DeviceConstant.java
@@ -0,0 +1,21 @@
+package com.sunyard.ssp.common.constant;
+
+/**
+ * @author:tsz
+ * @date:2020/5/11
+ * @description:
+ */
+public interface DeviceConstant {
+
+ /**
+ *@date :2020/05/11 15:52
+ *@description : 状态启用
+ */
+ Integer ENABLE = 0;
+
+ /**
+ *@date :2020/05/11 15:52
+ *@description : 状态禁用
+ */
+ Integer DISABLE = 1;
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/DeviceGroupRefConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/DeviceGroupRefConstant.java
new file mode 100644
index 0000000..c0a2f5f
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/DeviceGroupRefConstant.java
@@ -0,0 +1,19 @@
+package com.sunyard.ssp.common.constant;
+
+/**
+ * @author:tsz
+ * @date:2020/3/26
+ * @description:
+ */
+public interface DeviceGroupRefConstant {
+
+ /**
+ * 设备分组内的设备状态 启用
+ */
+ Integer DEVICE_ENABLED = 0;
+
+ /**
+ * 设备分组内的设备状态 禁用
+ */
+ Integer DEVICE_DISABLED = 1;
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/DictDataConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/DictDataConstant.java
new file mode 100644
index 0000000..14444b3
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/DictDataConstant.java
@@ -0,0 +1,10 @@
+package com.sunyard.ssp.common.constant;
+
+/**
+ * @author:tsz
+ * @date:2020/5/12
+ * @description:
+ */
+public interface DictDataConstant {
+ Long [] DICT_ID = {78L,79L,80L};
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/FileConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/FileConstant.java
new file mode 100644
index 0000000..463bf35
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/FileConstant.java
@@ -0,0 +1,11 @@
+package com.sunyard.ssp.common.constant;
+
+/**
+ * @author:tsz
+ * @date:2020/5/28
+ * @description:
+ */
+public interface FileConstant {
+
+ String FILE_TYPE_PEM = "PEM";
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/KeyAttributeConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/KeyAttributeConstant.java
new file mode 100644
index 0000000..e02ccf0
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/KeyAttributeConstant.java
@@ -0,0 +1,46 @@
+package com.sunyard.ssp.common.constant;
+
+/**
+ * @author:tsz
+ * @date:2020/4/29
+ * @description:
+ */
+public interface KeyAttributeConstant {
+
+ /**
+ *@author :tsz
+ *@date :2020/04/29 14:05
+ *@description : 密钥状态 启用
+ */
+ Integer STATUS_ENABLE = 0;
+ /**
+ *@author :tsz
+ *@date :2020/04/29 14:05
+ *@description : 密钥状态 停用
+ */
+ Integer STATUS_DISABLE = 1;
+
+ /**
+ *@date : 2020:06:12 14:55
+ *@description : 导入开关
+ */
+ Integer IMPORT_SWITCH_ENABLE = 0;
+
+ /**
+ *@date : 2020:06:12 14:55
+ *@description : 导入开关
+ */
+ Integer IMPORT_SWITCH_DISABLE = 1;
+
+ /**
+ *@date : 2020:06:12 15:21
+ *@description : 导出
+ */
+ Integer EXPORT_SWITCH_DISABLE = 1;
+
+ Integer TMPL_TYPE_TWO = 2;
+
+ Integer TMPL_TYPE_THREE = 3;
+
+ Integer TMPL_TYPE_ONE = 1;
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/KeyConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/KeyConstant.java
new file mode 100644
index 0000000..d1b4264
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/KeyConstant.java
@@ -0,0 +1,16 @@
+package com.sunyard.ssp.common.constant;
+
+/**
+ * @author:tsz
+ * @date:2020/4/7
+ * @description:
+ */
+public interface KeyConstant {
+ //密钥启用长度限制
+ Integer KEYNAME_LENGTH = 1000;
+
+ Integer DEFAULT_VERSION = 0;
+
+ Integer TYPE_ONE = 1;
+
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/KeySolutionConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/KeySolutionConstant.java
new file mode 100644
index 0000000..321e694
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/KeySolutionConstant.java
@@ -0,0 +1,33 @@
+package com.sunyard.ssp.common.constant;
+
+/**
+ * @author:tsz
+ * @date:2020/4/21
+ * @description:
+ */
+public interface KeySolutionConstant {
+
+ /**
+ *@author :tsz
+ *@date :2020/04/21 10:59
+ *@description : 模版里边的密钥名称key
+ */
+ String KEY_NAME = "keyName";
+ /**
+ *@date : 2020:06:10 15:55
+ *@description : 密钥模板里的密钥类型
+ */
+ String KEY_TYPE = "keyType";
+ /**
+ *@date : 2020:06:10 15:55
+ *@description : 密钥模板里的密钥类型 公钥
+ */
+ String PK = "PK";
+
+ /**
+ *@date : 2020:06:10 15:55
+ *@description : 密钥模板里的密钥类型 私钥
+ */
+ String SK = "SK";
+
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/NodeConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/NodeConstant.java
new file mode 100644
index 0000000..b422d9f
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/NodeConstant.java
@@ -0,0 +1,16 @@
+package com.sunyard.ssp.common.constant;
+
+/**
+ * @author:tsz
+ * @date:2020/4/21
+ * @description:
+ */
+public interface NodeConstant {
+
+ /**
+ *@author :tsz
+ *@date :2020/04/21 10:50
+ *@description : 节点父id默认值
+ */
+ Long PID = -1L;
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ParamConfKeyConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ParamConfKeyConstant.java
new file mode 100644
index 0000000..64ce227
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ParamConfKeyConstant.java
@@ -0,0 +1,124 @@
+package com.sunyard.ssp.common.constant;
+
+/**
+ * @author:fyc
+ * @date:2020/3/17
+ * @description: 业务参数key值常量
+ */
+public interface ParamConfKeyConstant {
+
+ /**
+ * 白名单开关
+ */
+ String IP_WHITELIST_SWITCH = "ipWhitelistSwitch";
+
+ /**
+ * 通讯超时时间
+ */
+ String COMMUNICATE_TIME_OUT = "communicateTimeOut";
+
+ /**
+ * 心跳检测时间
+ */
+ String HEART_DETECT_TIME = "heartDetectTime";
+
+ /**
+ * 心跳包
+ */
+ String HEART_PACKAGE = "heartPackage";
+
+ /**
+ * ftp传输路径设置
+ */
+ String FTP_UPLOAD_PATH = "ftpUploadPath";
+
+ /**
+ * B端界面超时时间
+ */
+ String B_INTERFACE_TIMEOUT = "BInterfaceTimeOut";
+
+ /**
+ * 加密机操作审批
+ */
+ String ENCRYPTION_MACHINE_APPROVAL = "encryptionMachineApproval";
+
+ /**
+ * 秘钥操作审批
+ */
+ String SECRET_KEY_APPROVAL = "secretKeyApproval";
+
+ /**
+ * 登入模式
+ */
+ String LOGIN_METHOD = "loginMethod";
+
+ /**
+ * 是否开启图形码登入
+ */
+ String IS_USE_GRAPHIC_CODE = "isUseGraphicCode";
+
+ /**
+ * IP白名单配置类目数值
+ */
+ Integer IP_WHITELIST_ITEM = 0;
+
+ /**
+ * 通讯参数类目数值
+ */
+ Integer COMMUNICATE_PARAM_ITEM = 1;
+
+ /**
+ * 终端UI参数类目数值
+ */
+ Integer TERMINAL_PARAM_ITEM = 2;
+
+ /**
+ * 权限审批类目数值
+ */
+ Integer AUTHORITY_APPROVAL_PARAM_ITEM = 3;
+
+ /**
+ * 登入选项类目数值
+ */
+ Integer LOGIN_PARAM_ITEM = 4;
+
+ /**
+ * 审批结果true
+ */
+ String APPROVAL_TRUE = "true";
+
+ /**
+ * 审批结果false
+ */
+ String APPROVAL_FALSE = "false";
+
+ /**
+ * 调试模式类目数值
+ */
+ Integer SYS_PARAM_ITEM = 7;
+
+ /**
+ * 调试模式开关
+ */
+ String SYS_DEBUG_SWITCH = "sysDebugSwitch";
+
+ /**
+ * 系统初始化配置文件路劲
+ */
+ String SYS_PARAM_CONFIG_FILE_PATH = System.getProperty("user.dir") + "/config/sysParam.config.json";
+
+ /**
+ * 调试模式开关枚举
+ */
+ enum SYS_DEBUG_SWITCH_VALUE{
+ DEV("dev"), CONFIG("config"), PRODUCT("product");
+ private String value;
+ private SYS_DEBUG_SWITCH_VALUE(String value){
+ this.value = value;
+ }
+ public String getValue(){
+ return value;
+ }
+ }
+
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ProtocolConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ProtocolConstant.java
new file mode 100644
index 0000000..dbf5a76
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ProtocolConstant.java
@@ -0,0 +1,22 @@
+package com.sunyard.ssp.common.constant;
+
+/**
+ * @author:tsz
+ * @date:2020/4/21
+ * @description:
+ */
+public interface ProtocolConstant {
+
+ /**
+ *@author :tsz
+ *@date :2020/04/21 10:10
+ *@description : 入口协议
+ */
+ String ENTRANCE_TYPE = "0";
+
+ /**
+ *@date : 2020:05:25 14:56
+ *@description : 加密机协议
+ */
+ String DEVICE_TYPE = "2";
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/RegexConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/RegexConstant.java
new file mode 100644
index 0000000..935c2dd
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/RegexConstant.java
@@ -0,0 +1,96 @@
+package com.sunyard.ssp.common.constant;
+
+/**
+ * @author:tsz
+ * @date:2020/4/14
+ * @description: 正则规则
+ */
+public interface RegexConstant {
+
+ /**
+ *@author :tsz
+ *@date :2020/04/14 16:48
+ *@description : 节点编号
+ */
+ String NODE_NUMBER = "\\d{6,12}";
+
+ /**
+ *@author :tsz
+ *@date :2020/04/14 16:49
+ *@description : 方案编号
+ */
+ String KEY_SOLUTION_NUMBER = "[A-Z][A-Z0-9]{2,5}";
+
+ /**
+ *@author :tsz
+ *@date :2020/04/14 16:50
+ *@description : 模板编号
+ */
+ String TMPL_NUMBER = "[A-Z][A-Z0-9]{2,5}";
+
+ /**
+ *@author :tsz
+ *@date :2020/04/14 16:52
+ *@description : 密钥名称
+ */
+ String KEY_NAME = "[A-Z][A-Z0-9]{2,5}";
+
+ /**
+ *@author :tsz
+ *@date :2020/04/15 10:37
+ *@description : 普通名称校验规则 1-15位的字符
+ */
+ String COMMON_NAME = "^.{1,30}$";
+
+ /**
+ *@author :tsz
+ *@date :2020/04/15 10:37
+ *@description : 普通名称校验规则 1-30位的数字,字母,汉字 备用,暂时没有用
+ */
+ String COMMON_NAME_TEST = "^[\\w\\u4e00-\\u9fa5]{2,30}$";
+ /**
+ *@date :2020/05/22 15:47
+ *@description : 加密机名称校验
+ */
+ String DEVICE_NAME = "^.{1,15}$";
+ /**
+ *@date :2020/05/22 15:47
+ *@description : 加密机编号校验
+ */
+ String DEVICE_NUMBER = "^[1-9]\\d*$";
+ /**
+ *@date :2020/05/22 15:47
+ *@description : 加密机ipv4校验
+ */
+ String DEVICE_IPV4 = "^((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)$";
+ /**
+ *@date :2020/05/22 15:47
+ *@description : 加密机ipv6校验
+ */
+ String DEVICE_IPV6 = "^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*$";
+
+ /**
+ *@date :2020/05/22 15:47
+ *@description : 加密机端口号校验
+ */
+ String DEVICE_PORT = "^([0-9]|[1-9]\\d{1,3}|[1-5]\\d{4}|6[0-5]{2}[0-3][0-5])$";
+
+ /**
+ *@date :2020/05/22 15:47
+ *@description : 加密机设备型号校验
+ */
+ String DEVICE_MODEL= "^.{1,15}$";
+
+ /**
+ *@date :2020/05/22 15:47
+ *@description : 加密机资产类型校验
+ */
+ String DEVICE_ASSETTYPE= "^.{1,15}$";
+
+ /**
+ *@date : 2020:05:28 13:52
+ *@description : 证书检测是否是base64加密的
+ */
+ String CERTIFICATE_CONTENT = "[-]{5}BEGIN[\\s]*[\\w\\s]*[-]{5}[\\s]*[a-zA-Z\\d\\s/+]*[=]{0,2}[\\s]*[-]{5}END[\\s]*[\\w\\s]*[-]{5}[\\s]*";
+
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/SdkConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/SdkConstant.java
new file mode 100644
index 0000000..a22f768
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/SdkConstant.java
@@ -0,0 +1,86 @@
+package com.sunyard.ssp.common.constant;
+
+/**
+ * @author:tsz
+ * @date:2020/5/6
+ * @description:
+ */
+public interface SdkConstant {
+
+ /**
+ *@date : 2020:05:25 14:31
+ *@description : 渠道通信key
+ */
+ String SERVER_CLUSTER = "SERVER_CLUSTER";
+
+ /**
+ *@date : 2020:05:25 14:32
+ *@description : 渠道验证
+ */
+ String CHANNEL_CHECK = "channel.check";
+
+
+ /**
+ *@date :2020/05/25 14:02
+ *@description : 渠道更新命令
+ */
+ String CHANNEL_CMD_UPDATE = "channel.enable.update";
+
+ /**
+ *@date :2020/05/25 14:02
+ *@description : 渠道中的密钥方案变动
+ */
+ String CHANNEL_CMD_SOLUTION_UPDATE = "channel.solution.update";
+
+ String PING = "ping";
+
+ /**
+ *@date : 2020:05:25 15:04
+ *@description : 协议变动
+ */
+ String PROTO_UPDATE = "proto.update";
+
+ /**
+ *@date : 2020:05:25 15:04
+ *@description : 加密机组变动
+ */
+ String HSMGROUP_UPDATE = "hsmgroup.update";
+
+ /**
+ *@date : 2020:05:25 15:04
+ *@description : 加密机组变动
+ */
+ String HSM_UPDATE = "hsm.update";
+
+ /**
+ *@date : 2020:06:03 11:01
+ *@description : 模板变更
+ */
+ String KEYTEMPLATE_UPDATE= "keytemplate.update";
+
+ /**
+ *@date : 2020:05:25 15:04
+ *@description : 加密机协议校验
+ */
+ String PROTO_CHECK = "proto.check";
+
+ /**
+ *@date :2020/05/25 14:24
+ *@description : 密钥更新命令
+ */
+ String KEY_CMD_UPDATE = "key.update";
+
+ String IDENTITY_MANAGER = "Manager";
+
+ /**
+ *@date :2020/05/25 14:23
+ *@description : sdk通信加密的jks配置文件位置
+ */
+ String CLIENT_TRUSTSTORE = "config/clientTruststore.jks";
+
+ /**
+ *@date :2020/05/25 14:23
+ *@description : sdk通信加密的jks 通知字段
+ */
+ String CLIENT_KEY = "client";
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/SecurityConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/SecurityConstant.java
new file mode 100644
index 0000000..0265448
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/SecurityConstant.java
@@ -0,0 +1,78 @@
+package com.sunyard.ssp.common.constant;
+
+/**
+ * @author Exrickx
+ */
+public interface SecurityConstant {
+
+ /**
+ * token分割
+ */
+ String TOKEN_SPLIT = "Bearer ";
+
+ /**
+ * JWT签名加密key
+ */
+ String JWT_SIGN_KEY = "keeper";
+
+ /**
+ * token参数头
+ */
+ String HEADER = "accessToken";
+
+ /**
+ * 权限参数头
+ */
+ String AUTHORITIES = "authorities";
+
+ /**
+ * 用户选择JWT保存时间参数头
+ */
+ String SAVE_LOGIN = "saveLogin";
+
+ /**
+ * github保存state前缀key
+ */
+ String GITHUB_STATE = "KEEPER_GITHUB:";
+
+ /**
+ * qq保存state前缀key
+ */
+ String QQ_STATE = "KEEPER_QQ:";
+
+ /**
+ * qq保存state前缀key
+ */
+ String WEIBO_STATE = "KEEPER_WEIBO:";
+
+ /**
+ * 交互token前缀key
+ */
+ String TOKEN_PRE = "KEEPER_TOKEN_PRE:";
+
+ /**
+ * 用户token前缀key 单点登录使用
+ */
+ String USER_TOKEN = "KEEPER_USER_TOKEN:";
+
+ /**
+ * 用户登陆之后的租户识别id
+ * @auther: ZS
+ * @description:
+ * @param:
+ * @return:
+ * @date: 2019/3/20 16:21
+ */
+ String TENANT_ID = "KEEPER_TENANT_ID";
+
+ /**
+ * 更新用户接口url
+ * @auther: ZS
+ * @description:
+ * @param:
+ * @return:
+ * @date: 2019/7/31 14:54
+ */
+ String USER_UPDATE_URL = "/keeper/user/admin/edit";
+
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/SqlConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/SqlConstant.java
new file mode 100644
index 0000000..8788bc6
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/SqlConstant.java
@@ -0,0 +1,19 @@
+package com.sunyard.ssp.common.constant;
+
+/**
+ * @author:tsz
+ * @date:2020/3/13
+ * @description:
+ */
+public interface SqlConstant {
+
+ /**
+ * 通配符
+ */
+ String SQL_LIKE_WILDCARD = "%";
+
+ /**
+ * 数据库排序字段
+ */
+ String DB_SORT_COLUMN = "SORT_ORDER";
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/SspServerConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/SspServerConstant.java
new file mode 100644
index 0000000..7b64901
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/SspServerConstant.java
@@ -0,0 +1,9 @@
+package com.sunyard.ssp.common.constant;
+
+public interface SspServerConstant {
+ /**
+ * 通配符
+ */
+ //sspserver端口号
+ int SERVER_PORT = 8800;
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ValidatorConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ValidatorConstant.java
new file mode 100644
index 0000000..027b5bf
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/ValidatorConstant.java
@@ -0,0 +1,15 @@
+package com.sunyard.ssp.common.constant;
+
+public interface ValidatorConstant {
+
+ String POSTION_BASE_NAME = "position";
+
+ String POSTION_FORM_TITLE_KEY = "title";
+
+ String DEPARTMENT_BASE_NAME = "department";
+
+ String PERMISSION_BASE_NAME = "permission";
+
+ String ROLE_BASE_NAME = "role";
+
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/WorkflowConstant.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/WorkflowConstant.java
new file mode 100644
index 0000000..fa6059c
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/constant/WorkflowConstant.java
@@ -0,0 +1,50 @@
+package com.sunyard.ssp.common.constant;
+
+/**
+ * @author:tsz
+ * @date:2020/3/13
+ * @description:
+ */
+public interface WorkflowConstant {
+
+ /********************************************************
+ @author :tsz
+ @date :2020/03/13 17:16
+ @description : 渠道
+ ********************************************************/
+ String TYPE_SYSTEM = "system";
+
+ /**
+ *@date :2020/05/11 10:59
+ *@description : 申请时判断是否可以添加
+ */
+ Integer [] APPLICANTID_STATUS = {1,2};
+
+ /**
+ *@author :tsz
+ *@date :2020/03/26 13:52
+ *@description : 加密机
+ */
+ String TYPE_ENCRYTOR = "encrytor";
+
+ /**
+ *@date :2020/03/24 10:17
+ *@description : 审批通过
+ */
+ Integer STATUS_APPROVAL = 2;
+
+ /**
+ *@date :2020/03/24 10:17
+ *@description : 待审批
+ */
+ Integer STATUS_PENDING_APPROVAL = 1;
+
+ /**
+ *@author :tsz
+ *@date :2020/03/24 10:17
+ *@description : 生命周期添加
+ */
+ Integer LIFECYCLE_ADD = 0;
+
+ Integer ENABLED = 0;
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/enums/UserHeaderTypeEnum.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/enums/UserHeaderTypeEnum.java
new file mode 100644
index 0000000..6cdad77
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/enums/UserHeaderTypeEnum.java
@@ -0,0 +1,52 @@
+package com.sunyard.ssp.common.enums;
+
+import com.sunyard.ssp.common.constant.CommonConstant;
+
+public enum UserHeaderTypeEnum {
+ HEADER_TYPE_MAIN(CommonConstant.HEADER_TYPE_MAIN,"main"),
+ HEADER_TYPE_VICE(CommonConstant.HEADER_TYPE_VICE,"vice"),
+ HEADER_TYPE_NONE(CommonConstant.HEADER_TYPE_NONE,"none")
+ ;
+
+ private Integer key;
+ private String name;
+
+ UserHeaderTypeEnum(Integer statusKey, String statusName) {
+ this.key = statusKey;
+ this.name = statusName;
+ }
+
+ public Integer getKey() {
+ return key;
+ }
+
+ public void setKey(Integer key) {
+ this.key = key;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public static String getNameByKey(Integer key){
+ for (UserHeaderTypeEnum applicationStatus : UserHeaderTypeEnum.values()) {
+ if(applicationStatus.getKey().equals(key)){
+ return applicationStatus.getName();
+ }
+ }
+ return null;
+ }
+
+ public static Integer getKeyByName(String name){
+ for (UserHeaderTypeEnum applicationStatus : UserHeaderTypeEnum.values()) {
+ if(applicationStatus.getName().equals(name)){
+ return applicationStatus.getKey();
+ }
+ }
+ return null;
+ }
+}
diff --git a/chsm-web-manage/src/main/java/com/sunyard/ssp/common/exception/GlobalExceptionResolver.java b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/exception/GlobalExceptionResolver.java
new file mode 100644
index 0000000..5328e32
--- /dev/null
+++ b/chsm-web-manage/src/main/java/com/sunyard/ssp/common/exception/GlobalExceptionResolver.java
@@ -0,0 +1,96 @@
+package com.sunyard.ssp.common.exception;
+
+import com.sunyard.ssp.common.Result;
+import com.sunyard.ssp.utils.ResultUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.mybatis.spring.MyBatisSystemException;
+import org.springframework.validation.BindException;
+import org.springframework.validation.FieldError;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+/**
+ * 全局controller异常处理
+ * @auther: ZS
+ * @description:
+ * @param:
+ * @return:
+ * @date: 2020/5/25 16:24
+ */
+@Slf4j
+@ControllerAdvice
+public class GlobalExceptionResolver {
+
+ /**
+ * 处理所有不可知异常
+ *
+ * @param e 异常
+ * @return json结果
+ */
+// @ExceptionHandler(Exception.class)
+// @ResponseBody
+// public Result