Quellcode durchsuchen

初始化提交

zsy vor 7 Monaten
Commit
aa4741636c
61 geänderte Dateien mit 5375 neuen und 0 gelöschten Zeilen
  1. 20 0
      .gitignore
  2. 3 0
      README.md
  3. 118 0
      build.gradle
  4. 234 0
      gradlew
  5. 89 0
      gradlew.bat
  6. 1 0
      settings.gradle
  7. 57 0
      src/main/java/com/rf/fileCrack/FileCrackApplication.java
  8. 46 0
      src/main/java/com/rf/fileCrack/base/model/BaseEntity.java
  9. 18 0
      src/main/java/com/rf/fileCrack/base/repository/BaseRepository.java
  10. 76 0
      src/main/java/com/rf/fileCrack/base/rest/BaseController.java
  11. 30 0
      src/main/java/com/rf/fileCrack/config/CorsConfig.java
  12. 22 0
      src/main/java/com/rf/fileCrack/config/Properties.java
  13. 87 0
      src/main/java/com/rf/fileCrack/config/RedisConfig.java
  14. 75 0
      src/main/java/com/rf/fileCrack/config/StaticScheduleTask.java
  15. 51 0
      src/main/java/com/rf/fileCrack/config/Swagger2Config.java
  16. 18 0
      src/main/java/com/rf/fileCrack/dao/dto/JpaDto.java
  17. 21 0
      src/main/java/com/rf/fileCrack/dao/dto/ProgressDto.java
  18. 49 0
      src/main/java/com/rf/fileCrack/dao/dto/UserRecordsDto.java
  19. 2 0
      src/main/java/com/rf/fileCrack/dao/lombok.config
  20. 40 0
      src/main/java/com/rf/fileCrack/file/dao/model/FileEntity.java
  21. 25 0
      src/main/java/com/rf/fileCrack/file/dao/repository/FileRepository.java
  22. 88 0
      src/main/java/com/rf/fileCrack/file/rest/FileController.java
  23. 20 0
      src/main/java/com/rf/fileCrack/file/service/FileService.java
  24. 37 0
      src/main/java/com/rf/fileCrack/file/service/impl/FileServiceImpl.java
  25. 93 0
      src/main/java/com/rf/fileCrack/filter/AuthenticationInterceptor.java
  26. 62 0
      src/main/java/com/rf/fileCrack/filter/JWTInterceptor.java
  27. 56 0
      src/main/java/com/rf/fileCrack/filter/JWTInterceptorConfig.java
  28. 12 0
      src/main/java/com/rf/fileCrack/filter/JwtIgnore.java
  29. 33 0
      src/main/java/com/rf/fileCrack/filter/UserCheckInterceptor.java
  30. 71 0
      src/main/java/com/rf/fileCrack/security/AesEncryptUtils.java
  31. 107 0
      src/main/java/com/rf/fileCrack/security/DESede.java
  32. 67 0
      src/main/java/com/rf/fileCrack/security/SSLConfig.java
  33. 18 0
      src/main/java/com/rf/fileCrack/security/SafetyProcess.java
  34. 40 0
      src/main/java/com/rf/fileCrack/socket/MyClient.java
  35. 24 0
      src/main/java/com/rf/fileCrack/socket/WebSocketConfig.java
  36. 213 0
      src/main/java/com/rf/fileCrack/socket/WebSocketServer.java
  37. 50 0
      src/main/java/com/rf/fileCrack/utils/AgeUtil.java
  38. 324 0
      src/main/java/com/rf/fileCrack/utils/AssertUtils.java
  39. 41 0
      src/main/java/com/rf/fileCrack/utils/CPUSerial.java
  40. 35 0
      src/main/java/com/rf/fileCrack/utils/Constant.java
  41. 133 0
      src/main/java/com/rf/fileCrack/utils/Data.java
  42. 1228 0
      src/main/java/com/rf/fileCrack/utils/DateUtil.java
  43. 71 0
      src/main/java/com/rf/fileCrack/utils/EmailUtil.java
  44. 19 0
      src/main/java/com/rf/fileCrack/utils/HttpStatus.java
  45. 32 0
      src/main/java/com/rf/fileCrack/utils/IPUtiles.java
  46. 70 0
      src/main/java/com/rf/fileCrack/utils/JWTUtil.java
  47. 35 0
      src/main/java/com/rf/fileCrack/utils/LocalAssert.java
  48. 131 0
      src/main/java/com/rf/fileCrack/utils/OSUtil.java
  49. 17 0
      src/main/java/com/rf/fileCrack/utils/PageRequestUtil.java
  50. 431 0
      src/main/java/com/rf/fileCrack/utils/RandomUtil.java
  51. 62 0
      src/main/java/com/rf/fileCrack/utils/Result.java
  52. 112 0
      src/main/java/com/rf/fileCrack/utils/SendEmail.java
  53. 44 0
      src/main/java/com/rf/fileCrack/utils/WebContextUtil.java
  54. 80 0
      src/main/java/com/rf/fileCrack/utils/XMLUtil.java
  55. 140 0
      src/main/java/com/rf/fileCrack/utils/ZipUtils.java
  56. 48 0
      src/main/resources/config/application-prod.yml
  57. 51 0
      src/main/resources/config/application-test.yml
  58. 26 0
      src/main/resources/config/application.yml
  59. 144 0
      src/main/resources/logback.xml
  60. 28 0
      src/main/resources/proguard.conf
  61. BIN
      uploadFile/1733888808310-测评结果汇总.xlsx

+ 20 - 0
.gitignore

@@ -0,0 +1,20 @@
+# ---> Java
+*.class
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.ear
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+
+/.gradle/
+/build/
+/src/main/resources/static/
+/logs/
+/gradle/
+/.idea/

+ 3 - 0
README.md

@@ -0,0 +1,3 @@
+# AIFile_crack
+
+review code

+ 118 - 0
build.gradle

@@ -0,0 +1,118 @@
+buildscript {
+	ext {
+		queryDslVersion = '4.2.1'
+		lombokVersion = '1.18.12'
+	}
+}
+plugins {
+	id 'org.springframework.boot' version '2.4.2'
+	id 'io.spring.dependency-management' version '1.0.11.RELEASE'
+	id 'java'
+}
+
+group = 'com.rf'
+version = 'v1.1-'+getNewVersion()
+sourceCompatibility = '8'
+
+configurations {
+	compileOnly {
+		extendsFrom annotationProcessor
+	}
+}
+
+repositories {
+	maven {
+		url 'https://maven.aliyun.com/repository/public'
+	}
+	maven {
+		credentials {
+			username '0p07qf'
+			password 'z1XwdFEf4M'
+		}
+		url 'https://repo.rdc.aliyun.com/repository/107260-release-GqdtcU/'
+	}
+	maven {
+		credentials {
+			username '0p07qf'
+			password 'z1XwdFEf4M'
+		}
+		url 'https://repo.rdc.aliyun.com/repository/107260-snapshot-C6ziam/'
+	}
+	maven {
+		url "https://plugins.gradle.org/m2/"
+	}
+	mavenLocal()
+}
+
+dependencies {
+	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
+	implementation 'org.springframework.boot:spring-boot-starter-web'
+	compileOnly 'org.projectlombok:lombok'
+	annotationProcessor 'org.projectlombok:lombok'
+	implementation 'org.springframework.boot:spring-boot-starter-validation:2.6.3'
+
+	implementation 'mysql:mysql-connector-java:8.0.21'
+
+	implementation("com.querydsl:querydsl-core:${queryDslVersion}")
+	implementation("com.querydsl:querydsl-jpa:${queryDslVersion}")
+	annotationProcessor("com.querydsl:querydsl-apt:${queryDslVersion}:jpa",
+			"org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.2.Final",
+			"javax.annotation:javax.annotation-api:1.3.2",
+			"org.projectlombok:lombok")
+
+	compileOnly "org.projectlombok:lombok:${lombokVersion}"
+	annotationProcessor "org.projectlombok:lombok:${lombokVersion}"
+	implementation("org.projectlombok:lombok:${lombokVersion}")
+	testImplementation 'org.springframework.boot:spring-boot-starter-test:2.6.3'
+
+	implementation 'com.alibaba:fastjson:1.2.83'
+	implementation 'org.apache.poi:poi-ooxml:3.17'
+
+	implementation 'commons-lang:commons-lang:2.6'
+
+	implementation group: 'io.springfox', name: 'springfox-swagger2', version: '2.9.2'
+	implementation group: 'io.springfox', name: 'springfox-swagger-ui', version: '2.9.2'
+	implementation group: 'io.swagger', name: 'swagger-annotations', version: '1.5.22'
+	implementation group: 'io.swagger', name: 'swagger-models', version: '1.5.22'
+	implementation group: 'commons-fileupload', name: 'commons-fileupload', version: '1.3.1'
+	implementation group: 'com.github.qcloudsms', name: 'qcloudsms', version: '1.0.6'
+	implementation group: 'cn.keking.project', name: 'kk-anti-reptile', version: '1.0.0-RELEASE'
+	implementation group: 'com.belerweb', name: 'pinyin4j', version: '2.5.1'
+	implementation 'org.springframework.boot:spring-boot-starter-websocket:2.5.5'
+	implementation 'org.java-websocket:Java-WebSocket:1.5.1'
+	implementation 'com.auth0:java-jwt:3.18.2'
+	implementation group: 'com.alibaba', name: 'druid-spring-boot-starter', version: '1.2.9'
+	testImplementation group: 'junit', name: 'junit', version: '4.13.2'
+	implementation 'com.github.wechatpay-apiv3:wechatpay-apache-httpclient:0.4.7'
+
+	implementation group: 'org.springframework.boot', name: 'spring-boot-configuration-processor', version: '2.6.8'
+
+	implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.6'
+
+	implementation group: 'cn.hutool', name: 'hutool-all', version: '5.7.18'
+
+	implementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-redis', version: '2.6.3'
+
+	implementation group: 'org.dom4j', name: 'dom4j', version: '2.1.1'
+
+	implementation group: 'commons-net', name: 'commons-net', version: '3.6'
+
+	implementation group: 'dnsjava', name: 'dnsjava', version: '2.1.1'
+
+	implementation group: 'com.sun.mail', name: 'javax.mail', version: '1.6.2'
+
+
+
+
+
+
+
+}
+
+test {
+	useJUnitPlatform()
+}
+
+def getNewVersion(){
+	return new Date().format("yyyyMMddHHmmss",TimeZone.getTimeZone("GMT+08:00"))
+}

+ 234 - 0
gradlew

@@ -0,0 +1,234 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+#   Gradle start up script for POSIX generated by Gradle.
+#
+#   Important for running:
+#
+#   (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+#       noncompliant, but you have some other compliant shell such as ksh or
+#       bash, then to run this script, type that shell name before the whole
+#       command line, like:
+#
+#           ksh Gradle
+#
+#       Busybox and similar reduced shells will NOT work, because this script
+#       requires all of these POSIX shell features:
+#         * functions;
+#         * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+#           «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+#         * compound commands having a testable exit status, especially «case»;
+#         * various built-in commands including «command», «set», and «ulimit».
+#
+#   Important for patching:
+#
+#   (2) This script targets any POSIX shell, so it avoids extensions provided
+#       by Bash, Ksh, etc; in particular arrays are avoided.
+#
+#       The "traditional" practice of packing multiple parameters into a
+#       space-separated string is a well documented source of bugs and security
+#       problems, so this is (mostly) avoided, by progressively accumulating
+#       options in "$@", and eventually passing that to Java.
+#
+#       Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+#       and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+#       see the in-line comments for details.
+#
+#       There are tweaks for specific operating systems such as AIX, CygWin,
+#       Darwin, MinGW, and NonStop.
+#
+#   (3) This script is generated from the Groovy template
+#       https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+#       within the Gradle project.
+#
+#       You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+    APP_HOME=${app_path%"${app_path##*/}"}  # leaves a trailing /; empty if no leading path
+    [ -h "$app_path" ]
+do
+    ls=$( ls -ld "$app_path" )
+    link=${ls#*' -> '}
+    case $link in             #(
+      /*)   app_path=$link ;; #(
+      *)    app_path=$APP_HOME$link ;;
+    esac
+done
+
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+
+APP_NAME="Gradle"
+APP_BASE_NAME=${0##*/}
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+    echo "$*"
+} >&2
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in                #(
+  CYGWIN* )         cygwin=true  ;; #(
+  Darwin* )         darwin=true  ;; #(
+  MSYS* | MINGW* )  msys=true    ;; #(
+  NONSTOP* )        nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD=$JAVA_HOME/jre/sh/java
+    else
+        JAVACMD=$JAVA_HOME/bin/java
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD=java
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+    case $MAX_FD in #(
+      max*)
+        MAX_FD=$( ulimit -H -n ) ||
+            warn "Could not query maximum file descriptor limit"
+    esac
+    case $MAX_FD in  #(
+      '' | soft) :;; #(
+      *)
+        ulimit -n "$MAX_FD" ||
+            warn "Could not set maximum file descriptor limit to $MAX_FD"
+    esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+#   * args from the command line
+#   * the main class name
+#   * -classpath
+#   * -D...appname settings
+#   * --module-path (only if needed)
+#   * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+    APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+    CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+    JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    for arg do
+        if
+            case $arg in                                #(
+              -*)   false ;;                            # don't mess with options #(
+              /?*)  t=${arg#/} t=/${t%%/*}              # looks like a POSIX filepath
+                    [ -e "$t" ] ;;                      #(
+              *)    false ;;
+            esac
+        then
+            arg=$( cygpath --path --ignore --mixed "$arg" )
+        fi
+        # Roll the args list around exactly as many times as the number of
+        # args, so each arg winds up back in the position where it started, but
+        # possibly modified.
+        #
+        # NB: a `for` loop captures its iteration list before it begins, so
+        # changing the positional parameters here affects neither the number of
+        # iterations, nor the values presented in `arg`.
+        shift                   # remove old arg
+        set -- "$@" "$arg"      # push replacement arg
+    done
+fi
+
+# Collect all arguments for the java command;
+#   * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+#     shell script including quotes and variable substitutions, so put them in
+#     double quotes to make sure that they get re-expanded; and
+#   * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+        "-Dorg.gradle.appname=$APP_BASE_NAME" \
+        -classpath "$CLASSPATH" \
+        org.gradle.wrapper.GradleWrapperMain \
+        "$@"
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+#   readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+#   set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+        printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+        xargs -n1 |
+        sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+        tr '\n' ' '
+    )" '"$@"'
+
+exec "$JAVACMD" "$@"

+ 89 - 0
gradlew.bat

@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem      https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega

+ 1 - 0
settings.gradle

@@ -0,0 +1 @@
+rootProject.name = 'AIFile_crack'

+ 57 - 0
src/main/java/com/rf/fileCrack/FileCrackApplication.java

@@ -0,0 +1,57 @@
+package com.rf.fileCrack;
+
+import com.querydsl.jpa.impl.JPAQueryFactory;
+import lombok.extern.slf4j.Slf4j;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.context.annotation.Bean;
+import org.springframework.core.env.Environment;
+import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+import javax.persistence.EntityManager;
+
+/**
+ * @author zzf
+ */
+@EnableJpaRepositories(basePackages = {"com.rf.fileCrack"})
+@SpringBootApplication(scanBasePackages = {"com.rf.fileCrack"})
+@EnableJpaAuditing
+@EnableTransactionManagement
+@EnableScheduling
+@Slf4j
+public class FileCrackApplication {
+
+    static Logger logger = LoggerFactory.getLogger(FileCrackApplication.class);
+    @Autowired
+    static Environment environment;
+    @Value("${spring.profiles.active}")
+    static String profile;
+
+
+    public static void main(String[] args) {
+
+        SpringApplication.run(FileCrackApplication.class, args);
+
+    }
+
+
+    /**
+     * 让Spring管理JPAQueryFactory
+     *
+     * @param entityManager
+     * @return
+     */
+    @Bean
+    public JPAQueryFactory jpaQueryFactory(EntityManager entityManager) {
+        return new JPAQueryFactory(entityManager);
+    }
+
+
+}

+ 46 - 0
src/main/java/com/rf/fileCrack/base/model/BaseEntity.java

@@ -0,0 +1,46 @@
+package com.rf.fileCrack.base.model;
+
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+import org.hibernate.annotations.GenericGenerator;
+import org.springframework.data.jpa.domain.support.AuditingEntityListener;
+
+import javax.persistence.*;
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+
+/**
+ * @author zzf
+ * @description:
+ * @date 2021/1/18 19:13
+ */
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@EntityListeners({AuditingEntityListener.class})
+@MappedSuperclass
+public class BaseEntity implements Serializable {
+    @Getter
+    @Id
+    @GenericGenerator(name = "jpa-uuid", strategy = "uuid")
+    @GeneratedValue(generator = "jpa-uuid")
+    @Column(name = "id", columnDefinition = "varchar(36) COMMENT '数据ID'")
+    @NotNull(groups = Update.class)
+    private String id;
+
+    @Column(name = "create_time", columnDefinition = "varchar(36) COMMENT '创建时间'")
+    private String createTime;
+
+
+    @Column(name = "update_time", columnDefinition = "varchar(36) COMMENT '更新时间'")
+    private String updateTime;
+
+
+
+    public @interface Update {
+    }
+}

+ 18 - 0
src/main/java/com/rf/fileCrack/base/repository/BaseRepository.java

@@ -0,0 +1,18 @@
+package com.rf.fileCrack.base.repository;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.querydsl.QuerydslPredicateExecutor;
+import org.springframework.data.repository.NoRepositoryBean;
+
+import java.io.Serializable;
+
+/**
+ * @author zzf
+ * @description:
+ * @date 2021/1/18 19:17
+ */
+@NoRepositoryBean
+public interface BaseRepository<T, PK extends Serializable> extends JpaRepository<T, PK>, JpaSpecificationExecutor, QuerydslPredicateExecutor<T> {
+
+}

+ 76 - 0
src/main/java/com/rf/fileCrack/base/rest/BaseController.java

@@ -0,0 +1,76 @@
+package com.rf.fileCrack.base.rest;
+
+import com.rf.fileCrack.utils.HttpStatus;
+import com.rf.fileCrack.utils.Result;
+
+
+/**
+ * @author zzf
+ * @description:
+ * @date 2021/1/18 19:20
+ */
+public class BaseController {
+    protected static final String PAGE_NUM = "pageNum";
+
+    protected static final String PAGE_SIZE = "pageSize";
+
+    protected Result success() {
+        return success(null, "成功");
+    }
+
+    protected static <T> Result<T> success(T data) {
+        return success(data, "成功");
+    }
+
+    protected static <T> Result<T> success(T data, String message) {
+        if (null == data) {
+            return new Result<>(HttpStatus.SUCCESS, message);
+        }
+        return new Result<>(HttpStatus.SUCCESS, message, data);
+    }
+
+    protected static <T> Result<T> success(String code,T data, String message) {
+        if (null == data) {
+            return new Result<>(code, message);
+        }
+        return new Result<>(code, message, data);
+    }
+
+    protected Result fail() {
+        return fail(null, "失败");
+    }
+
+    protected static <T> Result<T> fail(T data) {
+        return fail(data, "失败");
+    }
+
+    protected static <T> Result<T> fail(String message) {
+        return new Result<>(HttpStatus.RUNTIME_EXCEPTION, message);
+    }
+
+    protected static <T> Result<T> fail(String code ,T data ,String message){
+        if(data == null)
+            return new Result<>(code,message);
+        else
+            return new Result<>(code,message,data);
+    }
+
+    protected static <T> Result<T> fail(T data, String message) {
+        if (null == data) {
+            return new Result<>(HttpStatus.RUNTIME_EXCEPTION, message);
+        }
+        return new Result<>(HttpStatus.RUNTIME_EXCEPTION, message, data);
+    }
+
+    protected Result failBadRequest() {
+        return failBadRequest(null, "参数异常");
+    }
+
+    protected static <T> Result<T> failBadRequest(T data) {
+        return failBadRequest(null, "参数异常");
+    }
+
+    protected static <T> Result<T> failBadRequest(T data, String message) {
+        return new Result<>(org.springframework.http.HttpStatus.BAD_REQUEST.value() + "", message, data);
+    }
+}

+ 30 - 0
src/main/java/com/rf/fileCrack/config/CorsConfig.java

@@ -0,0 +1,30 @@
+package com.rf.fileCrack.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+
+@Configuration
+public class CorsConfig {
+
+    private CorsConfiguration buildConfig() {
+
+        CorsConfiguration corsConfiguration = new CorsConfiguration();
+        corsConfiguration.setAllowCredentials(true);
+        corsConfiguration.addAllowedOriginPattern("*");
+        corsConfiguration.addAllowedHeader("*");
+        corsConfiguration.addAllowedMethod("*");
+        return corsConfiguration;
+
+    }
+
+    @Bean
+    public CorsFilter corsFilter() {
+        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+        source.registerCorsConfiguration("/**", buildConfig());
+        return new CorsFilter(source);
+    }
+
+}

+ 22 - 0
src/main/java/com/rf/fileCrack/config/Properties.java

@@ -0,0 +1,22 @@
+package com.rf.fileCrack.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+import java.time.Duration;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @Author:zzf
+ * @Date:2022/7/5:18:15
+ * @Description:
+ */
+
+public class Properties {
+    private final Map<String, Duration> initCaches = new HashMap<>();
+    public Map<String ,Duration> getInitCache(){
+
+        return initCaches;
+    }
+}

+ 87 - 0
src/main/java/com/rf/fileCrack/config/RedisConfig.java

@@ -0,0 +1,87 @@
+package com.rf.fileCrack.config;
+
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.cache.CacheManager;
+import org.springframework.cache.annotation.CachingConfigurerSupport;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.cache.RedisCacheConfiguration;
+import org.springframework.data.redis.cache.RedisCacheManager;
+import org.springframework.data.redis.cache.RedisCacheWriter;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
+import org.springframework.data.redis.serializer.RedisSerializationContext;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+import java.time.Duration;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @Description:Redis缓存时间、序列化、反序列化等配置
+ * @Author: zsf
+ * @Date: 2022/7/1
+ */
+@Slf4j
+public class RedisConfig extends CachingConfigurerSupport {
+    @Autowired
+    private Properties properties;
+
+    @Bean
+    public CacheManager cacheManager(RedisConnectionFactory factory) {
+        RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration
+                .defaultCacheConfig()
+                .entryTtl(Duration.ofDays(30))
+                .disableCachingNullValues()
+                .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer()));
+        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(factory);
+        Set<String> cacheNames = new HashSet<>();
+        ConcurrentHashMap<String, RedisCacheConfiguration> cacheConfig = new ConcurrentHashMap<>();
+
+        properties.getInitCache().forEach((key, value) -> {
+            cacheNames.add(key);
+            cacheConfig.put(key,cacheConfiguration.entryTtl(value));
+        });
+        return RedisCacheManager.builder(redisCacheWriter)
+                .cacheDefaults(cacheConfiguration)
+                .initialCacheNames(cacheNames)
+                .withInitialCacheConfigurations(cacheConfig)
+                .build();
+    }
+
+
+    @Bean
+    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
+        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
+        redisTemplate.setConnectionFactory(redisConnectionFactory);
+        redisTemplate.setValueSerializer(jackson2JsonRedisSerializer());
+
+        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
+        redisTemplate.setKeySerializer(stringRedisSerializer);
+
+        redisTemplate.setHashKeySerializer(stringRedisSerializer);
+        redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer());
+        redisTemplate.afterPropertiesSet();
+        return redisTemplate;
+    }
+
+    public Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer() {
+        Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
+        ObjectMapper objectMapper = new ObjectMapper();
+
+        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
+
+        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
+
+        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
+        return jackson2JsonRedisSerializer;
+    }
+}

+ 75 - 0
src/main/java/com/rf/fileCrack/config/StaticScheduleTask.java

@@ -0,0 +1,75 @@
+package com.rf.fileCrack.config;
+
+import cn.hutool.core.date.DateUtil;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.rf.fileCrack.file.dao.model.FileEntity;
+import com.rf.fileCrack.file.service.FileService;
+import com.rf.fileCrack.socket.WebSocketServer;
+import com.rf.fileCrack.utils.SendEmail;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @Author:zzf
+ * @Date:2022/7/1:16:30
+ * @Description:测试计划相关的定时任务信息
+ */
+@Configuration
+@EnableScheduling
+@Slf4j
+public class StaticScheduleTask {
+
+    @Autowired
+    private FileService fileService;
+
+    /**
+     * 根据文件状态通知算法解密或解密完成通知用户
+     */
+    @Scheduled(initialDelay = 60000,fixedDelay = 60000)
+    public void updateFileStatus() throws IOException {
+        List<FileEntity> fileEntitys = this.fileService.findByFileStatus("1");
+        for (FileEntity fileEntity : fileEntitys){
+            JSONObject jsonObject = new JSONObject();
+            jsonObject.put("fileId",fileEntity.getId());
+            jsonObject.put("filePath",fileEntity.getFilePath());
+            WebSocketServer.sendInfo(jsonObject.toJSONString());
+            fileEntity.setFileStatus("2");
+            this.fileService.save(fileEntity);
+        }
+        fileEntitys = this.fileService.findByFileStatus("3");
+        for (FileEntity fileEntity : fileEntitys){
+            //根据邮箱查询用户信息
+            String email = fileEntity.getEmail();
+            if (email != null) {
+                SendEmail sendEmail=new SendEmail();
+                //破解密码
+                sendEmail.setPassword(fileEntity.getPassword());
+                //破解的文件名
+                String[] fileNames = fileEntity.getFilePath().split("-");
+                String fileName = fileNames[fileNames.length-1];
+                sendEmail.setFileName(fileName);
+                //设置要发送的邮箱
+                sendEmail.setReceiveMailAccount(email);
+                try {
+                    sendEmail.Send();
+                    fileEntity.setFileStatus("4");
+                    fileEntity.setUpdateTime(DateUtil.now());
+                    this.fileService.save(fileEntity);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+}

+ 51 - 0
src/main/java/com/rf/fileCrack/config/Swagger2Config.java

@@ -0,0 +1,51 @@
+package com.rf.fileCrack.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.ParameterBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.schema.ModelRef;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.service.Parameter;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author lpf
+ * @description:swagger 配置
+ * @date 2022/3/14 19:25
+ */
+@Configuration
+@EnableSwagger2
+@Profile({"test","lan"})
+public class Swagger2Config {
+
+    @Bean
+    public Docket createRestApi() {
+        ParameterBuilder tokenPar = new ParameterBuilder();
+        List<Parameter> pars = new ArrayList<>();
+        tokenPar.name("Authorization").description("token令牌,格式为Bearer Token(可从/test/token接口处获取临时测试token)").modelRef(new ModelRef("string")).parameterType("header").required(false).build();
+        pars.add(tokenPar.build());
+        return new Docket(DocumentationType.SWAGGER_2)
+                .apiInfo(apiInfo())
+                .select()
+                .apis(RequestHandlerSelectors.basePackage("com.rf.fileCrack"))
+                .paths(PathSelectors.any())
+                .build()
+                .globalOperationParameters(pars);
+    }
+
+    private ApiInfo apiInfo() {
+        return new ApiInfoBuilder()
+                .title("AI文件破解系统")
+                .version("v1.0")
+                .build();
+    }
+}

+ 18 - 0
src/main/java/com/rf/fileCrack/dao/dto/JpaDto.java

@@ -0,0 +1,18 @@
+package com.rf.fileCrack.dao.dto;
+
+import org.springframework.stereotype.Component;
+
+import java.lang.annotation.*;
+
+/**
+ * @author lpf
+ * @description: 自定义注解类,加载dto上表示这是个JpaDto类,解决jpa原生不能返回dto的问题
+ * @date 2022/4/6 21:08
+ */
+
+@Documented
+@Component
+@Target(value = {ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface JpaDto {
+}

+ 21 - 0
src/main/java/com/rf/fileCrack/dao/dto/ProgressDto.java

@@ -0,0 +1,21 @@
+package com.rf.fileCrack.dao.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author lpf
+ * @description:
+ * @date 2022/5/5 18:02
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class ProgressDto {
+
+    private long maxNum;
+
+    private long havingDoNum;
+
+}

+ 49 - 0
src/main/java/com/rf/fileCrack/dao/dto/UserRecordsDto.java

@@ -0,0 +1,49 @@
+package com.rf.fileCrack.dao.dto;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author lpf
+ * @description: 用户测试记录界面返回参数(去除返回参数中的答题参数testRecord,testResults(老的数据格式)减少传参大小)
+ * @date 2022/5/12 15:39
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class UserRecordsDto {
+
+    private String id;
+
+    private String phone;
+
+
+    private String institutionNo;
+
+
+    private String flag;
+
+
+    private String name;
+
+
+    private String testDate;
+
+
+    private String testResult;
+
+
+
+    private String fileName;
+
+
+    private String img;
+
+
+    private String type;
+
+
+    private String testPlanId;
+
+}

+ 2 - 0
src/main/java/com/rf/fileCrack/dao/lombok.config

@@ -0,0 +1,2 @@
+config.stopbubbling=true
+lombok.equalsandhashcode.callsuper=call

+ 40 - 0
src/main/java/com/rf/fileCrack/file/dao/model/FileEntity.java

@@ -0,0 +1,40 @@
+package com.rf.fileCrack.file.dao.model;
+
+import com.rf.fileCrack.base.model.BaseEntity;
+import lombok.*;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Index;
+import javax.persistence.Table;
+
+/**
+ * @author zsy
+ * @description:文件信息表
+ * @date 2021/6/17 15:55
+ */
+@Entity
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Table(name = "t_file_info")
+@EqualsAndHashCode(callSuper=true)
+@org.hibernate.annotations.Table(appliesTo = "t_file_info", comment = "文件信息表")
+public class FileEntity extends BaseEntity {
+
+    @Column(name = "email", columnDefinition = "varchar(50)  not null  comment '邮箱'")
+    private String email;
+
+    @Column(name = "call_word", columnDefinition = "varchar(100) comment '提示词'")
+    private String callWord;
+
+    @Column(name = "password", columnDefinition = "varchar(32) comment '密码'")
+    private String password;
+
+    @Column(name = "file_path", columnDefinition = "varchar(255) comment  '文件路径'")
+    private String filePath;
+
+    @Column(name = "file_status", columnDefinition = "varchar(10) default '1' comment '文件状态:1--已入库未开始解密,2--解密中,3--已解密未通知(邮箱有问题),4--已解密并通知'")
+    private String fileStatus;
+
+}

+ 25 - 0
src/main/java/com/rf/fileCrack/file/dao/repository/FileRepository.java

@@ -0,0 +1,25 @@
+package com.rf.fileCrack.file.dao.repository;
+
+import com.rf.fileCrack.base.repository.BaseRepository;
+import com.rf.fileCrack.file.dao.model.FileEntity;
+import org.apache.catalina.User;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.jpa.repository.Modifying;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.query.Param;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * @Description: 用户注册登录等相关接口
+ * @Author: zsy
+ * @Date: 2024/12/4
+ */
+public interface FileRepository extends BaseRepository<FileEntity, String> {
+
+
+    List<FileEntity> findByFileStatus(String fileStatus);
+}

+ 88 - 0
src/main/java/com/rf/fileCrack/file/rest/FileController.java

@@ -0,0 +1,88 @@
+package com.rf.fileCrack.file.rest;
+
+import cn.hutool.core.date.DateUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.rf.fileCrack.base.rest.BaseController;
+import com.rf.fileCrack.file.dao.model.FileEntity;
+import com.rf.fileCrack.file.service.FileService;
+import com.rf.fileCrack.socket.WebSocketServer;
+import com.rf.fileCrack.utils.Result;
+import com.rf.fileCrack.utils.SendEmail;
+import io.swagger.annotations.ApiOperation;
+import org.apache.commons.io.FileUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.multipart.MultipartFile;
+import javax.servlet.http.HttpServletRequest;
+import javax.websocket.Session;
+import java.io.File;
+import java.io.FileInputStream;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+
+import static com.rf.fileCrack.utils.EmailUtil.checkEmail;
+
+/**
+ * @Author:zzf
+ * @Date:2022/8/9:17:25
+ * @Description:
+ */
+
+@Controller
+@RequestMapping("/file")
+public class FileController extends BaseController {
+
+    @Autowired
+    private FileService fileService;
+
+    @PostMapping("/upload")
+    @ApiOperation(value = "上传文件",notes = "image 警报事件图片")
+    @ResponseBody
+    public Result uploadFile(MultipartFile file, String callWord, String email, HttpServletRequest request ) throws Exception {
+        if (!checkEmail(email)){
+            return fail("邮箱无效,请重新填写有效邮箱!");
+        };
+        String fileName = "";
+        String FILEDIR = "./uploadFile/";
+        if (file == null) {
+            throw new Exception("文件为空");
+        } else {
+            FileEntity fileEntity = new FileEntity();
+            if (!file.isEmpty()) {
+                fileName = System.currentTimeMillis()+"-"+file.getOriginalFilename();
+                try {
+                    File temp = new File(FILEDIR);
+                    if (!temp.exists()) {
+                        temp.mkdirs();
+                    }
+                    File fileLocal = new File(FILEDIR, fileName);
+                    FileUtils.copyInputStreamToFile(file.getInputStream(), fileLocal);
+                    fileEntity.setFilePath(FILEDIR+fileName);
+                    fileEntity.setEmail(email);
+                    fileEntity.setCallWord(callWord);
+                    fileEntity.setCreateTime(DateUtil.now());
+                    fileEntity.setUpdateTime(DateUtil.now());
+                    fileEntity = this.fileService.save(fileEntity);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                    throw new Exception("文件上传失败");
+                }
+                JSONObject jsonObject = new JSONObject();
+                jsonObject.put("fileId",fileEntity.getId());
+                jsonObject.put("filePath",fileEntity.getFilePath());
+                WebSocketServer.sendInfo(jsonObject.toJSONString());
+                fileEntity.setFileStatus("2");
+                this.fileService.save(fileEntity);
+            }
+        }
+        return success(FILEDIR+fileName);
+    }
+
+}

+ 20 - 0
src/main/java/com/rf/fileCrack/file/service/FileService.java

@@ -0,0 +1,20 @@
+package com.rf.fileCrack.file.service;
+
+import com.rf.fileCrack.file.dao.model.FileEntity;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * @Description: 用户注册登录等相关接口
+ * @Author: zsy
+ * @Date: 2024/12/4
+ */
+public interface FileService {
+
+    FileEntity save(FileEntity fileEntity);
+
+    FileEntity findById(String id);
+
+    List<FileEntity> findByFileStatus(String fileStatus);
+}

+ 37 - 0
src/main/java/com/rf/fileCrack/file/service/impl/FileServiceImpl.java

@@ -0,0 +1,37 @@
+package com.rf.fileCrack.file.service.impl;
+
+import com.rf.fileCrack.file.dao.model.FileEntity;
+import com.rf.fileCrack.file.dao.repository.FileRepository;
+import com.rf.fileCrack.file.service.FileService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * @Description: 用户注册登录等相关接口
+ * @Author: zsy
+ * @Date: 2024/12/4
+ */
+@Service
+public class FileServiceImpl implements FileService {
+
+    @Autowired
+    private FileRepository fileRepository;
+
+    @Override
+    public FileEntity save(FileEntity fileEntity) {
+        this.fileRepository.save(fileEntity);
+        return fileEntity;
+    }
+
+    @Override
+    public FileEntity findById(String id) {
+        return this.fileRepository.findById(id).get();
+    }
+
+    @Override
+    public List<FileEntity> findByFileStatus(String fileStatus) {
+        return this.fileRepository.findByFileStatus(fileStatus);
+    }
+}

+ 93 - 0
src/main/java/com/rf/fileCrack/filter/AuthenticationInterceptor.java

@@ -0,0 +1,93 @@
+package com.rf.fileCrack.filter;
+
+import com.alibaba.fastjson.JSON;
+import com.auth0.jwt.exceptions.AlgorithmMismatchException;
+import com.auth0.jwt.exceptions.SignatureVerificationException;
+import com.auth0.jwt.exceptions.TokenExpiredException;
+import com.rf.fileCrack.filter.JwtIgnore;
+import com.rf.fileCrack.utils.JWTUtil;
+import com.rf.fileCrack.utils.LocalAssert;
+import com.rf.fileCrack.utils.WebContextUtil;
+import io.swagger.models.HttpMethod;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+
+/**
+ * @Description:使用AuthenticationInterceptor拦截器对接口参数进行验证
+ * @Author: mimang
+ * @Date: 2024/9/6
+ */
+@Slf4j
+@Component
+public class AuthenticationInterceptor implements HandlerInterceptor {
+
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+        HashMap<String, Object> resultJson = new HashMap<>();
+        final String url = request.getRequestURI();
+        log.info("url-------------------"+url);
+        // 从http请求头中取出token
+        final String token = request.getHeader(JWTUtil.AUTH_HEADER_KEY);
+        //如果不是映射到方法,直接通过
+        if(!(handler instanceof HandlerMethod)){
+            return true;
+        }
+        //如果是方法探测,直接通过
+        if (HttpMethod.OPTIONS.equals(request.getMethod())) {
+            response.setStatus(HttpServletResponse.SC_OK);
+            return true;
+        }
+        //如果方法有JwtIgnore注解,直接通过
+        HandlerMethod handlerMethod = (HandlerMethod) handler;
+        Method method=handlerMethod.getMethod();
+        if (method.isAnnotationPresent(JwtIgnore.class)) {
+            JwtIgnore jwtIgnore = method.getAnnotation(JwtIgnore.class);
+            if(jwtIgnore.value()){
+                return true;
+            }
+        }
+
+        try {
+            LocalAssert.isStringEmpty(token, "token为空,鉴权失败!");
+            //验证,并获取token内部信息
+            String userToken = JWTUtil.verifyToken(token);
+            //将token放入本地缓存
+            WebContextUtil.setUserToken(userToken);
+            return true;
+        }catch (SignatureVerificationException e) {
+            e.printStackTrace();
+            resultJson.put("code", HttpServletResponse.SC_UNAUTHORIZED);
+            resultJson.put("msg", "无效签名信息");
+        } catch (AlgorithmMismatchException e) {
+            e.printStackTrace();
+            resultJson.put("code", HttpServletResponse.SC_UNAUTHORIZED);
+            resultJson.put("msg", "token算法不一致");
+        }catch (TokenExpiredException e){
+            e.printStackTrace();
+            resultJson.put("code", HttpServletResponse.SC_UNAUTHORIZED);
+            resultJson.put("msg", "token已过期,请重新获取");
+        } catch (Exception e) {
+            e.printStackTrace();
+            resultJson.put("code", HttpServletResponse.SC_UNAUTHORIZED);
+            resultJson.put("msg", "登录状态失效,请重新登录");
+        }
+        String s = JSON.toJSONString(resultJson);
+        response.setContentType("application/json;charset=UTF-8");
+        response.getWriter().println(s);
+        return false;
+    }
+
+    @Override
+    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
+        //方法结束后,移除缓存的token
+        WebContextUtil.removeUserToken();
+    }
+}
+

+ 62 - 0
src/main/java/com/rf/fileCrack/filter/JWTInterceptor.java

@@ -0,0 +1,62 @@
+package com.rf.fileCrack.filter;
+
+import com.alibaba.fastjson.JSON;
+import com.auth0.jwt.exceptions.AlgorithmMismatchException;
+import com.auth0.jwt.exceptions.SignatureVerificationException;
+import com.rf.fileCrack.utils.JWTUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.HashMap;
+
+/**
+ * @author lpf
+ * @description:
+ * @date 2021/12/2821:48
+ */
+@Slf4j
+public class JWTInterceptor implements HandlerInterceptor {
+
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+        HashMap<String, Object> resultJson = new HashMap<>();
+        String uri = request.getRequestURI();
+        try {
+            String token = request.getHeader("Authorization");
+            if(StringUtils.isEmpty(token)) {
+                resultJson.put("code", HttpServletResponse.SC_UNAUTHORIZED);
+                resultJson.put("msg", "无效签名信息");
+            }
+            String[] len = token.split(" ");
+            if (len.length >=1){
+                token = len[1];
+                JWTUtil.verify(token);
+                return true;
+            }else {
+                resultJson.put("code", HttpServletResponse.SC_UNAUTHORIZED);
+                resultJson.put("msg", "无效签名信息");
+            }
+
+        } catch (SignatureVerificationException e) {
+            e.printStackTrace();
+            resultJson.put("code", HttpServletResponse.SC_UNAUTHORIZED);
+            resultJson.put("msg", "无效签名信息");
+        } catch (AlgorithmMismatchException e) {
+            e.printStackTrace();
+            resultJson.put("code", HttpServletResponse.SC_UNAUTHORIZED);
+            resultJson.put("msg", "token算法不一致");
+        } catch (Exception e) {
+            e.printStackTrace();
+            resultJson.put("code", HttpServletResponse.SC_UNAUTHORIZED);
+            resultJson.put("msg", "登录状态失效,请重新登录");
+        }
+        String s = JSON.toJSONString(resultJson);
+        response.setContentType("application/json;charset=UTF-8");
+        response.getWriter().println(s);
+        return false;
+    }
+}

+ 56 - 0
src/main/java/com/rf/fileCrack/filter/JWTInterceptorConfig.java

@@ -0,0 +1,56 @@
+package com.rf.fileCrack.filter;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+/**
+ * @author lpf
+ * @description:
+ * @date 2021/12/2822:06
+ */
+//@Configuration
+public class JWTInterceptorConfig implements WebMvcConfigurer {
+
+    /*@Autowired
+    private UserCheckInterceptor userCheckInterceptor;
+
+    @Autowired
+    private JWTInterceptor jwtInterceptor;*/
+
+
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        String[] swaggerExcludes = new String[]{"/swagger-ui.html", "/swagger-resources/**", "/csrf", "/webjars/**"};
+        String[] webLogin = new String[]{"/user/authCode", "/user/saveUser", "/user/webLogin", "/user/webUpdatePassword", "/user/*/checkUser"};
+        String[] systemApi = new String[]{"/user/addUser","/user/login"};
+        registry.addInterceptor(new AuthenticationInterceptor())
+                .addPathPatterns("/**")
+                .excludePathPatterns("/", "/index**", "/error")
+                .excludePathPatterns(systemApi)
+                //.excludePathPatterns(webLogin)
+                .excludePathPatterns(swaggerExcludes)
+                .excludePathPatterns("/favicon.ico")
+                .excludePathPatterns("/druid/**")
+                .excludePathPatterns("/static/**");
+        registry.addInterceptor(new AuthenticationInterceptor())
+                .addPathPatterns("/**")
+                .excludePathPatterns("/", "/index.html", "/error")
+                .excludePathPatterns(systemApi)
+                //.excludePathPatterns(webLogin)
+                .excludePathPatterns(swaggerExcludes)
+                .excludePathPatterns("/favicon.ico")
+                .excludePathPatterns("/druid/**")
+                .excludePathPatterns("/static/**");
+
+    }
+
+    @Override
+    public void addResourceHandlers(ResourceHandlerRegistry registry) {
+        registry.addResourceHandler("/static/**")
+                .addResourceLocations("classpath:/static/");
+    }
+}

+ 12 - 0
src/main/java/com/rf/fileCrack/filter/JwtIgnore.java

@@ -0,0 +1,12 @@
+package com.rf.fileCrack.filter;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target({ElementType.METHOD, ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+public @interface JwtIgnore {
+    boolean value() default true;
+}

+ 33 - 0
src/main/java/com/rf/fileCrack/filter/UserCheckInterceptor.java

@@ -0,0 +1,33 @@
+package com.rf.fileCrack.filter;
+
+import com.alibaba.fastjson.JSON;
+import com.auth0.jwt.interfaces.DecodedJWT;
+import com.rf.fileCrack.utils.JWTUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.HashMap;
+
+/**
+ * @author lpf
+ * @description:
+ * @date 2021/01/20 16:54
+ */
+public class UserCheckInterceptor implements HandlerInterceptor {
+    @Override
+    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+        HashMap<String, Object> resultJson = new HashMap<>();
+        String uri = request.getRequestURI();
+        String token = request.getHeader("Authorization");
+        token = token.split(" ")[1];
+        JWTUtil.verify(token);
+        DecodedJWT verify = JWTUtil.verify(token);
+        String userId = verify.getClaim("userId").asString();
+        String type = verify.getClaim("type").asString();
+        return true;
+    }
+}

+ 71 - 0
src/main/java/com/rf/fileCrack/security/AesEncryptUtils.java

@@ -0,0 +1,71 @@
+package com.rf.fileCrack.security;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import com.alibaba.fastjson.JSONObject;
+import org.apache.commons.codec.binary.Hex;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author zzf
+ * @description:
+ * @date 2021/8/4 15:27
+ */
+public class AesEncryptUtils {
+
+
+    private static final String KEY = "Sp5biS+gX+#CqAFF";
+
+    private static final String OFFSET = "ud2E8l6wchltwIDA";
+
+    private static final String ALGORITHMSTR = "AES/CBC/PKCS5Padding";
+
+    public static String encrypt(String content, String encryptKey) throws Exception {
+
+        Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
+        SecretKeySpec secretKeySpec =  new SecretKeySpec(encryptKey.getBytes(), "AES");
+        IvParameterSpec iv = new IvParameterSpec(OFFSET.getBytes());
+        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec,iv);
+        byte[] b = cipher.doFinal(content.getBytes("utf-8"));
+        return Hex.encodeHexString(b);
+
+
+    }
+
+    public static String decrypt(String encryptStr, String decryptKey) throws Exception {
+
+        Cipher cipher = Cipher.getInstance(ALGORITHMSTR);
+        SecretKeySpec skeySpec = new SecretKeySpec(KEY.getBytes("ASCII"), "AES");
+        IvParameterSpec iv = new IvParameterSpec(OFFSET.getBytes());
+        cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
+        byte [] encryptBytes =  Hex.decodeHex(encryptStr);
+        byte[] decryptBytes = cipher.doFinal(encryptBytes);
+        return new String(decryptBytes);
+    }
+
+    public static String encrypt(String content) throws Exception {
+        return encrypt(content, KEY);
+    }
+    public static String decrypt(String encryptStr) throws Exception {
+        return decrypt(encryptStr, KEY);
+    }
+
+
+    public static void main(String[] args) throws Exception {
+        Map map=new HashMap<String,String>();
+        map.put("key","value");
+        map.put("中文","汉字");
+        String content = JSONObject.toJSONString(map);
+        System.out.println("加密前:" + content);
+
+        String encrypt = encrypt(content, KEY);
+        System.out.println("加密后:" + encrypt);
+
+        String decrypt = decrypt(encrypt, KEY);
+        System.out.println("解密后:" + decrypt);
+    }
+}

+ 107 - 0
src/main/java/com/rf/fileCrack/security/DESede.java

@@ -0,0 +1,107 @@
+package com.rf.fileCrack.security;
+
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.security.SecureRandom;
+import java.util.Base64;
+
+/**
+ * @author zzf
+ * @description:
+ * @date 2021/7/29 9:16
+ */
+public class DESede {
+    private DESede() {
+
+    }
+
+    private static final String DESEDE_CHARSET_NAME = "UTF-8";
+
+    private static final String DESEDE = "DESede";
+
+    private static final String DES_CBC = "DESede/CBC/PKCS5Padding";
+
+    public static final String DEFAULT_KEY = "240262447423713749922240";
+
+    public static String DEFAULT_DESEDE_IV = "12345678";
+
+    public static byte[] encrypt(byte[] key, byte[] ivByte, byte[] value) {
+        try {
+
+            SecureRandom sr = new SecureRandom();
+            SecretKey securekey = new SecretKeySpec(key, DESEDE);
+            IvParameterSpec iv = new IvParameterSpec(ivByte);
+            Cipher cipher = Cipher.getInstance(DES_CBC);
+            cipher.init(Cipher.ENCRYPT_MODE, securekey, iv, sr);
+
+            return cipher.doFinal(value);
+
+        } catch (Exception e) {
+
+        }
+        return null;
+    }
+
+    public static byte[] decrypt(byte[] key, byte[] ivByte, byte[] value) {
+        try {
+
+            SecureRandom sr = new SecureRandom();
+            SecretKey securekey = new SecretKeySpec(key, DESEDE);
+            IvParameterSpec iv = new IvParameterSpec(ivByte);
+            Cipher cipher = Cipher.getInstance(DES_CBC);
+            cipher.init(Cipher.DECRYPT_MODE, securekey, iv, sr);
+
+            return cipher.doFinal(value);
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return null;
+    }
+
+    public static String base64Encode(String src) throws Exception {
+        Base64.Encoder encoder = Base64.getEncoder();
+        return encoder.encodeToString(src.getBytes(DESEDE_CHARSET_NAME));
+    }
+
+    public static String base64Encode(byte[] buff) throws Exception {
+        Base64.Encoder encoder = Base64.getEncoder();
+        return encoder.encodeToString(buff);
+    }
+
+    public static String base64Decode(String src) throws Exception {
+        Base64.Decoder decoder = Base64.getDecoder();
+        return new String(decoder.decode(src), DESEDE_CHARSET_NAME);
+    }
+
+    public static byte[] base64DecodeToBytes(String src) throws Exception {
+        Base64.Decoder decoder = Base64.getDecoder();
+        return decoder.decode(src);
+    }
+
+
+    public static String encryptString(String str) {
+        try {
+            byte[] encrypt = DESede.encrypt(DEFAULT_KEY.getBytes(), DEFAULT_DESEDE_IV.getBytes(), str.getBytes());
+            String enStr = DESede.base64Encode(encrypt);
+            return enStr;
+        } catch (Exception e) {
+            throw new IllegalArgumentException(e.getMessage());
+        }
+    }
+
+    public static String decryptString(String str) {
+        try {
+            byte[] strBytes = DESede.base64DecodeToBytes(str);
+            return new String(DESede.decrypt(DEFAULT_KEY.getBytes(), DEFAULT_DESEDE_IV.getBytes(), strBytes));
+        } catch (Exception e) {
+            throw new IllegalArgumentException(e.getMessage());
+        }
+    }
+
+    public static void main(String[] args) {
+    }
+}

+ 67 - 0
src/main/java/com/rf/fileCrack/security/SSLConfig.java

@@ -0,0 +1,67 @@
+package com.rf.fileCrack.security;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.connector.Connector;
+import org.apache.tomcat.util.descriptor.web.SecurityCollection;
+import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+
+
+/**
+ * @author zzf
+ * @description:
+ * @date 2021/9/15 14:32
+ */
+@Configuration
+@Profile({"prod", "public"})
+public class SSLConfig {
+
+    @Value("${spring.profiles.active}")
+    private String profile;
+
+    @Bean
+    public TomcatServletWebServerFactory servletContainer() {
+
+        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
+
+            @Override
+            protected void postProcessContext(Context context) {
+
+                SecurityConstraint securityConstraint = new SecurityConstraint();
+                securityConstraint.setUserConstraint("CONFIDENTIAL");
+                SecurityCollection collection = new SecurityCollection();
+                collection.addPattern("/*");
+                securityConstraint.addCollection(collection);
+                context.addConstraint(securityConstraint);
+            }
+        };
+        tomcat.addAdditionalTomcatConnectors(initiateHttpConnector());
+        return tomcat;
+    }
+
+
+    private Connector initiateHttpConnector() {
+        Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
+        connector.setScheme("http");
+        connector.setSecure(false);
+        if ("prod".equals(profile)) {
+            connector.setPort(8082);
+            connector.setRedirectPort(8848);
+        } else if ("public".equals(profile)) {
+            connector.setPort(8081);
+            connector.setRedirectPort(8443);
+        } else {
+            //TODO 待定
+            connector.setPort(9528);
+            connector.setRedirectPort(8849);
+        }
+
+
+        return connector;
+    }
+
+}

+ 18 - 0
src/main/java/com/rf/fileCrack/security/SafetyProcess.java

@@ -0,0 +1,18 @@
+package com.rf.fileCrack.security;
+
+import java.lang.annotation.*;
+
+/**
+ * @author zzf
+ * @description:
+ * @date 2021/7/29 11:44
+ */
+@Target({ElementType.METHOD,ElementType.TYPE})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface SafetyProcess {
+    boolean decode() default false;
+
+    boolean encode() default true;
+}

+ 40 - 0
src/main/java/com/rf/fileCrack/socket/MyClient.java

@@ -0,0 +1,40 @@
+package com.rf.fileCrack.socket;
+
+import org.java_websocket.client.WebSocketClient;
+import org.java_websocket.drafts.Draft_6455;
+import org.java_websocket.handshake.ServerHandshake;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.URI;
+
+public class MyClient extends WebSocketClient {
+
+    private final static Logger logger = LoggerFactory.getLogger(MyClient.class);
+    public MyClient(String serverUri) {
+        super(URI.create(serverUri),new Draft_6455(),null,0);
+    }
+
+    @Override
+    public void onOpen(ServerHandshake handshakedata) {
+        logger.info("MyClient","-------------onOpen");
+    }
+
+    @Override
+    public void onMessage(String message) {
+        logger.info("MyClient","------------onMessage");
+        logger.info("MyClient","------------"+message);
+    }
+
+    @Override
+    public void onClose(int code, String reason, boolean remote) {
+        logger.info("MyClient","onClose");
+    }
+
+    @Override
+    public void onError(Exception ex) {
+        logger.info("MyClient","-------------------onError");
+        logger.info("MyClient","-------------------"+ex.getMessage());
+    }
+
+}

+ 24 - 0
src/main/java/com/rf/fileCrack/socket/WebSocketConfig.java

@@ -0,0 +1,24 @@
+package com.rf.fileCrack.socket;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.socket.server.standard.ServerEndpointExporter;
+
+
+/**
+ * @author zsy
+ * @description:
+ * @date 2024/12/09 14:31
+ */
+@Configuration
+public class WebSocketConfig {
+
+    /**
+     * 注入一个ServerEndpointExporter,该Bean会自动注册使用@ServerEndpoint注解申明的websocket endpoint
+     */
+    @Bean
+    public ServerEndpointExporter serverEndpointExporter() {
+        return new ServerEndpointExporter();
+    }
+
+}

+ 213 - 0
src/main/java/com/rf/fileCrack/socket/WebSocketServer.java

@@ -0,0 +1,213 @@
+package com.rf.fileCrack.socket;
+
+import cn.hutool.core.date.DateUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.rf.fileCrack.file.dao.model.FileEntity;
+import com.rf.fileCrack.file.rest.FileController;
+import com.rf.fileCrack.file.service.FileService;
+import com.rf.fileCrack.utils.SendEmail;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import javax.websocket.*;
+import javax.websocket.server.PathParam;
+import javax.websocket.server.ServerEndpoint;
+import java.io.IOException;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * @author zsy
+ * @description:
+ * @date 2024/12/09 14:32
+ */
+@Slf4j
+@ServerEndpoint(value = "/websocket/{userId}")
+@Component
+public class WebSocketServer {
+
+    @Autowired
+    private FileService fileService;
+
+    public static WebSocketServer webSocketServer;
+
+    @PostConstruct
+    public void init(){
+        webSocketServer = this;
+        webSocketServer.fileService = this.fileService;
+    }
+
+    private static  HashMap<String,String>control;
+    private static List<String> fileList;
+    static{
+        control = new HashMap<>();
+    }
+    /** 记录当前在线连接数 */
+    private static AtomicInteger onlineCount = new AtomicInteger(0);
+    /**
+     * 用来存放每个客户端对应的WebSocketServer对象
+     */
+    private static ConcurrentHashMap<String, WebSocketServer> webSocketMap = new ConcurrentHashMap<>();
+    /**
+     *与某个客户端的连接会话需要通过它来给客户端发送数据
+     */
+    private Session session;
+
+    /**
+     * 用来接收userId
+     */
+    private String userId;
+    /**
+     * 连接建立成功调用的方法
+     */
+    @OnOpen
+    public void onOpen(Session session , @PathParam("userId") String userId) throws IOException {
+        this.session = session;
+        this.userId = userId;
+        //判断用户是否已经登录对应的角色
+        if(fileList==null){
+            fileList = new ArrayList<>();
+            fileList.add(userId);
+        }
+        if(webSocketMap.containsKey(userId)){
+            webSocketMap.remove(userId);
+            webSocketMap.put(userId,this);
+        }else{
+            webSocketMap.put(userId,this);
+            addOnlineCount();
+        }
+        log.info("用户连接:{},当前在线人数为:{}",userId,getOnlineCount());
+        try{
+            sendMessage("连接成功");
+        }catch(IOException e ) {
+            log.error("用户:{},网络异常",userId);
+        }
+        System.out.println("onOpen-----");
+        for (Map.Entry entry:control.entrySet()) {
+            System.out.println(entry.getKey()+"----"+entry.getValue());
+        }
+    }
+
+    /**
+     * 连接关闭调用的方法
+     */
+    @OnClose
+    public void onClose(Session session) {
+        if (webSocketMap.containsKey(userId)) {
+            webSocketMap.remove(userId);
+            subOnlineCount();
+            control.remove(userId);
+        }
+        System.out.println("onClose---");
+        if(fileList != null ){
+            fileList.remove(userId);
+        }
+        log.info("有一连接关闭:{},当前在线人数为:{}", userId, webSocketMap.size());
+    }
+
+    /**
+     * 收到客户端消息后调用的方法
+     *
+     * @param message
+     *            客户端发送过来的消息
+     */
+    @OnMessage
+    public void onMessage(String message, Session session) throws IOException {
+        JSONObject respJson = new JSONObject();
+        System.out.println("onMessage----");
+        for (Map.Entry entry:control.entrySet()) {
+            System.out.println(entry.getKey()+"----"+entry.getValue());
+        }
+        log.info("用户消息:" + userId + ",报文:" + message);
+        if (!StringUtils.isEmpty(message)) {
+            JSONObject jsonObject = JSONObject.parseObject(message);
+            String fileId = null;
+            String password = null;
+            if (jsonObject.containsKey("fileId") && StringUtils.isNotBlank(jsonObject.getString("fileId"))) {
+                fileId = jsonObject.getString("fileId");
+                if (jsonObject.containsKey("password") && StringUtils.isNotBlank(jsonObject.getString("password"))) {
+                    password = jsonObject.getString("password");
+                    savePassword(fileId,password);
+                    respJson.put("msg","发送成功");
+                }else {
+                    log.error("请求的文件password错误!");
+                    respJson.put("msg","发送失败,文件password错误!");
+                }
+            }else {
+                log.error("请求的文件ID或密码为空!");
+                respJson.put("msg","发送失败,文件ID或密码为空!");
+            }
+            sendMessage(respJson.toJSONString());
+        }
+    }
+
+    /**
+     * 发生错误时调用
+     *
+     * @param session
+     * @param error
+     */
+    @OnError
+    public void onError(Session session, Throwable error) {
+        log.error("用户错误:" + this.userId + ",原因:" + error.getMessage());
+        error.printStackTrace();
+    }
+
+    /**
+     * 实现服务器主动推送
+     */
+    public void sendMessage(String message) throws IOException {
+        this.session.getBasicRemote().sendText(message);
+    }
+
+    public static void sendInfo(String message) throws IOException {
+        log.info("消息内容:" + message);
+        webSocketMap.get("10001").sendMessage(message);
+    }
+
+    public static synchronized AtomicInteger getOnlineCount() {
+        return onlineCount;
+    }
+
+    public static synchronized void addOnlineCount() {
+        WebSocketServer.onlineCount.getAndIncrement();
+    }
+
+    public static synchronized void subOnlineCount() {
+        WebSocketServer.onlineCount.getAndDecrement();
+    }
+
+    //保存解密后密码并发邮箱通知
+    public static void savePassword(String fileId, String password) {
+        FileEntity fileEntity = webSocketServer.fileService.findById(fileId);
+        //根据邮箱查询用户信息
+        String email = fileEntity.getEmail();
+        if (email != null) {
+            SendEmail sendEmail=new SendEmail();
+            //破解密码
+            sendEmail.setPassword(password);
+            //破解的文件名
+            String[] fileNames = fileEntity.getFilePath().split("-");
+            String fileName = fileNames[fileNames.length-1];
+            sendEmail.setFileName(fileName);
+            //设置要发送的邮箱
+            sendEmail.setReceiveMailAccount(email);
+            try {
+                sendEmail.Send();
+                fileEntity.setFileStatus("4");
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }else {
+            fileEntity.setFileStatus("3");
+        }
+        fileEntity.setPassword(password);
+        fileEntity.setUpdateTime(DateUtil.now());
+        webSocketServer.fileService.save(fileEntity);
+    }
+
+}

+ 50 - 0
src/main/java/com/rf/fileCrack/utils/AgeUtil.java

@@ -0,0 +1,50 @@
+package com.rf.fileCrack.utils;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+
+public class AgeUtil {
+
+    public static  Date parse(String strDate) throws ParseException {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+        return sdf.parse(strDate);
+    }
+    public static  double getAge(String Birthday) throws Exception {
+        Date birthDay = parse(Birthday);
+        Calendar cal = Calendar.getInstance();
+        if (cal.before(birthDay)) {
+            throw new IllegalArgumentException(
+                    "The birthDay is before Now.It's unbelievable!");
+        }
+        int yearNow = cal.get(Calendar.YEAR);
+        int monthNow = cal.get(Calendar.MONTH);
+        int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH);
+        cal.setTime(birthDay);
+        int yearBirth = cal.get(Calendar.YEAR);
+        int monthBirth = cal.get(Calendar.MONTH);
+        int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);
+        double age = yearNow - yearBirth;
+        if (monthNow < monthBirth) {
+            age -= 0.5;
+        }else if (monthNow > monthBirth){
+            age += 0.5;
+        }
+        return age;
+    }
+
+    public static void main(String args[]) {
+        try {
+            double  age = getAge("2001-07-21");
+            System.out.println("age=="+age);
+        } catch (ParseException e) {
+            e.printStackTrace();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+
+    }
+}
+

+ 324 - 0
src/main/java/com/rf/fileCrack/utils/AssertUtils.java

@@ -0,0 +1,324 @@
+package com.rf.fileCrack.utils;
+
+import java.util.*;
+
+/**
+ * @Author:zzf
+ * @Date:2022/6/15:10:58
+ * @Description:断言,取代代码中错综复杂的if-else条件控制语句
+ */
+
+public class AssertUtils {
+    /**
+     * 功能描述:
+     * 〈判断数组是否为空〉
+     */
+    public static <T> boolean isEmpty(T[] obj) {
+        return null == obj || 0 == obj.length;
+    }
+
+    /**
+     * 功能描述:
+     * 〈判断数组是否不为空〉
+     */
+    public static <T> boolean isNotEmpty(T[] obj) {
+        return !isEmpty(obj);
+    }
+
+    /**
+     * 功能描述:
+     * 〈判断对象是否为空〉
+     */
+    public static boolean isEmpty(Object obj) {
+        return null == obj;
+    }
+
+    /**
+     * 功能描述:
+     * 〈判断对象是否不为空〉
+     */
+    public static boolean isNotEmpty(Object obj) {
+        return !isEmpty(obj);
+    }
+
+    /**
+     * 功能描述:
+     * 〈字符串是否为空〉
+     */
+    public static boolean isEmpty(String str) {
+        return null == str || "".equals(str);
+    }
+
+    /**
+     * 功能描述:
+     * 〈字符串是否不为空〉
+     */
+    public static boolean isNotEmpty(String str) {
+        return !isEmpty(str);
+    }
+
+    /**
+     * 功能描述:
+     * 〈判断集合是否为空〉
+     */
+    public static boolean isEmpty(Collection obj) {
+        return null == obj || obj.isEmpty();
+    }
+
+    /**
+     * 功能描述:
+     * 〈判断集合是否不为空〉
+     */
+    public static boolean isNotEmpty(Collection obj) {
+        return !isEmpty(obj);
+    }
+
+    /**
+     * 功能描述:
+     * 〈判断map集合是否为空〉
+     */
+    public static boolean isEmpty(Map obj) {
+        return null == obj || obj.isEmpty();
+    }
+
+    /**
+     * 功能描述:
+     * 〈判断map集合是否不为空〉
+     */
+    public static boolean isNotEmpty(Map obj) {
+        return !isEmpty(obj);
+    }
+
+    /**
+     * 功能描述:
+     * 〈char数值是否是数字〉
+     */
+    public static boolean charIsNumb(int charValue) {
+        return charValue >= 48 && charValue <= 57 || charValue >= 96 && charValue <= 105;
+    }
+
+    /**
+     * 功能描述:
+     * 〈判断字符串是否是纯数字浮点类型〉
+     */
+    public static boolean isFloat(String s) {
+        if(!(s.indexOf(".") > -1)){
+            return false;
+        }
+        char[] chars = s.toCharArray();
+        boolean flag = true;
+        for (char aChar : chars) {
+            if(aChar != 46){
+                if(!(aChar >= 48 && aChar <= 57 || aChar >= 96 && aChar <= 105)){
+                    flag = false;
+                    break;
+                }
+            }
+        }
+        return flag;
+    }
+
+    /**
+     * 功能描述:
+     * 〈非纯数字浮点类型〉
+     */
+    public static boolean isNotFloat(String s) {
+        return !isFloat(s);
+    }
+    /**
+     * 功能描述:
+     * 〈字符串是否是数字〉
+     */
+    public static boolean isNumb(String str) {
+        if (isEmpty((Object)str)) {
+            return false;
+        } else {
+            char[] chr = str.toCharArray();
+
+            for(int i = 0; i < chr.length; ++i) {
+                if (chr[i] < '0' || chr[i] > '9') {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+
+    /**
+     * 功能描述:
+     * 〈判断字符串是否不是数字〉
+     */
+    public static boolean isNotNumb(String str) {
+        return !isNumb(str);
+    }
+
+    /**
+     * 功能描述:
+     * 〈判断字符串是否有长度,并自定义异常信息〉
+     */
+    public static void hasLength(String str, String msg) {
+        if (str == null || str.length() < 1) {
+            throw new RuntimeException(msg);
+        }
+    }
+
+    /**
+     * 功能描述:
+     * 〈自定义参数校验异常〉
+     */
+    public static void paramCheck(String msg,Object...obj) {
+        for (Object o : obj) {
+            // 参数异常
+            if(isEmpty(o)){
+                throw new RuntimeException(msg);
+            }
+        }
+    }
+
+    /**
+     * 功能描述:
+     * 〈可变参数,判断是否所有对象都为空〉
+     */
+    public static boolean isAllEmpty(Object... obj) {
+        Object[] var1 = obj;
+        int var2 = obj.length;
+
+        for(int var3 = 0; var3 < var2; ++var3) {
+            Object o = var1[var3];
+            if (!isEmpty(o)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * 功能描述:
+     * 〈可变参数-判断只要有任意一个对象为空,则为true〉
+     */
+    public static boolean isAnyEmpty(Object... obj) {
+        Object[] var1 = obj;
+        int var2 = obj.length;
+
+        for(int var3 = 0; var3 < var2; ++var3) {
+            Object o = var1[var3];
+            if (isEmpty(o)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 功能描述:
+     * 〈可变参数 -判断是否所有参数都不为空〉
+     */
+    public static boolean isAllNotEmpty(Object... obj) {
+        Object[] var1 = obj;
+        int var2 = obj.length;
+
+        for(int var3 = 0; var3 < var2; ++var3) {
+            Object o = var1[var3];
+            if (isEmpty(o)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * 功能描述:
+     * 〈判断是否两个对象相等〉
+     */
+    public static boolean isEqual(Object o1, Object o2) {
+        if (o1 == null) {
+            return o2 == null;
+        } else if (o2 == null) {
+            return false;
+        } else if (o1.getClass().isArray()) {
+            for(int i = 0; i < ((Object[])((Object[])o1)).length; ++i) {
+                if (!isEqual(((Object[])((Object[])o1))[i], ((Object[])((Object[])o2))[i])) {
+                    return false;
+                }
+            }
+            return true;
+        } else if (Collection.class.isAssignableFrom(o1.getClass())) {
+            Iterator i1 = ((Collection)o1).iterator();
+            Iterator i2 = ((Collection)o2).iterator();
+            if (((Collection)o1).size() != ((Collection)o2).size()) {
+                return false;
+            } else {
+                for(int i = 0; i < ((Collection)o1).size(); ++i) {
+                    if (!isEqual(i1.next(), i2.next())) {
+                        return false;
+                    }
+                }
+                return true;
+            }
+        } else if (!Map.class.isAssignableFrom(o1.getClass())) {
+            return o1.equals(o2);
+        } else {
+            Map<Object, Object> m1 = (Map)o1;
+            Map<Object, Object> m2 = (Map)o2;
+            if (m1.size() != m2.size()) {
+                return false;
+            } else if (!isEqual(m1.keySet(), m2.keySet())) {
+                return false;
+            } else {
+                Iterator var4 = m1.entrySet().iterator();
+
+                Map.Entry o;
+                do {
+                    if (!var4.hasNext()) {
+                        return true;
+                    }
+
+                    o = (Map.Entry)var4.next();
+                } while(m2.containsKey(o.getKey()) && isEqual(o.getValue(), m2.get(o.getKey())));
+
+                return false;
+            }
+        }
+    }
+
+    /**
+     * 功能描述:
+     * 〈判断两个对象是否不相等〉
+     */
+    public static boolean isNotEqual(Object o1, Object o2) {
+        return !isEqual(o1,o2);
+    }
+
+    /**
+     * 功能描述:
+     * 〈比较两个集合是否相等〉
+     */
+    public static boolean compare(List<Comparable> l1, List<Comparable> l2) {
+        if (l1 != null && !l1.isEmpty()) {
+            if (l2 != null && !l2.isEmpty()) {
+                Collections.sort(l1);
+                Collections.sort(l2);
+                if (l1.size() != l2.size()) {
+                    return false;
+                } else {
+                    for(int i = 0; i < l1.size(); ++i) {
+                        if (((Comparable)l1.get(i)).compareTo(l2.get(i)) != 0) {
+                            return false;
+                        }
+                    }
+
+                    return true;
+                }
+            } else {
+                return false;
+            }
+        } else {
+            return l2 == null || l2.isEmpty();
+        }
+    }
+
+
+
+}
+
+

+ 41 - 0
src/main/java/com/rf/fileCrack/utils/CPUSerial.java

@@ -0,0 +1,41 @@
+package com.rf.fileCrack.utils;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileWriter;
+import java.io.InputStreamReader;
+
+public class CPUSerial {
+
+    public static String getCPUSerial() {
+        String result = "";
+        try {
+            File file = File.createTempFile("tmp", ".vbs");
+            file.deleteOnExit();
+            FileWriter fw = new java.io.FileWriter(file);
+            StringBuilder sb = new StringBuilder("On Error Resume Next \r\n\r\n");
+            sb.append("strComputer = \".\"  \r\n");
+            sb.append("Set objWMIService = GetObject(\"winmgmts:\" _ \r\n");
+            sb.append("    & \"{impersonationLevel=impersonate}!\\\\\" & strComputer & \"\\root\\cimv2\") \r\n");
+            sb.append("Set colItems = objWMIService.ExecQuery(\"Select * from Win32_Processor\")  \r\n ");
+            sb.append("For Each objItem in colItems\r\n " + "    Wscript.Echo objItem.ProcessorId  \r\n ");
+            sb.append("    exit for  ' do the first cpu only! \r\n");
+            sb.append("Next");
+
+            fw.write(sb.toString());
+            fw.close();
+            Process p = Runtime.getRuntime().exec("cscript //NoLogo //T:10 " + file.getPath());
+            BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
+            String line;
+            while ((line = input.readLine()) != null) {
+                result += line;
+            }
+            input.close();
+            file.delete();
+        } catch (Exception e) {
+            e.fillInStackTrace();
+        }
+        return result;
+    }
+
+}

+ 35 - 0
src/main/java/com/rf/fileCrack/utils/Constant.java

@@ -0,0 +1,35 @@
+package com.rf.fileCrack.utils;
+
+/**
+ * @author zzf
+ * @description:静态类
+ * @date 2021/1/19 16:45
+ */
+public class Constant {
+
+
+    public static final String SYSTEM_VERSION ="1.0";
+
+
+
+    public static final String DEFAULT_VALUE_ZERO ="0";
+
+    public static String MAGIC_NUM_0 = "0";
+    public static String MAGIC_NUM_1 = "1";
+    public static String MAGIC_NUM_2 = "2";
+
+    public static final String DATE_TRANS_FLAG_START = "start";
+    public static final String DATE_TRANS_FLAG_END = "end";
+
+
+    public static final String DEFAULT_PASSWORD = "123456";
+
+
+
+
+
+
+
+
+
+}

+ 133 - 0
src/main/java/com/rf/fileCrack/utils/Data.java

@@ -0,0 +1,133 @@
+package com.rf.fileCrack.utils;
+
+import lombok.extern.slf4j.Slf4j;
+
+import java.sql.*;
+
+@Slf4j
+public class Data {
+	
+
+	public static void main(String[] args) throws InterruptedException, SQLException {
+
+        String className = "com.mysql.jdbc.Driver";
+        String url = "jdbc:mysql://localhost:3306/psychological_112";
+        String userName = "root";
+        String password = "";
+        Connection con = null;
+
+        try{
+            Class.forName(className);
+            con = DriverManager.getConnection(url,userName,password);
+        } catch (ClassNotFoundException | SQLException e) {
+            e.printStackTrace();
+            return;
+        }
+        Thread.sleep(3000);
+        PreparedStatement stat = null;
+        try{
+
+            String alterTable = "alter table t_user_info add column role_type varchar(2) default '1' comment '用户角色 1、普通用户 2、机构管理员 3、机构超级管理员'";
+            stat = con.prepareStatement(alterTable);
+            stat.execute();
+        } catch (SQLException e) {
+            e.printStackTrace();
+            return;
+        }finally {
+            if(stat != null){
+                stat.close();
+            }
+        }
+        PreparedStatement stat1 = null;
+        ResultSet rs = null;
+        try{
+            String institution_user_sql = "select * from t_institution_user ";
+            stat1 = con.prepareStatement(institution_user_sql);
+            rs = stat1.executeQuery();
+            while (rs.next()){
+                try {
+
+                    String insertSql = "INSERT INTO t_user_info (id, gender, password, pet_name, phone, birthday, profession, addition_info, institution_name, institution_no, user_status, g_id, model_phone, role_type) \r\n"
+                            + "VALUES \r\n"
+                            + "(?, ?, ?,?, ?, ?, ?,?, ?, ?, ?,?, ?, ?)\r\n";
+                    PreparedStatement statement = con.prepareStatement(insertSql);
+                    statement.setString(1, rs.getString("id"));
+                    statement.setString(2,  rs.getString("gender"));
+                    statement.setString(3, rs.getString("password"));
+                    statement.setString(4, rs.getString("pet_name"));
+                    statement.setString(5, rs.getString("phone"));
+                    statement.setString(6, rs.getString("birthday"));
+                    statement.setString(7, rs.getString("profession"));
+                    statement.setString(8, rs.getString("addition_info"));
+                    statement.setString(9, rs.getString("institution_name"));
+                    statement.setString(10, rs.getString("institution_no"));
+                    statement.setString(11, rs.getString("user_status"));
+                    statement.setString(12, "");
+                    statement.setString(13, "0");
+                    statement.setString(14, "2");
+
+                    int i = statement.executeUpdate();
+                    statement.close();
+                }catch (Exception e){
+                }
+
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }finally {
+            if(rs != null){
+                rs.close();
+            }
+            if(stat1 != null ){
+                stat1.close();
+            }
+        }
+
+
+        PreparedStatement stat2  = null;
+        ResultSet rs2 = null;
+        try{
+            String sql = "select * from t_institution_info ";
+            stat2 = con.prepareStatement(sql);
+            rs2  = stat2.executeQuery();
+            while (rs2.next()){
+                try {
+                    String insertSql = "INSERT INTO t_user_info (id, gender, password, pet_name, phone, birthday, profession, addition_info, institution_name, institution_no, user_status, g_id, model_phone, role_type) \r\n"
+                            + "VALUES \r\n"
+                            + "(?, ?, ?,?, ?, ?, ?,?, ?, ?, ?,?, ?, ?)\r\n";
+                    PreparedStatement statement = con.prepareStatement(insertSql);
+                    statement.setString(1, rs2.getString("id"));
+                    statement.setString(2,  "0");
+                    statement.setString(3, rs2.getString("password"));
+                    statement.setString(4, rs2.getString("institution_name"));
+                    statement.setString(5, rs2.getString("login_name"));
+                    statement.setString(6, "");
+                    statement.setString(7, "");
+                    statement.setString(8, "");
+                    statement.setString(9, rs2.getString("institution_name"));
+                    statement.setString(10, rs2.getString("institution_no"));
+                    statement.setString(11, "2");
+                    statement.setString(12, "");
+                    statement.setString(13, "0");
+                    statement.setString(14, "3");
+
+                    int i = statement.executeUpdate();
+                }catch (Exception e ){
+                }
+
+            }
+        } catch (SQLException e) {
+            e.printStackTrace();
+        }finally {
+            if(rs2 != null){
+                rs2.close();
+            }
+            if(stat2 != null){
+                stat2.close();
+            }
+        }
+
+        Thread.sleep(1000);
+
+    }
+}

+ 1228 - 0
src/main/java/com/rf/fileCrack/utils/DateUtil.java

@@ -0,0 +1,1228 @@
+package com.rf.fileCrack.utils;
+
+import java.text.DateFormat;
+import java.text.DecimalFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.TimeZone;
+
+public class DateUtil {
+	/**
+	 * 默认的日期格式组合,用来将字符串转化为日期用
+	 * 
+	 */
+	public static final String[] DATE_PARSE_PATTERNS = { "yyyy/MM/dd",
+			"yyyy-MM-dd", "yyyy年MM月dd日" };
+	/**
+	 * 获取当前系统时间格式
+	 * 
+	 */
+	public static final String DEFAULT_DATE = "yyyy-MM-dd HH:mm:ss";
+	/**
+	 * 特殊日期格式
+	 */
+	public static final String DEFAULT_DATE_T = "yyyy-MM-dd:HH:mm";
+	
+	/**
+	 * 特殊日期格式2
+	 */
+	public static final String DEFAULT_DATE_T2 = "yyyy-MM-dd HH:mm";
+	/**
+	 * 默认的时间格式
+	 */
+	public static final String DEFAULT_TIME_PATTERN = "HH:mm:ss";
+
+	/**
+	 * 默认的日期格式
+	 */
+	public static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd";
+	
+	/**
+	 * 获取当前系统时间格式
+	 * 用于生成文件名
+	 */
+	public static final String DEFAULT_FILE_DATE = "yyyyMMddHHmmss";
+	
+
+	/**
+	 * 日期代码,周日
+	 */
+	public static final int SUNDAY = 1;
+
+	/**
+	 * 日期代码,周一
+	 */
+	public static final int MONDAY = 2;
+
+	/**
+	 * 日期代码,周二
+	 */
+	public static final int TUESDAY = 3;
+
+	/**
+	 * 日期代码,周三
+	 */
+	public static final int WEDNESDAY = 4;
+
+	/**
+	 * 日期代码,周四
+	 */
+	public static final int THURSDAY = 5;
+
+	/**
+	 * 日期代码,周五
+	 */
+	public static final int FRIDAY = 6;
+
+	/**
+	 * 日期代码,周六
+	 */
+	public static final int SATURDAY = 7;
+
+	/**
+	 * 日期精度,秒
+	 */
+	public static final int ACCURACY_SECOND = 1;
+
+	/**
+	 * 日期精度,分
+	 */
+	public static final int ACCURACY_MINUTE = 2;
+
+	/**
+	 * 日期精度,小时
+	 */
+	public static final int ACCURACY_HOUR = 3;
+
+	/**
+	 * 日期精度,天
+	 */
+	public static final int ACCURACY_DAY = 4;
+
+	/**
+	 * 日期精度,月
+	 */
+	public static final int ACCURACY_MONTH = 5;
+
+	/**
+	 * 日期精度,年
+	 */
+	public static final int ACCURACY_YEAR = 6;
+
+	/**
+	 * 比较用日期格式,精度为年
+	 */
+	public static final String ACCURACY_PATTERN_YEAR = "yyyy";
+
+	/**
+	 * 比较用日期格式,精度为月
+	 */
+	public static final String ACCURACY_PATTERN_MONTH = "yyyyMM";
+
+	/**
+	 * 比较用日期格式,精度为日
+	 */
+	public static final String ACCURACY_PATTERN_DAY = "yyyyMMdd";
+
+	/**
+	 * 比较用日期格式,精度为时
+	 */
+	public static final String ACCURACY_PATTERN_HOUR = "yyyyMMddHH";
+
+	/**
+	 * 比较用日期格式,精度为分
+	 */
+	public static final String ACCURACY_PATTERN_MINUTE = "yyyyMMddHHmm";
+
+	/**
+	 * 比较用日期格式,精度为秒
+	 */
+	public static final String ACCURACY_PATTERN_SECOND = "yyyyMMddHHmmss";
+
+	/**
+	 * 单一属性格式,时
+	 */
+	public static final String SINGLE_YEAR = "yyyy";
+
+	/**
+	 * 单一属性格式,时
+	 */
+	public static final String SINGLE_MONTH = "M";
+
+	/**
+	 * 单一属性格式,时
+	 */
+	public static final String SINGLE_DAY = "d";
+
+	/**
+	 * 单一属性格式,时
+	 */
+	public static final String SINGLE_HOUR = "H";
+
+	/**
+	 * 单一属性格式,分
+	 */
+	public static final String SINGLE_MINUTE = "m";
+
+	/**
+	 * 单一属性格式,秒
+	 */
+	public static final String SINGLE_SECOND = "s";
+
+	/**
+     * 
+     */
+	public static final long MILLISECONDS_PER_SECOND = 1000;
+
+	/**
+     * 
+     */
+	public static final long MILLISECONDS_PER_MINUTE = 1000 * 60;
+
+	/**
+     * 
+     */
+	public static final long MILLISECONDS_PER_HOUR = 1000 * 60 * 60;
+
+	/**
+     * 
+     */
+	public static final long MILLISECONDS_PER_DAY = 1000 * 60 * 60 * 24;
+
+	/**
+	 * 将给定的日期字符串,按照预定的日期格式,转化为Date型数据
+	 * 
+	 * @param dateStr
+	 *            日期字符字符串
+	 * @return 日期型结果
+	 */
+	public static Date parseDate(String dateStr) {
+		Date date = null;
+		try {
+			date = org.apache.commons.lang.time.DateUtils.parseDate(dateStr,
+					DATE_PARSE_PATTERNS);
+		} catch (ParseException e) {
+			e.printStackTrace();
+		}
+		return date;
+	}
+	
+	/**
+	 * 根据指定格式转化String型日期到Date型
+	 * 
+	 * @param dateStr
+	 *            String型日期
+	 * @param parsePattern
+	 *            指定的格式
+	 * @return Date型日期
+	 */
+	public static Date parseDate(String dateStr, String parsePattern) {
+		Date date = null;
+		try {
+			date = org.apache.commons.lang.time.DateUtils.parseDate(dateStr,
+					new String[] { parsePattern.toString() });
+		} catch (ParseException e) {
+			e.printStackTrace();
+		}
+		return date;
+	}
+
+	/**
+	 * 返回系统当前时间(Date型)
+	 * 
+	 * @return 系统当前时间
+	 */
+	public static Date getCurrentDate() {
+		return new Date();
+	}
+
+	/**
+	 * 日期计算,日加减
+	 * 
+	 * @param date
+	 *            初始日期
+	 * @param amount
+	 *            天数增量(负数为减)
+	 * @return 计算后的日期
+	 */
+	public static Date addDays(Date date, int amount) {
+		return org.apache.commons.lang.time.DateUtils.addDays(date, amount);
+	}
+
+	/**
+	 * 日期计算,周加减
+	 * 
+	 * @param date
+	 *            初始日期
+	 * @param amount
+	 *            周数增量(负数为减)
+	 * @return 计算后的日期
+	 */
+	public static Date addWeeks(Date date, int amount) {
+		return org.apache.commons.lang.time.DateUtils.addWeeks(date, amount);
+	}
+
+	/**
+	 * 日期计算,月加减
+	 * 
+	 * @param date
+	 *            初始日期
+	 * @param amount
+	 *            月数增量(负数为减)
+	 * @return 计算后的日期
+	 */
+	public static Date addMonths(Date date, int amount) {
+		return org.apache.commons.lang.time.DateUtils.addMonths(date, amount);
+	}
+
+	/**
+	 * 日期计算,年加减
+	 * 
+	 * @param date
+	 *            初始日期
+	 * @param amount
+	 *            年数增量(负数为减)
+	 * @return 计算后的日期
+	 */
+	public static Date addYears(Date date, int amount) {
+		return org.apache.commons.lang.time.DateUtils.addYears(date, amount);
+	}
+
+	/**
+	 * 日期计算,小时加减
+	 * 
+	 * @param date
+	 *            初始日期
+	 * @param amount
+	 *            小时增量(负数为减)
+	 * @return 计算后的日期
+	 */
+	public static Date addHours(Date date, int amount) {
+		return org.apache.commons.lang.time.DateUtils.addHours(date, amount);
+	}
+
+	/**
+	 * 日期计算,分钟加减
+	 * 
+	 * @param date
+	 *            初始日期
+	 * @param amount
+	 *            分钟增量(负数为减)
+	 * @return 计算后的日期
+	 */
+	public static Date addMinutes(Date date, int amount) {
+		return org.apache.commons.lang.time.DateUtils.addMinutes(date, amount);
+	}
+
+	/**
+	 * 日期计算,秒加减
+	 * 
+	 * @param date
+	 *            初始日期
+	 * @param amount
+	 *            秒增量(负数为减)
+	 * @return 计算后的日期
+	 */
+	public static Date addSeconds(Date date, int amount) {
+		return org.apache.commons.lang.time.DateUtils.addSeconds(date, amount);
+	}
+
+	/**
+	 * 根据指定格式,返回日期时间字符串
+	 * 
+	 * @param date
+	 *            日期变量
+	 * @param pattern
+	 *            日期格式
+	 * @return 日期时间字符串
+	 */
+	public static String getDateStr(Date date, String pattern) {
+		DateFormat df = new SimpleDateFormat(pattern);
+		return df.format(date);
+	}
+
+	/**
+	 * 输出时间String(默认格式)
+	 * 
+	 * @param date
+	 *            日期
+	 * @return 默认格式化的日期
+	 */
+	public static String getTimeStr(Date date) {
+		return getDateStr(date, DEFAULT_TIME_PATTERN);
+	}
+
+	/**
+	 * 取指定日期所在月的第一天的日期
+	 * 
+	 * @param date
+	 *            指定的日期
+	 * @return 指定日期所在月的第一天
+	 */
+	public static Date getFirstDayOfMonth(Date date) {
+		Calendar cal = getCalendar(date);
+		cal.set(Calendar.DATE, 1);
+		return cal.getTime();
+	}
+
+	/**
+	 * 取指定日期所在月的最后一天的日期
+	 * 
+	 * @param date
+	 *            指定的日期
+	 * @return 指定日期所在月的最后一天
+	 */
+	public static Date getLastDayOfMonth(Date date) {
+		Date nextMonth = addMonths(date, 1);
+		Date firstDayOfNextMonth = getFirstDayOfMonth(nextMonth);
+		return addDays(firstDayOfNextMonth, -1);
+	}
+
+	/**
+	 * 取指定日期所在年的第一天的日期
+	 * 
+	 * @param date
+	 *            指定的日期
+	 * @return 指定日期所在年的第一天
+	 */
+	public static Date getFirstDayOfYear(Date date) {
+		Calendar cal = getCalendar(date);
+		cal.set(Calendar.DATE, 1);
+		cal.set(Calendar.MONTH, 0);
+		return cal.getTime();
+	}
+
+	/**
+	 * 取指定日期所在年的最后一天的日期
+	 * 
+	 * @param date
+	 *            指定的日期
+	 * @return 指定日期所在月的最后一天
+	 */
+	public static Date getLastDayOfYear(Date date) {
+		Date nextMonth = addYears(date, 1);
+		Date firstDayOfNextYear = getFirstDayOfYear(nextMonth);
+		return addDays(firstDayOfNextYear, -1);
+	}
+
+	/**
+	 * 取指定日期所在周的指定天的日期
+	 * 
+	 * @param date
+	 *            指定的日期
+	 * @param day
+	 *            指定的天(星期几)
+	 * @param firstDay
+	 *            一星期的起始天
+	 * @return 指定周星期日的日期
+	 */
+	public static Date getDayInWeek(Date date, int day, int firstDay) {
+		Calendar cal = getCalendar(date);
+		cal.setFirstDayOfWeek(firstDay);
+		cal.set(Calendar.DAY_OF_WEEK, day);
+		return cal.getTime();
+	}
+
+	/**
+	 * 根据Date型的日期,取Calendar型的日期
+	 * 
+	 * @param date
+	 *            Date型的日期
+	 * @return Calendar型的日期
+	 */
+	public static Calendar getCalendar(Date date) {
+		Calendar cal = Calendar.getInstance();
+		cal.setTime(date);
+		return cal;
+	}
+
+	/**
+	 * 日期比较(精确到天),date1晚于date2
+	 * 
+	 * @param date1
+	 *            日期1
+	 * @param date2
+	 *            日期2
+	 * @return date1晚于date2,返回true,否则返回false
+	 */
+	public static boolean later(Date date1, Date date2) {
+		boolean result = false;
+		if (1 == compare(date1, date2, ACCURACY_DAY)) {
+			result = true;
+		}
+		return result;
+	}
+
+	/**
+	 * 日期比较(精确到天),date1早于date2
+	 * 
+	 * @param date1
+	 *            日期1
+	 * @param date2
+	 *            日期2
+	 * @return date1早于date2,返回true,否则返回false
+	 */
+	public static boolean earlier(Date date1, Date date2) {
+		boolean result = false;
+		if (-1 == compare(date1, date2, ACCURACY_DAY)) {
+			result = true;
+		}
+		return result;
+	}
+
+	/**
+	 * 日期比较(精确到天),date1等于date2
+	 * 
+	 * @param date1
+	 *            日期1
+	 * @param date2
+	 *            日期2
+	 * @return date1等于date2,返回true,否则返回false
+	 */
+	public static boolean equal(Date date1, Date date2) {
+		boolean result = false;
+		if (0 == compare(date1, date2, ACCURACY_DAY)) {
+			result = true;
+		}
+		return result;
+	}
+
+	/**
+	 * 根据指定规则比较日期,date1晚于date2
+	 * 
+	 * @param date1
+	 *            日期1
+	 * @param date2
+	 *            日期2
+	 * @param accuracy
+	 *            日期精度
+	 * @return date1晚于date2,返回true,否则返回false
+	 */
+	public static boolean later(Date date1, Date date2, int accuracy) {
+		boolean result = false;
+		if (1 == compare(date1, date2, accuracy)) {
+			result = true;
+		}
+		return result;
+	}
+
+	/**
+	 * 根据指定规则比较日期,date1早于date2
+	 * 
+	 * @param date1
+	 *            日期1
+	 * @param date2
+	 *            日期2
+	 * @param accuracy
+	 *            日期精度
+	 * @return date1早于date2,返回true,否则返回false
+	 */
+	public static boolean earlier(Date date1, Date date2, int accuracy) {
+		boolean result = false;
+		if (-1 == compare(date1, date2, accuracy)) {
+			result = true;
+		}
+		return result;
+	}
+
+	/**
+	 * 根据指定规则比较日期,date1等于date2
+	 * 
+	 * @param date1
+	 *            日期1
+	 * @param date2
+	 *            日期2
+	 * @param accuracy
+	 *            日期精度
+	 * @return date1等于date2,返回true,否则返回false
+	 */
+	public static boolean equal(Date date1, Date date2, int accuracy) {
+		boolean result = false;
+		if (0 == compare(date1, date2, accuracy)) {
+			result = true;
+		}
+		return result;
+	}
+
+	/**
+	 * 根据指定规则,比较日期
+	 * 
+	 * @param date1
+	 *            日期1
+	 * @param date2
+	 *            日期2
+	 * @param accuracy
+	 *            日期精度
+	 * @return int型,date1晚,返回1;date1早,返回-1;相等,返回0
+	 */
+	public static int compare(Date date1, Date date2, int accuracy) {
+		String pattern = DEFAULT_DATE_PATTERN;
+		switch (accuracy) {
+		case ACCURACY_YEAR:
+			pattern = ACCURACY_PATTERN_YEAR;
+			break;
+		case ACCURACY_MONTH:
+			pattern = ACCURACY_PATTERN_MONTH;
+			break;
+		case ACCURACY_DAY:
+			pattern = ACCURACY_PATTERN_DAY;
+			break;
+		case ACCURACY_HOUR:
+			pattern = ACCURACY_PATTERN_HOUR;
+			break;
+		case ACCURACY_MINUTE:
+			pattern = ACCURACY_PATTERN_MINUTE;
+			break;
+		case ACCURACY_SECOND:
+			pattern = ACCURACY_PATTERN_SECOND;
+			break;
+		default:
+			break;
+		}
+		Date formatedDate1 = transDateFormat(date1, pattern);
+		Date formatedDate2 = transDateFormat(date2, pattern);
+		return formatedDate1.compareTo(formatedDate2);
+	}
+	/**
+	 * 根据指定规则,比较日期
+	 * 
+	 * @param date1
+	 *            日期1
+	 * @param date2
+	 *            日期2
+	 * @param accuracy
+	 *            日期精度
+	 * @return int型,date1晚,返回1;date1早,返回-1;相等,返回0
+	 * @throws ParseException 
+	 */
+	public static int compare(String date1, String date2, int accuracy) throws ParseException {
+		String pattern = DEFAULT_DATE_PATTERN;
+		switch (accuracy) {
+		case ACCURACY_YEAR:
+			pattern = ACCURACY_PATTERN_YEAR;
+			break;
+		case ACCURACY_MONTH:
+			pattern = ACCURACY_PATTERN_MONTH;
+			break;
+		case ACCURACY_DAY:
+			pattern = ACCURACY_PATTERN_DAY;
+			break;
+		case ACCURACY_HOUR:
+			pattern = ACCURACY_PATTERN_HOUR;
+			break;
+		case ACCURACY_MINUTE:
+			pattern = ACCURACY_PATTERN_MINUTE;
+			break;
+		case ACCURACY_SECOND:
+			pattern = ACCURACY_PATTERN_SECOND;
+			break;
+		default:
+			break;
+		}
+		SimpleDateFormat sdf = new SimpleDateFormat(DEFAULT_DATE);
+		Date formatedDate1 = transDateFormat(sdf.parse(date1), pattern);
+		Date formatedDate2 = transDateFormat(sdf.parse(date2), pattern);
+		return formatedDate1.compareTo(formatedDate2);
+	}
+	/**
+	 * 根据指定规则,转化日期,如只取年、取年月等
+	 * 
+	 * @param date
+	 *            待转化日期
+	 * @param pattern
+	 *            日期格式
+	 * @return 转化后的日期
+	 */
+	public static Date transDateFormat(Date date, String pattern) {
+		String dateStr = getDateStr(date, pattern);
+		return parseDate(dateStr, pattern);
+	}
+
+	/**
+	 * 返回时定时间的年
+	 * 
+	 * @param date
+	 *            日期
+	 * @return String型的年
+	 */
+	public static String getYear(Date date) {
+		return getDateStr(date, SINGLE_YEAR);
+	}
+
+	/**
+	 * 返回时定时间的月
+	 * 
+	 * @param date
+	 *            日期
+	 * @return String型的月
+	 */
+	public static String getMonth(Date date) {
+		return getDateStr(date, SINGLE_MONTH);
+	}
+
+	/**
+	 * 返回时定时间的日
+	 * 
+	 * @param date
+	 *            日期
+	 * @return String型的日
+	 */
+	public static String getDay(Date date) {
+		return getDateStr(date, SINGLE_DAY);
+	}
+
+	/**
+	 * 返回时定时间的小时
+	 * 
+	 * @param date
+	 *            日期
+	 * @return String型的小时
+	 */
+	public static String getHour(Date date) {
+		return getDateStr(date, SINGLE_HOUR);
+	}
+
+	/**
+	 * 返回时定时间的分
+	 * 
+	 * @param date
+	 *            日期
+	 * @return String型的分
+	 */
+	public static String getMinute(Date date) {
+		return getDateStr(date, SINGLE_MINUTE);
+	}
+
+	/**
+	 * 返回时定时间的秒
+	 * 
+	 * @param date
+	 *            日期
+	 * @return String型的秒
+	 */
+	public static String getSecond(Date date) {
+		return getDateStr(date, SINGLE_SECOND);
+	}
+
+	/**
+	 * 将时间日期变量的年份变为指定年, 如果日期不存在,则向后一天,如20102月
+	 * 
+	 * @param date
+	 *            日期时间变量
+	 * @param amount
+	 *            指定年
+	 * @return 修改后的日期变量
+	 */
+	public static Date setYear(Date date, int amount) {
+		Calendar cal = getCalendar(date);
+		cal.set(Calendar.YEAR, amount);
+		return cal.getTime();
+	}
+
+	/**
+	 * 将时间日期变量的月份变为指定月
+	 * 
+	 * @param date
+	 *            日期时间变量
+	 * @param amount
+	 *            指定月
+	 * @return 修改后的日期变量
+	 */
+	public static Date setMonth(Date date, int amount) {
+		Calendar cal = getCalendar(date);
+		cal.set(Calendar.MONTH, amount - 1);
+		return cal.getTime();
+	}
+
+	/**
+	 * 将时间日期变量的年份变为指定日
+	 * 
+	 * @param date
+	 *            日期时间变量
+	 * @param amount
+	 *            指定日
+	 * @return 修改后的日期变量
+	 */
+	public static Date setDay(Date date, int amount) {
+		Calendar cal = getCalendar(date);
+		cal.set(Calendar.DAY_OF_MONTH, amount);
+		return cal.getTime();
+	}
+
+	/**
+	 * 将时间日期变量的小时变为指定时
+	 * 
+	 * @param date
+	 *            日期时间变量
+	 * @param amount
+	 *            指定时
+	 * @return 修改后的日期变量
+	 */
+	public static Date setHour(Date date, int amount) {
+		Calendar cal = getCalendar(date);
+		cal.set(Calendar.HOUR_OF_DAY, amount);
+		return cal.getTime();
+	}
+
+	/**
+	 * 将时间日期变量的分钟变为指定分
+	 * 
+	 * @param date
+	 *            日期时间变量
+	 * @param amount
+	 *            指定分
+	 * @return 修改后的日期变量
+	 */
+	public static Date setMinute(Date date, int amount) {
+		Calendar cal = getCalendar(date);
+		cal.set(Calendar.MINUTE, amount);
+		return cal.getTime();
+	}
+
+	/**
+	 * 将时间日期变量的秒变为指定秒
+	 * 
+	 * @param date
+	 *            日期时间变量
+	 * @param amount
+	 *            指定秒
+	 * @return 修改后的日期变量
+	 */
+	public static Date setSecond(Date date, int amount) {
+		Calendar cal = getCalendar(date);
+		cal.set(Calendar.SECOND, amount);
+		return cal.getTime();
+	}
+
+	/**
+	 * 根据制定单位,计算两个日期之间的天数差
+	 * 
+	 * @param a
+	 *            时间点1
+	 * @param b
+	 *            时间点2
+	 * @return 时间差
+	 */
+	public static int getDateDistance(Date a, Date b) {
+		return getDateDistance(a, b, ACCURACY_DAY);
+	}
+
+	/**
+	 * 根据制定单位,计算两个日期之间的差
+	 * 
+	 * @param a
+	 *            时间点1
+	 * @param b
+	 *            时间点2
+	 * @param unit
+	 *            时间单位
+	 * @return 时间差
+	 */
+	public static int getDateDistance(Date a, Date b, int unit) {
+		int result = 0;
+		if (null != a && null != b) {
+			String pattern = null;
+			switch (unit) {
+			case ACCURACY_HOUR: // '\003'
+				pattern = "yyyyMMddHH";
+				break;
+			case ACCURACY_MINUTE: // '\002'
+				pattern = "yyyyMMddHHmm";
+				break;
+			case ACCURACY_SECOND: // '\001'
+				pattern = "yyyyMMddHHmmss";
+				break;
+			default:
+				pattern = "yyyyMMdd";
+			}
+			Date startDate = transDateFormat(1 != a.compareTo(b) ? a : b,
+					pattern);
+			Date endDate = transDateFormat(1 != a.compareTo(b) ? b : a, pattern);
+			if (1 <= unit && 4 >= unit) {
+				result = getDistanceByUnit(startDate, endDate, unit);
+				return result;
+			}
+			GregorianCalendar startCalendar = new GregorianCalendar();
+			startCalendar.setTime(startDate);
+			int startYears = startCalendar.get(Calendar.YEAR);
+			int startMonths = startCalendar.get(Calendar.MONTH);
+			int startDays = startCalendar.get(Calendar.DAY_OF_MONTH);
+
+			GregorianCalendar endCalendar = new GregorianCalendar();
+			endCalendar.setTime(endDate);
+			int endYears = endCalendar.get(Calendar.YEAR);
+			int endMonths = endCalendar.get(Calendar.MONTH);
+			int endDays = endCalendar.get(Calendar.DAY_OF_MONTH);
+
+			int yearBetween = endYears - startYears;
+			int monthBetween = endMonths - startMonths;
+			if (endDays < startDays
+					&& endDays != endCalendar.getActualMaximum(Calendar.DATE)) {
+				monthBetween--;
+			}
+			if (ACCURACY_YEAR == unit) {
+				if (monthBetween < 0) {
+					yearBetween--;
+				}
+				result = yearBetween;
+			}
+			if (ACCURACY_MONTH == unit) {
+				result = (yearBetween * 12 + monthBetween);
+			}
+		}
+		return result;
+
+	}
+
+	/**
+	 * 内部方法,计算时间点的差距
+	 * 
+	 * @param startDate
+	 *            起始时间
+	 * @param endDate
+	 *            终止时间
+	 * @param unit
+	 *            时间单位
+	 * @return 时间差
+	 */
+	public static int getDistanceByUnit(Date startDate, Date endDate, int unit) {
+		int result = 0;
+		long millisecondPerUnit = MILLISECONDS_PER_DAY;
+		switch (unit) {
+		case ACCURACY_HOUR:
+			millisecondPerUnit = MILLISECONDS_PER_HOUR;
+			break;
+		case ACCURACY_MINUTE:
+			millisecondPerUnit = MILLISECONDS_PER_MINUTE;
+			break;
+		case ACCURACY_SECOND:
+			millisecondPerUnit = MILLISECONDS_PER_SECOND;
+			break;
+		default:
+			break;
+		}
+		long start = startDate.getTime();
+		long end = endDate.getTime();
+		long distance = end - start;
+		result = Integer.valueOf((distance / millisecondPerUnit) + "");
+		return result;
+	}
+	
+	/**
+	 * 内部方法,计算时间点的差距toLong
+	 * 
+	 * @param startDate
+	 *            起始时间
+	 * @param endDate
+	 *            终止时间
+	 * @param unit
+	 *            时间单位
+	 * @return 时间差
+	 */
+	public static long getDistanceByUnit_toLong(Date startDate, Date endDate, int unit) {
+		long result = 0;
+		long millisecondPerUnit = MILLISECONDS_PER_DAY;
+		switch (unit) {
+		case ACCURACY_HOUR:
+			millisecondPerUnit = MILLISECONDS_PER_HOUR;
+			break;
+		case ACCURACY_MINUTE:
+			millisecondPerUnit = MILLISECONDS_PER_MINUTE;
+			break;
+		case ACCURACY_SECOND:
+			millisecondPerUnit = MILLISECONDS_PER_SECOND;
+			break;
+		default:
+			break;
+		}
+		long start = startDate.getTime();
+		long end = endDate.getTime();
+		long distance = end - start;
+		result = distance / millisecondPerUnit;
+		return result;
+	}
+	
+	 
+
+	/**
+	 * 返回指定日期是当年的第几周
+	 * 
+	 * @param date
+	 *            指定日期
+	 * @return 周数(从1开始)
+	 */
+	public static int getWeekOfYear(Date date) {
+		return getCalendar(date).get(Calendar.WEEK_OF_YEAR);
+	}
+
+	/**
+	 * 获取指定日期是星期几
+	 * 
+	 * @param date
+	 *            指定日期
+	 * @return 星期日--1; 星期一--2; 星期二--3; 星期三--4; 星期四--5; 星期五--6; 星期六--7;
+	 */
+	public static int getWeekOfDate(Date date) {
+		return getCalendar(date).get(Calendar.DAY_OF_WEEK);
+	}
+
+	/**
+	 * 判断指定年份日期的年份是否为闰年
+	 * 
+	 * @param date
+	 *            日期
+	 * @return 闰年ture,非闰年false
+	 */
+	public static boolean isLeapYear(Date date) {
+		int year = getCalendar(date).get(Calendar.YEAR);
+		return isLeapYear(year);
+	}
+
+	/**
+	 * 判断指定年份日期的年份是否为闰年
+	 * 
+	 * @param year
+	 *            年份数字
+	 * @return 闰年ture,非闰年false
+	 */
+	public static boolean isLeapYear(int year) {
+		if ((year % 400) == 0) {
+			return true;
+		} else if ((year % 4) == 0) {
+			if ((year % 100) == 0) {
+				return false;
+			} else {
+				return true;
+			}
+		} else {
+			return false;
+		}
+	}
+
+	/**
+	 * 按照strFormat格式输出当前时间
+	 * 
+	 * @param strFormat
+	 *            格式
+	 * @return 指定格式的当前系统日期
+	 */
+	public static String getCurrentDate(String strFormat) {
+		return getDateStr(getCurrentDate(), strFormat);
+	}
+
+	/**
+	 * 校验日期数据(校验输入值是否为指定的日期格式)
+	 * 
+	 * @param strDate
+	 *            要校验的日期
+	 * @param strFormat
+	 *            日期格式
+	 * @return true/false (符合/不符合)
+	 */
+	public static boolean checkDate(String strDate, String strFormat) {
+		Date date = null;
+		if ((strDate != null) && (strDate.trim().length() != 0)) {
+			DateFormat myDateFmt = new SimpleDateFormat(strFormat);
+			try {
+				date = myDateFmt.parse(strDate);
+
+				if (!strDate.equals(myDateFmt.format(date))) {
+					date = null;
+					return false;
+				}
+			} catch (ParseException e) {
+				date = null;
+				return false;
+			}
+		}
+		return true;
+	}
+	/**
+	 * 
+	 * @Description:获取当期系统日期以特定格式显示
+	 * @param 
+	 * @return 格式为"yyyy-MM-dd HH:mm:ss"的时间
+	 * @throws 
+	 * @author baolf
+	 * @date 2016-7-25
+	 */
+	public static String getNowTime(){
+		Date now = new Date();
+		SimpleDateFormat sd = new SimpleDateFormat(DEFAULT_DATE);
+		String date = sd.format(now);
+		return date;
+	}
+	/**
+	 * 
+	 * @Description:获取当期系统两小时后时间   以特定格式显示
+	 * @param 
+	 * @return 格式为"yyyy-MM-dd HH:mm:ss"的时间
+	 * @throws 
+	 * @author wwq
+	 * @date 2018-08-13
+	 */
+	public static String get2HoursLater(){
+		Date twoHours = new Date(System.currentTimeMillis()+120 * 60 * 1000);
+		SimpleDateFormat sd = new SimpleDateFormat(DEFAULT_DATE);
+		String date = sd.format(twoHours);
+		return date;
+	}
+	/**
+	 * 
+	 * @Description:获取当期系统日期以特定格式显示
+	 * @param 
+	 * @return 格式为"yyyy-MM-dd"的时间
+	 * @throws 
+	 * @author
+	 * @date 2016-7-25
+	 */
+	public static String getNowTime1(){
+		Date now = new Date();
+		SimpleDateFormat sd = new SimpleDateFormat(DEFAULT_DATE_PATTERN);
+		String date = sd.format(now);
+		return date;
+	}
+	
+	/**
+	 * 自定义时间格式
+	 * @param strFormat
+	 * @return
+	 */
+	public static String getNowTime(String strFormat){
+		Date now = new Date();
+		SimpleDateFormat sd = new SimpleDateFormat(strFormat);
+		String date = sd.format(now);
+		return date;
+	}
+	
+    /**
+     * 时间串,没有分割符
+     * 用于自动生成文件名用
+     * @return
+     */
+	public static synchronized String getFileNameNowTime(){
+		Date now = new Date();
+		SimpleDateFormat sd = new SimpleDateFormat(DEFAULT_FILE_DATE);
+		String date = sd.format(now);
+		return date;
+	}
+	
+	/**
+	 * 获得几位随机数(正数)
+	 * @param num
+	 * @return
+	 */
+	public static String getRandom(int num)
+	{
+		StringBuffer format = new StringBuffer("0.0");
+		for(int ii=2;ii<=num;ii++)
+		{
+			format.append("0");
+		}
+		DecimalFormat df = new DecimalFormat(format.toString());
+		return df.format(Math.random()).replace("0.","");
+		
+	}
+	public static String getReleaseBatch(){
+		Date now = new Date();
+		SimpleDateFormat sd = new SimpleDateFormat(DEFAULT_DATE_PATTERN);
+		String date = sd.format(now);
+		date = date.replace("-", "");
+		return date;
+	}
+//	public static void main(String[] args) {
+//	}
+	public static String getBeforeNowTime(){
+		long time = 1*60*1000+10000;//1分钟
+		Date now = new Date(new Date().getTime()-time);
+		SimpleDateFormat sd = new SimpleDateFormat(DEFAULT_DATE);
+		String date = sd.format(now);
+		return date;
+	}
+	/**
+	 * 获取秒数  (1970-01-01 08:00:00)
+	 * @Description :
+	 * @param : 
+	 * @throws : 
+	 * @author :
+	 */
+	public static  int getDateInt(String date)
+	{		
+		return getDistanceByUnit( 
+				   parseDate("1970-01-01 08:00:00", DEFAULT_DATE),
+				   parseDate(date, DEFAULT_DATE),1) ;
+	}
+	/**
+	 * 判断字符串是否不为空 空返回false 非空返回true
+	 *
+	 * @param sourceStr
+	 * @return
+	 */
+	public static boolean isNotEmpty(String sourceStr) {
+
+		if (sourceStr == null) {
+			return false;
+		}
+		if (sourceStr.trim().length() > 0) {
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * 统计两个时间的时间差
+	 * 相差几秒几毫秒
+	 */
+	public static String getDistanceTime(String str1, String str2) {
+		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
+		Date one;
+		Date two;
+		long day = 0;//天数差
+		long hour = 0;//小时数差
+		long min = 0;//分钟数差
+		long second=0;//秒数差
+		long diff=0 ;//毫秒差
+		String result = null;
+		try {
+			final Calendar c = Calendar.getInstance();
+			c.setTimeZone(TimeZone.getTimeZone("GMT+8:00"));
+			one = df.parse(str1);
+			c.setTime(one);
+			two = df.parse(str2);
+			long time1 = one.getTime();
+			long time2 = two.getTime();
+			diff = time2 - time1;
+			day = diff / (24 * 60 * 60 * 1000);
+			hour = (diff / (60 * 60 * 1000) - day * 24);
+			min = ((diff / (60 * 1000)) - day * 24 * 60 - hour * 60);
+			second = diff/1000;
+			//System.out.println("day="+day+" hour="+hour+" min="+min+" ss="+second%60+" SSS="+diff%1000);
+			result=second%60+"秒"+diff%1000+"毫秒";
+		} catch (ParseException e) {
+			e.printStackTrace();
+		}
+		return String.valueOf(diff);
+	}
+
+	/*public static void main(String[] args) {
+		//开始时间
+		SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");
+		String beginTime = df.format(new Date());
+		String endTime = df.format(new Date());
+		System.out.println("时间差:"+getDistanceTime(beginTime,endTime));
+	}*/
+
+	/*
+	 * 将yyyyMMddHHmmss格式的数据装换成yyyy-MM-dd:HH:mm格式的数据
+	 * */
+	public static String formatDate(String dateStr) throws NullPointerException {
+		//
+		StringBuffer dateBuffer = new StringBuffer();
+		return dateBuffer.append(dateStr.substring(0, 4)).append("-").append(dateStr.substring(4, 6)).append("-").append(dateStr.substring(6, 8))
+				.append(" ").append(dateStr.substring(8, 10)).append(":").append(dateStr.substring(10, 12)).append(":").append(dateStr.substring(12, 14)).toString();
+	}
+	
+}

+ 71 - 0
src/main/java/com/rf/fileCrack/utils/EmailUtil.java

@@ -0,0 +1,71 @@
+package com.rf.fileCrack.utils;
+
+import org.apache.commons.net.smtp.SMTPClient;
+
+import org.apache.commons.net.smtp.SMTPReply;
+import org.xbill.DNS.Lookup;
+import org.xbill.DNS.Record;
+import org.xbill.DNS.Type;
+
+import java.io.IOException;
+
+public class EmailUtil {
+
+    /*public static void main(String[] args) {
+        String email = "1219951756@qq.com";
+        long start = System.currentTimeMillis();
+        boolean b = checkEmail(email);
+        long end = System.currentTimeMillis();
+        System.out.println("耗时:" + (end-start));
+        System.out.println("是否有效:" + b);
+    }*/
+
+    public static boolean checkEmail(String email) {
+        if (!email.matches("[\\w\\.\\-]+@([\\w\\-]+\\.)+[\\w\\-]+")) {
+            return false;
+        }
+        String host = "";
+        String hostName = email.split("@")[1];
+        Record[] result = null;
+        SMTPClient client = new SMTPClient();
+        try {
+            // 查找MX记录
+            Lookup lookup = new Lookup(hostName, Type.MX);
+            lookup.run();
+            if (lookup.getResult() != Lookup.SUCCESSFUL) {
+                return false;
+            } else {
+                result = lookup.getAnswers();
+            }
+            // 连接到邮箱服务器
+            for (int i = 0; i < result.length; i++) {
+                host = result[i].getAdditionalName().toString();
+                client.connect(host);
+                if (!SMTPReply.isPositiveCompletion(client.getReplyCode())) {
+                    client.disconnect();
+                    continue;
+                } else {
+                    break;
+                }
+            }
+            //以下2项自己填写快速的,有效的邮箱
+            client.login("163.com");
+            // 发送人
+            client.setSender("nebs_cyh@163.com");
+            // 接收人
+            client.addRecipient(email);
+            if (250 == client.getReplyCode()) {
+                return true;
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                client.disconnect();
+            } catch (IOException e) {
+            }
+        }
+        return false;
+    }
+
+}

+ 19 - 0
src/main/java/com/rf/fileCrack/utils/HttpStatus.java

@@ -0,0 +1,19 @@
+package com.rf.fileCrack.utils;
+
+/**
+ * @author zzf
+ * @description:
+ * @date 2021/1/18 19:37
+ */
+public interface HttpStatus {
+    String SUCCESS = "200";
+    String SUCCESS_PUB = "201";
+
+    String RUNTIME_EXCEPTION = "2001";
+
+    String SERVER_EXCEPTION = "500100";
+
+    String PARAMETER_ISNULL = "500101";
+
+    String USER_NOT_FOUND = "6001";
+}

+ 32 - 0
src/main/java/com/rf/fileCrack/utils/IPUtiles.java

@@ -0,0 +1,32 @@
+package com.rf.fileCrack.utils;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * @author lpf
+ * @description:
+ * @date 2021/12/2517:59
+ */
+public class IPUtiles {
+    public static String getRealIp(HttpServletRequest request) {
+        String ip = request.getHeader("X-Real-IP");
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("X-Forwarded-For");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("Proxy-Client-IP");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("WL-Proxy-Client-IP");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getRemoteAddr();
+        }
+        if (ip != null && ip.contains(",")) {
+            String[] ipArray = ip.split(",");
+            ip = ipArray[0];
+        }
+        return ip;
+    }
+
+}

+ 70 - 0
src/main/java/com/rf/fileCrack/utils/JWTUtil.java

@@ -0,0 +1,70 @@
+package com.rf.fileCrack.utils;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.JWTCreator;
+import com.auth0.jwt.algorithms.Algorithm;
+import com.auth0.jwt.exceptions.JWTVerificationException;
+import com.auth0.jwt.exceptions.TokenExpiredException;
+import com.auth0.jwt.interfaces.DecodedJWT;
+
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author lpf
+ * @description:
+ * @date 2021/12/2820:18
+ */
+public class JWTUtil {
+
+    private static final String SING = "xVWGEYTPF1hjnFt$HDZ0f^iet^^q@hZv";
+
+    public static final String AUTH_HEADER_KEY = "Authorization";
+
+    //token前缀
+    public static final String TOKEN_PREFIX = "Bearer ";
+
+    public static String getToken(Map<String, String> map) {
+
+        Calendar instance = Calendar.getInstance();
+        instance.add(Calendar.DATE, 5);
+        JWTCreator.Builder builder = JWT.create();
+        map.forEach(builder::withClaim);
+        String token = builder.withExpiresAt(instance.getTime())
+                .sign(Algorithm.HMAC256(SING));
+        return token;
+    }
+
+    /*public static String getTokenByUserInfo(UserEntity userEntity){
+        HashMap<String, String> payload = new HashMap<>();
+        payload.put("userId", userEntity.getId());
+        payload.put("phone",userEntity.getUserNo());
+        payload.put("email",userEntity.getEmail());
+        payload.put("type", userEntity.getRoleType());
+        return  getToken(payload);
+    }*/
+
+    /**
+     * 验证token
+     * @param token
+     */
+    public static String verifyToken(String token) throws Exception {
+        try {
+            return JWT.require(Algorithm.HMAC256(SING))
+                    .build()
+                    .verify(token.replace(TOKEN_PREFIX, ""))
+                    .getSubject();
+        } catch (TokenExpiredException e){
+            throw new Exception("token已失效,请重新登录",e);
+        } catch (JWTVerificationException e) {
+            throw new Exception("token验证失败!",e);
+        }
+    }
+
+
+    public static DecodedJWT verify(String token) {
+        return JWT.require(Algorithm.HMAC256(SING)).build().verify(token);
+    }
+
+}

+ 35 - 0
src/main/java/com/rf/fileCrack/utils/LocalAssert.java

@@ -0,0 +1,35 @@
+package com.rf.fileCrack.utils;
+
+import com.alibaba.druid.util.StringUtils;
+
+import java.util.Collection;
+
+/**
+ * @Description:断言工具类
+ * @Author: mimang
+ * @Date: 2024/9/6
+ */
+public abstract  class LocalAssert {
+    public static void isTrue(boolean expression, String message) throws RuntimeException {
+        if (!expression) {
+            throw new RuntimeException(message);
+        }
+    }
+    public static void isStringEmpty(String param, String message) throws RuntimeException{
+        if(StringUtils.isEmpty(param)) {
+            throw new RuntimeException(message);
+        }
+    }
+
+    public static void isObjectEmpty(Object object, String message) throws RuntimeException {
+        if (object == null) {
+            throw new RuntimeException(message);
+        }
+    }
+
+    public static void isCollectionEmpty(Collection coll, String message) throws RuntimeException {
+        if (coll == null || (coll.size() == 0)) {
+            throw new RuntimeException(message);
+        }
+    }
+}

+ 131 - 0
src/main/java/com/rf/fileCrack/utils/OSUtil.java

@@ -0,0 +1,131 @@
+package com.rf.fileCrack.utils;
+
+/**
+ * @author zzf
+ * @description:
+ * @date 2021/3/5 9:34
+ */
+
+public class OSUtil {
+
+
+    private static String OS = System.getProperty("os.name").toLowerCase();
+
+    private static OSUtil _instance = new OSUtil();
+
+
+    private OSUtil(){}
+
+    public static boolean isLinux(){
+        return OS.indexOf("linux")>=0;
+    }
+
+    public static boolean isMacOS(){
+        return OS.indexOf("mac")>=0&&OS.indexOf("os")>0&&OS.indexOf("x")<0;
+    }
+
+    public static boolean isMacOSX(){
+        return OS.indexOf("mac")>=0&&OS.indexOf("os")>0&&OS.indexOf("x")>0;
+    }
+
+    public static boolean isWindows(){
+        return OS.indexOf("windows")>=0;
+    }
+
+    public static boolean isOS2(){
+        return OS.indexOf("os/2")>=0;
+    }
+
+    public static boolean isSolaris(){
+        return OS.indexOf("solaris")>=0;
+    }
+
+    public static boolean isSunOS(){
+        return OS.indexOf("sunos")>=0;
+    }
+
+    public static boolean isMPEiX(){
+        return OS.indexOf("mpe/ix")>=0;
+    }
+
+    public static boolean isHPUX(){
+        return OS.indexOf("hp-ux")>=0;
+    }
+
+    public static boolean isAix(){
+        return OS.indexOf("aix")>=0;
+    }
+
+    public static boolean isOS390(){
+        return OS.indexOf("os/390")>=0;
+    }
+
+    public static boolean isFreeBSD(){
+        return OS.indexOf("freebsd")>=0;
+    }
+
+    public static boolean isIrix(){
+        return OS.indexOf("irix")>=0;
+    }
+
+    public static boolean isDigitalUnix(){
+        return OS.indexOf("digital")>=0&&OS.indexOf("unix")>0;
+    }
+
+    public static boolean isNetWare(){
+        return OS.indexOf("netware")>=0;
+    }
+
+    public static boolean isOSF1(){
+        return OS.indexOf("osf1")>=0;
+    }
+
+    public static boolean isOpenVMS(){
+        return OS.indexOf("openvms")>=0;
+    }
+
+
+    /**
+     * 获取操作系统名字
+     * @return 操作系统名
+     */
+    public static String getOSname(){
+        if(isAix()){
+            return "AIX";
+        }else if (isDigitalUnix()) {
+            return "Digital Unix";
+        }else if (isFreeBSD()) {
+            return "FreeBSD";
+        }else if (isHPUX()) {
+            return "HP-UX";
+        }else if (isIrix()) {
+            return "Irix";
+        }else if (isLinux()) {
+            return "Linux";
+        }else if (isMacOS()) {
+            return "Mac OS";
+        }else if (isMacOSX()) {
+            return "Mac OS X";
+        }else if (isMPEiX()) {
+            return "MPE/iX";
+        }else if (isNetWare()) {
+            return "NetWare";
+        }else if (isOpenVMS()) {
+            return "OpenVMS";
+        }else if (isOS2()) {
+            return "OS/2";
+        }else if (isOS390()) {
+            return "OS/390";
+        }else if (isOSF1()) {
+            return "OSF1";
+        }else if (isSolaris()) {
+            return "Solaris";
+        }else if (isSunOS()) {
+            return "SunOS";
+        }else if (isWindows()) {
+            return "Windows";
+        }else{
+            return "Others";
+        }
+    }
+}

+ 17 - 0
src/main/java/com/rf/fileCrack/utils/PageRequestUtil.java

@@ -0,0 +1,17 @@
+package com.rf.fileCrack.utils;
+
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Sort;
+
+/**
+ * @Description:分页工具
+ * @Author: zsf
+ * @Date: 2022/7/5
+ */
+public class PageRequestUtil {
+
+    public static PageRequest of(int page, int size) {
+        if (page <=0){page=0;}else {page = page-1;}
+        return PageRequest.of(page, size, Sort.unsorted());
+    }
+}

+ 431 - 0
src/main/java/com/rf/fileCrack/utils/RandomUtil.java

@@ -0,0 +1,431 @@
+package com.rf.fileCrack.utils;
+
+//import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+
+/**
+ * 随机数工具类
+ */
+public class RandomUtil {
+
+    /**
+     * 获取两数之间的随机数
+     * @param min 最小数
+     * @param max 最大数
+     * @return
+     */
+    public static int scopeNum(int min,int max){
+        Random random = new Random();
+        return random.nextInt(max)%(max-min+1) + min;
+    }
+
+    /**
+     * 获取两数之间的随机数,排除指定的数据
+     * @param min 最小值
+     * @param max 最大值
+     * @param arr 要排除的集合数据
+     * @return
+     */
+    public static int chooseNum(int min, int max, List arr){
+        //Log.i("集合",arr.toString());
+        if ( arr.size() == 4){
+            return 5;
+        }
+        Random random = new Random();
+        int num = random.nextInt(max)%(max-min+1) + min;
+        if ( arr.contains(num)){
+            return chooseNum(min,max,arr);
+        }else {
+            return num;
+        }
+    }
+
+    /**
+     * 随机生成26位字母
+     * @param size 生成位数
+     * @param flag 大小写
+     * @return
+     */
+    public static String randomChar(int size,char flag){
+        //最终生成的字符串
+        String str = "";
+        for (int i = 0; i < size; i++) {
+            str = str + (char)(Math.random()*26+flag);
+        }
+        return str;
+    }
+
+
+    /**
+     * 获取到记忆量表字符出厂顺序
+     *
+     * @return
+     */
+    public static Map recallChar(){
+        Map map = new HashMap();
+        Map exerciseList = new HashMap();
+        Map examList = new HashMap();
+
+        Map mapChar0 = createBack0();
+        Map mapChar1 = createBack(1);
+        Map mapChar2 = createBack(2);
+        String[] strings0 = new String[18];
+        String[] strings1 = new String[18];
+        String[] strings2 = new String[18];
+        for ( int i = 0 ; i<mapChar0.size() ;i++){
+            Object a = mapChar0.get(i);
+            strings0[i] = a.toString();
+            Object b = mapChar1.get(i);
+            strings1[i] = b.toString();
+            Object c = mapChar2.get(i);
+            strings2[i] = c.toString();
+        }
+        exerciseList.put("back0",strings0);
+        exerciseList.put("back1",strings1);
+        exerciseList.put("back2",strings2);
+
+        String[][] stringsa = new String[6][18];
+        String[][] stringsb = new String[6][18];
+        String[][] stringsc = new String[6][18];
+        for ( int j = 0 ; j<6 ;j++){
+            Map mapChar01 = createBack0();
+            Map mapChar11 = createBack(1);
+            Map mapChar21 = createBack(2);
+            String[] strings01 = new String[18];
+            String[] strings11 = new String[18];
+            String[] strings21 = new String[18];
+            for ( int i = 0 ; i<mapChar01.size() ;i++){
+                Object a = mapChar01.get(i);
+                strings01[i] = a.toString();
+                Object b = mapChar11.get(i);
+                strings11[i] = b.toString();
+                Object c = mapChar21.get(i);
+                strings21[i] = c.toString();
+            }
+            stringsa[j] = strings01;
+            stringsb[j] = strings11;
+            stringsc[j] = strings21;
+        }
+        examList.put("back0",stringsa);
+        examList.put("back1",stringsb);
+        examList.put("back2",stringsc);
+
+        map.put("exerciseList",exerciseList);
+        map.put("examList",examList);
+        return map;
+    }
+
+
+    /**
+     * 制作0back组块数据
+     * @return
+     */
+    public static Map createBack0(){
+        List list = new ArrayList();
+        List indexList = new ArrayList();
+        Map mapChar = new LinkedHashMap();
+        mapChar = getMapChar(mapChar,list);
+        indexList = getRandomNum(1,17,indexList,9);
+        for ( Object index : indexList){
+            mapChar.put(index,mapChar.get(0));
+        }
+        //Log.i("0-back",mapChar.toString());
+        return mapChar;
+    }
+
+    /**
+     * 1-back
+     * @return
+     */
+    public static Map createBack(int type){
+        Map mapChar = new LinkedHashMap();
+        List list = new ArrayList();
+        mapChar = getMapChar(mapChar,list);
+        //Log.i(type+"-mapOld",mapChar.toString());
+        List indexList = new ArrayList();
+        indexList = getRandomNum(type,17,indexList,9);
+        Collections.sort(indexList);
+        for ( Object index : indexList){
+            mapChar.put(index,mapChar.get((int)index-type));
+        }
+        //Log.i(type+"-Index",indexList.toString());
+        //Log.i(type+"-back",mapChar.toString());
+        return mapChar;
+    }
+
+
+
+    /**
+     * 获取到18位的随机字符
+     * @param map
+     * @param list
+     * @return
+     */
+    public static Map getMapChar(Map map,List list){
+        char strChar = (char)(Math.random()*26+'A');
+        if ( list.isEmpty()){
+            list.add(strChar);
+        }else {
+            if ( !list.contains( strChar)){
+                list.add(strChar);
+            }
+        }
+        if ( list.size() == 18 ){
+            for (int i = 0; i<list.size();i++){
+                map.put(i,list.get(i));
+            }
+            return map;
+        }else {
+            return getMapChar(map,list);
+        }
+    }
+
+    /**
+     * 获取到范围内随机数
+     * @param min
+     * @param max
+     * @param list
+     * @return
+     */
+    public static List getRandomNum(int min,int max,List list,int size){
+        Random random = new Random();
+        int num = random.nextInt(max)%(max-min+1) + min;
+        if ( !list.contains(num)) {
+            list.add(num);
+        }
+        if ( list.size() == size){
+            return list;
+        }else {
+            return getRandomNum(min,max,list,size);
+        }
+    }
+
+    /**
+     * 获取到记忆量表字符出厂顺序2
+     * @return
+     */
+    public static Map recallCharTwo(){
+        Map map = new HashMap();
+        Map exerciseList = new HashMap();
+        Map examList = new HashMap();
+
+        Map back1 = new LinkedHashMap();
+        Map back1Map1 = createBackOne(1);
+        Map back1Map2 = createBackTwo(1,back1Map1);
+        for ( int i = 0 ; i<back1Map1.size() ;i++){
+            back1.put(i,back1Map1.get(i));
+        }
+        for ( int i = 0 ; i<back1Map2.size() ;i++){
+            back1.put(i+9,back1Map2.get(i));
+        }
+        Map back2 = new LinkedHashMap();
+        Map back2Map1 = createBackOne(2);
+        Map back2Map2 = createBackS(2,back2Map1);
+        for ( int i = 0 ; i<back2Map1.size() ;i++){
+            back2.put(i,back2Map1.get(i));
+        }
+        for ( int i = 0 ; i<back2Map2.size() ;i++){
+            back2.put(i+9,back2Map2.get(i));
+        }
+        //System.out.println("mapChar1:"+mapChar1);
+        //System.out.println("mapChar2:"+mapChar2);
+        String[] strings1 = new String[18];
+        String[] strings2 = new String[18];
+        for ( int i = 0 ; i<back1.size() ;i++){
+            Object b = back1.get(i);
+            strings1[i] = b.toString();
+            Object c = back2.get(i);
+            strings2[i] = c.toString();
+        }
+        exerciseList.put("back1",strings1);
+        exerciseList.put("back2",strings2);
+
+        String[][] stringsb = new String[3][18];
+        String[][] stringsc = new String[3][18];
+        for ( int j = 0 ; j<3 ;j++){
+            Map examback1 = new LinkedHashMap();
+            Map examback1Map1 = createBackOne(1);
+            Map examback1Map2 = createBackTwo(1,examback1Map1);
+            for ( int i = 0 ; i<examback1Map1.size() ;i++){
+                examback1.put(i,examback1Map1.get(i));
+            }
+            for ( int i = 0 ; i<examback1Map2.size() ;i++){
+                examback1.put(i+9,examback1Map2.get(i));
+            }
+            Map examback2 = new LinkedHashMap();
+            Map examback2Map1 = createBackOne(2);
+            Map examback2Map2 = createBackS(2,examback2Map1);
+            for ( int i = 0 ; i<examback2Map1.size() ;i++){
+                examback2.put(i,examback2Map1.get(i));
+            }
+            for ( int i = 0 ; i<examback2Map2.size() ;i++){
+                examback2.put(i+9,examback2Map2.get(i));
+            }
+            String[] strings11 = new String[18];
+            String[] strings21 = new String[18];
+            for ( int i = 0 ; i<examback1.size() ;i++){
+                Object b = examback1.get(i);
+                strings11[i] = b.toString();
+                Object c = examback2.get(i);
+                strings21[i] = c.toString();
+            }
+            stringsb[j] = strings11;
+            stringsc[j] = strings21;
+        }
+        examList.put("back1",stringsb);
+        examList.put("back2",stringsc);
+
+        map.put("exerciseList",exerciseList);
+        map.put("examList",examList);
+        return map;
+    }
+
+    /**
+     * 1-back
+     * @return
+     */
+    public static Map createBackOne(int type){
+        Map mapChar = new LinkedHashMap();
+        List list = new ArrayList();
+        mapChar = getMapCharTwo(mapChar,list);
+        List indexList = new ArrayList();
+        indexList = getRandomNumTwo(type,8,indexList,4);
+        Collections.sort(indexList);
+        for ( Object index : indexList){
+            mapChar.put(index,mapChar.get((int)index-type));
+        }
+        return mapChar;
+    }
+
+    /**
+     * 1-back
+     * @return
+     */
+    public static Map createBackTwo(int type,Map map11){
+        Map mapChar = new LinkedHashMap();
+        List list = new ArrayList();
+        list.add(map11.get(8));
+        mapChar = getMapCharTwo(mapChar,list);
+        List indexList = new ArrayList();
+        indexList = getRandomNumTwo(type,8,indexList,4);
+        Collections.sort(indexList);
+        for ( Object index : indexList){
+            mapChar.put(index,mapChar.get((int)index-type));
+        }
+        return mapChar;
+    }
+
+    /**
+     * 1-back
+     * @return
+     */
+    public static Map createBackS(int type,Map map11){
+        Map mapChar = new LinkedHashMap();
+        List list = new ArrayList();
+        list.add(map11.get(8));
+        mapChar = getMapCharTwo(mapChar,list);
+        List indexList = new ArrayList();
+        indexList = getRandomNumTwo(type,8,indexList,5);
+        Collections.sort(indexList);
+        for ( Object index : indexList){
+            mapChar.put(index,mapChar.get((int)index-type));
+        }
+        return mapChar;
+    }
+
+
+
+    /**
+     * 获取到18位的随机字符
+     * @param map
+     * @param list
+     * @return
+     */
+    public static Map getMapCharTwo(Map map,List list){
+        //char strChar = (char)(Math.random()*26+'A');
+        int ran1 = (int) (Math.random()*(10-1)+1);
+        if ( list.isEmpty()){
+            list.add(ran1);
+        }else {
+            if ( !list.contains( ran1)){
+                list.add(ran1);
+            }
+        }
+        if ( list.size() == 9 ){
+            for (int i = 0; i<list.size();i++){
+                map.put(i,list.get(i));
+            }
+            return map;
+        }else {
+            return getMapCharTwo(map,list);
+        }
+    }
+
+    /**
+     * 获取到范围内随机数
+     * @param min
+     * @param max
+     * @param list
+     * @return
+     */
+    public static List getRandomNumTwo(int min,int max,List list,int size){
+        Random random = new Random();
+        int num = random.nextInt(max)%(max-min+1) + min;
+        if ( !list.contains(num)) {
+            list.add(num);
+        }
+        if ( list.size() == size){
+            return list;
+        }else {
+            return getRandomNumTwo(min,max,list,size);
+        }
+    }
+
+
+    /*public static Map recallCharTwo(){
+        Map map = new HashMap();
+        Map exerciseList = new HashMap();
+        Map examList = new HashMap();
+
+        String[] strings1 = new String[20];
+        String[] strings2 = new String[20];
+        for ( int i = 0 ; i<20 ;i++){
+            int ran1 = (int) (Math.random()*(10-1)+1);
+            int ran2 = (int) (Math.random()*(10-1)+1);
+            strings1[i] = String.valueOf(ran1);
+            strings2[i] = String.valueOf(ran2);
+        }
+        exerciseList.put("back1",strings1);
+        exerciseList.put("back2",strings2);
+
+        String[][] stringsb = new String[3][20];
+        String[][] stringsc = new String[3][20];
+        for ( int j = 0 ; j<3 ;j++){
+            String[] strings11 = new String[20];
+            String[] strings21 = new String[20];
+            for ( int i = 0 ; i<20 ;i++){
+                int ran1 = (int) (Math.random()*(10-1)+1);
+                int ran2 = (int) (Math.random()*(10-1)+1);
+                strings11[i] = String.valueOf(ran1);
+                strings21[i] = String.valueOf(ran2);
+            }
+            stringsb[j] = strings11;
+            stringsc[j] = strings21;
+        }
+        examList.put("back1",stringsb);
+        examList.put("back2",stringsc);
+
+        map.put("exerciseList",exerciseList);
+        map.put("examList",examList);
+        return map;
+    }*/
+
+
+}

+ 62 - 0
src/main/java/com/rf/fileCrack/utils/Result.java

@@ -0,0 +1,62 @@
+package com.rf.fileCrack.utils;
+
+/**
+ * @author zzf
+ * @description:
+ * @date 2021/1/18 19:27
+ */
+
+public class Result<T> {
+    /**
+     * 状态码
+     */
+    private String code;
+
+    /**
+     * 信息
+     */
+    private String msg;
+
+    /**
+     * 返回数据
+     */
+    private T data;
+
+    public Result(String code, String msg, T data) {
+        this.code = code;
+        this.msg = msg;
+        this.data = data;
+    }
+
+    public Result() {
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+
+    public T getData() {
+        return data;
+    }
+
+    public void setData(T data) {
+        this.data = data;
+    }
+
+    public Result(String code, String msg) {
+        this.code = code;
+        this.msg = msg;
+    }
+}

+ 112 - 0
src/main/java/com/rf/fileCrack/utils/SendEmail.java

@@ -0,0 +1,112 @@
+package com.rf.fileCrack.utils;
+
+import javax.mail.Session;
+import javax.mail.Transport;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeMessage;
+import java.util.Date;
+import java.util.Properties;
+
+public class SendEmail {
+
+    //发件人的邮箱和授权码
+    private final String myEmailAccount = "1219951757@qq.com";//发件人的邮箱
+    private final String myEmailPassword = "kjwsfnytpuabhgjc";//发件人的邮箱授权码
+    private String password=null;//破解密码
+    private String receiveMailAccount = null ;//收件人邮箱
+    private String fileName=null;//文件名
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+    public void setReceiveMailAccount(String receiveMailAccount) {
+        this.receiveMailAccount = receiveMailAccount;
+    }
+    public void setFileName(String fileName) {
+        this.fileName = fileName;
+    }
+    // 发件人邮箱的 SMTP 服务器地址, 必须准确, 不同邮件服务器地址不同, 一般(只是一般, 绝非绝对)格式为: smtp.xxx.com
+    // 网易163邮箱的 SMTP 服务器地址为: smtp.163.com    腾讯: smtp.qq.com
+    private  String myEmailSMTPServer = "smtp.qq.com";
+
+    public  void Send() throws Exception {
+        // 1. 创建参数配置, 用于连接邮件服务器的参数配置
+        Properties props = new Properties();                    // 参数配置
+        props.setProperty("mail.transport.protocol", "smtp");   // 使用的协议(JavaMail规范要求)
+        props.setProperty("mail.smtp.host", myEmailSMTPServer);   // 发件人的邮箱的 SMTP 服务器地址
+        props.setProperty("mail.smtp.auth", "true");            // 需要请求认证
+        // PS: 某些邮箱服务器要求 SMTP 连接需要使用 SSL 安全认证 (为了提高安全性, 邮箱支持SSL连接, 也可以自己开启),
+        //     如果无法连接邮件服务器, 仔细查看控制台打印的 log, 如果有有类似 “连接失败, 要求 SSL 安全连接” 等错误,
+        //     打开下面 /* ... */ 之间的注释代码, 开启 SSL 安全连接。
+
+        // SMTP 服务器的端口 (非 SSL 连接的端口一般默认为 25, 可以不添加, 如果开启了 SSL 连接,
+        //                  需要改为对应邮箱的 SMTP 服务器的端口, 具体可查看对应邮箱服务的帮助,
+        //                  QQ邮箱的SMTP(SLL)端口为465或587, 其他邮箱自行去查看)
+        final String smtpPort = "465";
+        props.setProperty("mail.smtp.port", smtpPort);
+        props.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
+        props.setProperty("mail.smtp.socketFactory.fallback", "false");
+        props.setProperty("mail.smtp.socketFactory.port", smtpPort);
+
+
+        // 2. 根据配置创建会话对象, 用于和邮件服务器交互
+        Session session = Session.getDefaultInstance(props);
+        session.setDebug(true);                                 // 设置为debug模式, 可以查看详细的发送 log
+
+        // 3. 创建一封邮件
+        MimeMessage message = createMessage(session, myEmailAccount, receiveMailAccount,fileName,password);
+
+        // 4. 根据 Session 获取邮件传输对象
+        Transport transport = session.getTransport();
+
+        // 5. 使用 邮箱账号 和 密码 连接邮件服务器, 这里认证的邮箱必须与 message 中的发件人邮箱一致, 否则报错
+        //
+        //    PS_01: 成败的判断关键在此一句, 如果连接服务器失败, 都会在控制台输出相应失败原因的 log,
+        //           仔细查看失败原因, 有些邮箱服务器会返回错误码或查看错误类型的链接, 根据给出的错误
+        //           类型到对应邮件服务器的帮助网站上查看具体失败原因。
+        //
+        //    PS_02: 连接失败的原因通常为以下几点, 仔细检查代码:
+        //           (1) 邮箱没有开启 SMTP 服务;
+        //           (2) 邮箱密码错误, 例如某些邮箱开启了独立密码;
+        //           (3) 邮箱服务器要求必须要使用 SSL 安全连接;
+        //           (4) 请求过于频繁或其他原因, 被邮件服务器拒绝服务;
+        //           (5) 如果以上几点都确定无误, 到邮件服务器网站查找帮助。
+        //
+        //    PS_03: 仔细看log, 认真看log, 看懂log, 错误原因都在log已说明。
+        transport.connect(myEmailAccount, myEmailPassword);
+
+        // 6. 发送邮件, 发到所有的收件地址, message.getAllRecipients() 获取到的是在创建邮件对象时添加的所有收件人, 抄送人, 密送人
+        transport.sendMessage(message, message.getAllRecipients());
+
+        // 7. 关闭连接
+        transport.close();
+    }
+
+    /**
+     * 创建一封只包含文本的简单邮件
+     *
+     * @param session 和服务器交互的会话
+     * @param sendMail 发件人邮箱
+     * @param receiveMail 收件人邮箱
+     * @return
+     * @throws Exception
+     */
+    public  MimeMessage createMessage(Session session, String sendMail, String receiveMail,String fileName,String password) throws Exception {
+        // 1. 创建一封邮件
+        MimeMessage message = new MimeMessage(session);
+        // 2. From: 发件人(昵称有广告嫌疑,避免被邮件服务器误认为是滥发广告以至返回失败,请修改昵称)
+        message.setFrom(new InternetAddress(sendMail, "AI文件破解平台", "UTF-8"));
+        // 3. To: 收件人(可以增加多个收件人、抄送、密送)
+        message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(receiveMail, "xx用户", "UTF-8"));
+        // 4. Subject: 邮件主题(标题有广告嫌疑,避免被邮件服务器误认为是滥发广告以至返回失败,请修改标题)
+        message.setSubject("AI文件破解平台通知", "UTF-8");
+        // 5. Content: 邮件正文(可以使用html标签)(内容有广告嫌疑,避免被邮件服务器误认为是滥发广告以至返回失败,请修改发送内容)
+        message.setContent("【AI文件破解平台】您上传的文件:"+fileName+";密码为:"+password, "text/html;charset=UTF-8");
+        // 6. 设置发件时间
+        message.setSentDate(new Date());
+        // 7. 保存设置
+        message.saveChanges();
+
+        return message;
+    }
+}

+ 44 - 0
src/main/java/com/rf/fileCrack/utils/WebContextUtil.java

@@ -0,0 +1,44 @@
+package com.rf.fileCrack.utils;
+
+import com.alibaba.fastjson.JSONObject;
+
+/**
+ * @Description:线程缓存工具类
+ * @Author: mimang
+ * @Date: 2024/9/6
+ */
+public class WebContextUtil {
+    //本地线程缓存token
+    private static ThreadLocal<String> local = new ThreadLocal<>();
+
+    /**
+     * 设置token信息
+     * @param content
+     */
+    public static void setUserToken(String content){
+        removeUserToken();
+        local.set(content);
+    }
+
+    /**
+     * 获取token信息
+     * @return
+     */
+    /*public static UserEntity getUserToken(){
+        if(local.get() != null){
+            UserEntity userToken = JSONObject.parseObject(local.get() , UserEntity.class);
+            return userToken;
+        }
+        return null;
+    }*/
+
+    /**
+     * 移除token信息
+     * @return
+     */
+    public static void removeUserToken(){
+        if(local.get() != null){
+            local.remove();
+        }
+    }
+}

+ 80 - 0
src/main/java/com/rf/fileCrack/utils/XMLUtil.java

@@ -0,0 +1,80 @@
+package com.rf.fileCrack.utils;
+
+import com.alibaba.fastjson.JSON;
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.DocumentHelper;
+import org.dom4j.Element;
+
+import java.util.*;
+
+/**
+ * @Description:xml工具
+ * @Author: zsf
+ * @Date: 2022/8/12
+ */
+public class XMLUtil {
+
+    /**
+     * 选择需要返回的格式: 1、返回 List<Map>\2、返回 Map
+     * @param xml
+     * @return
+     */
+    @SuppressWarnings("all")
+    public static Map<String, Object> parseXML(String xml) throws DocumentException {
+        // 1、 List<Map>
+        List<Map<String, Object>> resultList = new ArrayList<>();
+        // 2、 Map
+        Map<String, Object> resultMap = new HashMap<>();
+        Document document = null;
+        document = DocumentHelper.parseText(xml);
+        Element root = document.getRootElement();
+        Iterator<Element> rootIter = root.elementIterator();
+        while (rootIter.hasNext()) {
+            Element ele = rootIter.next();
+            Map<String, Object> parenMap = new HashMap<>();
+            chile(ele, null, parenMap, null, null);
+            // 1、list
+            resultList.add(parenMap);
+            // 2、map
+            resultMap.put(ele.getName(), parenMap);
+        }
+        // toJSON
+        String listJSON = JSON.toJSONString(resultList);
+        String mapJSON = JSON.toJSONString(resultMap);
+        //System.out.println(listJSON);
+        //System.out.println(JSON.toJSONString(mapJSON));
+        return resultMap;
+    }
+
+    public static void chile(Element ele, String keyName, Map<String, Object> parenMap, Map<String, Object> childMap,
+                             List<Map<String, Object>> childData) {
+        Iterator<Element> childIter = ele.elementIterator();
+        while (childIter.hasNext()) {
+            Element attr = childIter.next();
+            Iterator<Element> childIter2 = attr.elementIterator();
+            if (childIter2.hasNext()) {
+                Element attr2 = childIter2.next();
+                Map<String, Object> childMap2 = new HashMap<>();
+                List<Map<String, Object>> childData2 = new ArrayList<>();
+
+                chile(attr, attr.getName(), parenMap, childMap2, childData2);
+            } else if (keyName != null) {
+                childMap.put(attr.getName().trim(), attr.getText().trim());
+            } else {
+                //parenMap.put(attr.getName().trim(), attr.getText().trim());
+                parenMap.put(attr.attribute(0).getValue().trim(), attr.getText().trim());
+            }
+        }
+        if (keyName != null && childMap != null && !childMap.isEmpty()) {
+            if (parenMap != null && parenMap.get(keyName) != null) {
+                List<Map<String, Object>> object = (List<Map<String, Object>>) parenMap.get(keyName);
+                object.add(childMap);
+            } else {
+                childData.add(childMap);
+                parenMap.put(keyName, childData);
+            }
+        }
+    }
+
+}

+ 140 - 0
src/main/java/com/rf/fileCrack/utils/ZipUtils.java

@@ -0,0 +1,140 @@
+package com.rf.fileCrack.utils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class ZipUtils {
+    private static final Logger log = LoggerFactory.getLogger(ZipUtils.class);
+
+    private ZipUtils() {
+    }
+    /**
+     * 创建ZIP文件
+     * @param sourcePath 文件或文件夹路径
+     * @param zipPath 生成的zip文件存在路径(包括文件名)
+     * @param isDrop  是否删除原文件:true删除、false不删除
+     */
+    public static void createZip(String sourcePath, String zipPath,Boolean isDrop) {
+        FileOutputStream fos = null;
+        ZipOutputStream zos = null;
+        try {
+            fos = new FileOutputStream(zipPath);
+            zos = new ZipOutputStream(fos);
+            //zos.setEncoding("utf8");//此处修改字节码方式。
+            //createXmlFile(sourcePath,"293.xml");
+            writeZip(new File(sourcePath), "", zos,isDrop);
+        } catch (FileNotFoundException e) {
+            log.error("创建ZIP文件失败",e);
+        } finally {
+            try {
+                if (zos != null) {
+                    zos.close();
+                }
+            } catch (IOException e) {
+                log.error("创建ZIP文件失败",e);
+            }
+
+        }
+    }
+    /**
+     * 清空文件和文件目录
+     *
+     * @param f
+     */
+    public static void clean(File f) throws Exception {
+        String cs[] = f.list();
+        if (cs == null || cs.length <= 0) {
+            //System.out.println("delFile:[ " + f + " ]");
+            boolean isDelete = f.delete();
+            if (!isDelete) {
+                //System.out.println("delFile:[ " + f.getName() + "文件删除失败!" + " ]");
+                throw new Exception(f.getName() + "文件删除失败!");
+            }
+        } else {
+            for (int i = 0; i < cs.length; i++) {
+                String cn = cs[i];
+                String cp = f.getPath() + File.separator + cn;
+                File f2 = new File(cp);
+                if (f2.exists() && f2.isFile()) {
+                    //System.out.println("delFile:[ " + f2 + " ]");
+                    boolean isDelete = f2.delete();
+                    if (!isDelete) {
+                        //System.out.println("delFile:[ " + f2.getName() + "文件删除失败!" + " ]");
+                        throw new Exception(f2.getName() + "文件删除失败!");
+                    }
+                } else if (f2.exists() && f2.isDirectory()) {
+                    clean(f2);
+                }
+            }
+            //System.out.println("delFile:[ " + f + " ]");
+            boolean isDelete = f.delete();
+            if (!isDelete) {
+                //System.out.println("delFile:[ " + f.getName() + "文件删除失败!" + " ]");
+                throw new Exception(f.getName() + "文件删除失败!");
+            }
+        }
+    }
+    private static void writeZip(File file, String parentPath, ZipOutputStream zos,Boolean isDrop) {
+        if(file.exists()){
+            if(file.isDirectory()){//处理文件夹
+                parentPath+=file.getName()+File.separator;
+                File [] files=file.listFiles();
+                if(files.length != 0)
+                {
+                    for(File f:files){
+                        writeZip(f, parentPath, zos,isDrop);
+                    }
+                }
+                else
+                {       //空目录则创建当前目录
+                    try {
+                        zos.putNextEntry(new ZipEntry(parentPath));
+                    } catch (IOException e) {
+                        // TODO Auto-generated catch block
+                        e.printStackTrace();
+                    }
+                }
+            }else{
+                FileInputStream fis=null;
+                try {
+                    fis=new FileInputStream(file);
+                    ZipEntry ze = new ZipEntry(parentPath + file.getName());
+                    zos.putNextEntry(ze);
+                    byte [] content=new byte[1024];
+                    int len;
+                    while((len=fis.read(content))!=-1){
+                        zos.write(content,0,len);
+                        zos.flush();
+                    }
+
+                } catch (FileNotFoundException e) {
+                    log.error("创建ZIP文件失败",e);
+                } catch (IOException e) {
+                    log.error("创建ZIP文件失败",e);
+                }finally{
+                    try {
+                        if(fis!=null){
+                            fis.close();
+                        }
+                        if(isDrop){
+                            clean(file);
+                        }
+                    }catch(IOException e){
+                        log.error("创建ZIP文件失败",e);
+                    } catch (Exception e) {
+                        e.printStackTrace();
+                    }
+                }
+            }
+        }
+    }
+}

+ 48 - 0
src/main/resources/config/application-prod.yml

@@ -0,0 +1,48 @@
+server:
+  port: 8060
+  address: 0.0.0.0
+spring:
+  datasource:
+    type: com.alibaba.druid.pool.DruidDataSource
+    druid:
+      driver-class-name: com.mysql.cj.jdbc.Driver
+      url: jdbc:mysql://10.11.7.12:3306/post_station?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2B8
+      username: root
+      password: Gqt@qnrcyz105
+      initial-size: 5
+      min-idle: 5
+      max-active: 20
+      max-wait: 30000
+      time-between-eviction-runs-millis: 60000
+      min-evictable-idle-time-millis: 300000
+      validation-query: select '1' from dual
+      test-while-idle: true
+      test-on-borrow: false
+      test-on-return: false
+      pool-prepared-statements: true
+      max-open-prepared-statements: 20
+      max-pool-prepared-statement-per-connection-size: 20
+      filters: stat,wall
+      filter:
+        stat:
+          enabled: true
+          db-type: mysql
+          log-slow-sql: true
+          slow-sql-millis: 2000
+      stat-view-servlet:
+        url-pattern: /druid/*
+        reset-enable: false
+        login-username: testAdmin
+        login-password: asdcjiafh^&912834
+        enabled: true
+        allow:
+      web-stat-filter:
+        url-pattern: /*
+        exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*"
+        enabled: true
+        session-stat-enable: true
+
+
+
+
+

+ 51 - 0
src/main/resources/config/application-test.yml

@@ -0,0 +1,51 @@
+server:
+  port: 8060
+  address: 0.0.0.0
+spring:
+  datasource:
+    type: com.alibaba.druid.pool.DruidDataSource
+    druid:
+      driver-class-name: com.mysql.cj.jdbc.Driver
+      url: jdbc:mysql://49.232.26.44:3306/file_crack?useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true&useSSL=false&serverTimezone=GMT%2B8
+      username: root
+      password: Mysql@.2020
+      initial-size: 5
+      min-idle: 5
+      max-active: 20
+      max-wait: 30000
+      time-between-eviction-runs-millis: 60000
+      min-evictable-idle-time-millis: 300000
+      validation-query: select '1' from dual
+      test-while-idle: true
+      test-on-borrow: false
+      test-on-return: false
+      pool-prepared-statements: true
+      max-open-prepared-statements: 20
+      max-pool-prepared-statement-per-connection-size: 20
+      filters: stat,wall
+      filter:
+        stat:
+          enabled: true
+          db-type: mysql
+          log-slow-sql: true
+          slow-sql-millis: 2000
+      stat-view-servlet:
+        url-pattern: /druid/*
+        reset-enable: false
+        login-username: testAdmin
+        login-password: asdcjiafh^&912834
+        enabled: true
+        allow:
+      web-stat-filter:
+        url-pattern: /*
+        exclusions: "*.js,*.gif,*.jpg,*.bmp,*.png,*.css,*.ico,/druid/*"
+        enabled: true
+        session-stat-enable: true
+#swagger 显示隐藏配置
+swagger:
+  show: true
+
+
+
+
+

+ 26 - 0
src/main/resources/config/application.yml

@@ -0,0 +1,26 @@
+spring:
+  profiles:
+    active: test
+
+  jpa:
+    hibernate:
+      ddl-auto: update
+    database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
+    show-sql: false
+    open-in-view: false
+  servlet:
+    multipart:
+      enabled: true
+      file-size-threshold: 2KB
+      max-request-size: 1000MB
+      max-file-size: 1000MB
+logging:
+  level:
+    org.springframework.security:
+      - debug
+      - info
+    org.springframework.web: error
+    org.hibernate.SQL: debug
+    org.hibernate.engine.QueryParameters: debug
+    org.hibernate.engine.query.HQLQueryPlan: debug
+    org.hibernate.type.descriptor.sql.BasicBinder: trace

+ 144 - 0
src/main/resources/logback.xml

@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+    <property name="LOG_HOME" value="./logs/%d{yyyy-MM-dd}"/>
+    <property name="LOG_NAME" value="AIFileCrack"/>
+    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
+        <layout class="ch.qos.logback.classic.PatternLayout">
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{35}) |  %msg %n</pattern>
+        </layout>
+    </appender>
+    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_HOME}/${LOG_NAME}.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <maxFileSize>100MB</maxFileSize>
+            <maxHistory>30</maxHistory>
+            <totalSizeCap>10GB</totalSizeCap>
+            <cleanHistoryOnStart>true</cleanHistoryOnStart>
+        </rollingPolicy>
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{35} | %msg%n</pattern> 
+        </encoder>
+    </appender>
+    <appender name="POSITION_LOG_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_HOME}/${LOG_NAME}-position-sync.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <maxFileSize>100MB</maxFileSize>
+            <maxHistory>30</maxHistory>
+            <totalSizeCap>10GB</totalSizeCap>
+            <cleanHistoryOnStart>true</cleanHistoryOnStart>
+        </rollingPolicy>
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>INFO</level>
+        </filter>
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{35} | %msg%n</pattern> 
+        </encoder>
+    </appender>
+
+    <appender name="EVENT_LOG_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_HOME}/${LOG_NAME}-event-sync.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <maxFileSize>100MB</maxFileSize>
+            <maxHistory>30</maxHistory>
+            <totalSizeCap>10GB</totalSizeCap>
+            <cleanHistoryOnStart>true</cleanHistoryOnStart>
+        </rollingPolicy>
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>INFO</level>
+        </filter>
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{35} | %msg%n</pattern> 
+        </encoder>
+    </appender>
+
+    <appender name="TRACK_LOG_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_HOME}/${LOG_NAME}-track-sync.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <maxFileSize>100MB</maxFileSize>
+            <maxHistory>30</maxHistory>
+            <totalSizeCap>10GB</totalSizeCap>
+            <cleanHistoryOnStart>true</cleanHistoryOnStart>
+        </rollingPolicy>
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>INFO</level>
+        </filter>
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{35} | %msg%n</pattern> 
+        </encoder>
+    </appender>
+
+    <appender name="FILE_LOG_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_HOME}/${LOG_NAME}-file-sync.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <maxFileSize>100MB</maxFileSize>
+            <maxHistory>30</maxHistory>
+            <totalSizeCap>10GB</totalSizeCap>
+            <cleanHistoryOnStart>true</cleanHistoryOnStart>
+        </rollingPolicy>
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>INFO</level>
+        </filter>
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{35} | %msg%n</pattern> 
+        </encoder>
+    </appender>
+
+    <appender name="RESTART_LOG_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_HOME}/${LOG_NAME}-restart.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <maxFileSize>100MB</maxFileSize>
+            <maxHistory>30</maxHistory>
+            <totalSizeCap>10GB</totalSizeCap>
+            <cleanHistoryOnStart>true</cleanHistoryOnStart>
+        </rollingPolicy>
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>INFO</level>
+        </filter>
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{35} | %msg%n</pattern> 
+        </encoder>
+    </appender>
+
+    <appender name="REDIS_LOG_APPENDER" class="ch.qos.logback.core.rolling.RollingFileAppender">
+        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+            <fileNamePattern>${LOG_HOME}/${LOG_NAME}-redis.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
+            <maxFileSize>100MB</maxFileSize>
+            <maxHistory>30</maxHistory>
+            <totalSizeCap>10GB</totalSizeCap>
+            <cleanHistoryOnStart>true</cleanHistoryOnStart>
+        </rollingPolicy>
+        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+            <level>INFO</level>
+        </filter>
+        <encoder>
+            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{35} | %msg%n</pattern> 
+        </encoder>
+    </appender>
+
+    <root level="info">
+        <appender-ref ref="CONSOLE"/>
+        <appender-ref ref="FILE"/>
+    </root>
+    <logger name="com.patrol.mobile.controller" level="info" additivity="false">
+        <appender-ref ref="CONSOLE"/>
+    </logger>
+
+    <logger name="POSITION_LOG" level="info" additivity="false">
+        <appender-ref ref="POSITION_LOG_APPENDER"/>
+    </logger>
+    <logger name="EVENT_LOG" level="info" additivity="false">
+        <appender-ref ref="EVENT_LOG_APPENDER"/>
+    </logger>
+    <logger name="TRACK_LOG" level="info" additivity="false">
+        <appender-ref ref="TRACK_LOG_APPENDER"/>
+    </logger>
+    <logger name="FILE_LOG" level="info" additivity="false">
+        <appender-ref ref="FILE_LOG_APPENDER"/>
+    </logger>
+    <logger name="RESTART_LOG" level="info" additivity="false">
+        <appender-ref ref="RESTART_LOG_APPENDER"/>
+    </logger>
+    <logger name="REDIS_LOG" level="info" additivity="false">
+        <appender-ref ref="REDIS_LOG_APPENDER"/>
+    </logger>
+</configuration>

+ 28 - 0
src/main/resources/proguard.conf

@@ -0,0 +1,28 @@
+-ignorewarnings
+-keepdirectories
+
+-keep interface com.your_package.** { *; }
+-keep class com.your_package.main{ *; }
+-keep class com.your_package.model.** { *; }
+
+-keepparameternames
+-keepclassmembers @org.springframework.** class * {
+    *;
+}
+
+-keepclassmembers @org.springframework.** interface * {
+    *;
+}
+
+-keepclassmembers enum * {
+    public static **[] values();
+    public static ** valueOf(java.lang.String);
+}
+
+-keep @org.springframework.** class *
+-keepclassmembers @javax.** class * { *; }
+
+-dontwarn org.springframework.**
+-dontwarn javax.**
+-dontwarn org.yaml.snakeyaml.**
+-dontwarn okhttp3.**

BIN
uploadFile/1733888808310-测评结果汇总.xlsx