Browse Source

zzbusiness first time commit

zj 2 years ago
parent
commit
5d366f227d
32 changed files with 2525 additions and 0 deletions
  1. 80 0
      .gitignore
  2. 201 0
      LICENSE
  3. 79 0
      pom.xml
  4. 66 0
      zzbusiness-common/pom.xml
  5. 214 0
      zzbusiness-common/src/main/java/org/zhongzheng/common/doentity/BaseEntity.java
  6. 68 0
      zzbusiness-common/src/main/java/org/zhongzheng/common/doentity/TenantEntity.java
  7. 34 0
      zzbusiness-common/src/main/java/org/zhongzheng/common/env/TokenConstants.java
  8. 80 0
      zzbusiness-common/src/main/java/org/zhongzheng/common/feignclient/zzbusinessuser/IUserClient.java
  9. 51 0
      zzbusiness-common/src/main/java/org/zhongzheng/common/feignclient/zzbusinessuser/IUserClientFallback.java
  10. 105 0
      zzbusiness-common/src/main/java/org/zhongzheng/common/feignclient/zzbusinessuser/entity/User.java
  11. 60 0
      zzbusiness-common/src/main/java/org/zhongzheng/common/feignclient/zzbusinessuser/entity/UserInfo.java
  12. 107 0
      zzbusiness-common/src/main/java/org/zhongzheng/common/feignclient/zzbusinessuser/entity/UserOauth.java
  13. 32 0
      zzbusiness-common/src/main/java/org/zhongzheng/common/utils/CacheNames.java
  14. 11 0
      zzbusiness-common/src/main/java/org/zhongzheng/common/utils/IResultCode.java
  15. 158 0
      zzbusiness-common/src/main/java/org/zhongzheng/common/utils/R.java
  16. 40 0
      zzbusiness-common/src/main/java/org/zhongzheng/common/utils/impl/ResultCode.java
  17. 82 0
      zzbusiness-gateway/pom.xml
  18. 19 0
      zzbusiness-gateway/src/main/java/org/zhongzheng/gateway/GatewayServerApplication.java
  19. 46 0
      zzbusiness-gateway/src/main/java/org/zhongzheng/gateway/config/JwtConfiguration.java
  20. 78 0
      zzbusiness-gateway/src/main/java/org/zhongzheng/gateway/config/RouterFunctionConfiguration.java
  21. 57 0
      zzbusiness-gateway/src/main/java/org/zhongzheng/gateway/controller/DiscoveryClientController.java
  22. 107 0
      zzbusiness-gateway/src/main/java/org/zhongzheng/gateway/filter/AuthFilter.java
  23. 58 0
      zzbusiness-gateway/src/main/java/org/zhongzheng/gateway/props/JwtProperties.java
  24. 59 0
      zzbusiness-gateway/src/main/java/org/zhongzheng/gateway/provider/AuthProvider.java
  25. 83 0
      zzbusiness-gateway/src/main/java/org/zhongzheng/gateway/provider/ResponseProvider.java
  26. 203 0
      zzbusiness-gateway/src/main/java/org/zhongzheng/gateway/utils/JwtCrypto.java
  27. 115 0
      zzbusiness-gateway/src/main/java/org/zhongzheng/gateway/utils/JwtUtil.java
  28. 47 0
      zzbusiness-gateway/src/main/resources/application.yml
  29. 79 0
      zzbusiness-user/pom.xml
  30. 49 0
      zzbusiness-user/src/main/java/org/zhongzheng/user/UserApplication.java
  31. 43 0
      zzbusiness-user/src/main/java/org/zhongzheng/user/controller/UserController.java
  32. 14 0
      zzbusiness-user/src/main/resources/application.yml

+ 80 - 0
.gitignore

@@ -0,0 +1,80 @@
+######################
+# 解决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*
+
+######################
+# 解决maven产生的文件
+######################
+
+target/
+**/target/
+pom.xml.tag
+pom.xml.releaseBackup
+pom.xml.versionsBackup
+pom.xml.next
+release.properties
+dependency-reduced-pom.xml
+buildNumber.properties
+.mvn/timing.properties
+
+######################
+# 解决各类编辑器自动产生的文件
+######################
+
+*.iml
+
+## Directory-based project format:
+.idea/
+# if you remove the above rule, at least ignore the following:
+
+# User-specific stuff:
+# .idea/workspace.xml
+# .idea/tasks.xml
+# .idea/dictionaries
+
+# Sensitive or high-churn files:
+# .idea/dataSources.ids
+# .idea/dataSources.xml
+# .idea/sqlDataSources.xml
+# .idea/dynamic.xml
+# .idea/uiDesigner.xml
+
+# Gradle:
+# .idea/gradle.xml
+# .idea/libraries
+
+# Mongo Explorer plugin:
+# .idea/mongoSettings.xml
+
+## File-based project format:
+*.ipr
+*.iws
+
+## Plugin-specific files:
+
+# IntelliJ
+/out/
+/target/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# JIRA plugin
+atlassian-ide-plugin.xml
+
+# Crashlytics plugin (for Android Studio and IntelliJ)
+com_crashlytics_export_strings.xml
+crashlytics.properties
+crashlytics-build.properties

+ 201 - 0
LICENSE

@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   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
+
+       http://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.

+ 79 - 0
pom.xml

@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.zhongzheng</groupId>
+    <artifactId>ZZBusiness</artifactId>
+    <version>1.0-SNAPSHOT</version>
+    <packaging>pom</packaging>
+
+    <!--子模块-->
+    <modules>
+        <module>zzbusiness-common</module>
+        <module>zzbusiness-gateway</module>
+        <module>zzbusiness-user</module>
+    </modules>
+
+    <!-- 统一管理版本管理 -->
+    <properties>
+        <maven.compiler.source>1.8</maven.compiler.source>
+        <maven.compiler.target>1.8</maven.compiler.target>
+        <springboot.version>2.2.0.RELEASE</springboot.version>
+        <springcloud.alibaba.version>2.2.0.RELEASE</springcloud.alibaba.version>
+
+        <blade.tool.version>3.7.1</blade.tool.version>
+        <blade.project.version>3.7.1</blade.project.version>
+
+        <mybatis-plus.version>3.4.2</mybatis-plus.version>
+        <mysql.connector.version>8.0.32</mysql.connector.version>
+
+        <captcha.version>1.6.2</captcha.version>
+    </properties>
+
+    <!-- 作用:锁定版本 子module不用写groupId和version -->
+    <dependencyManagement>
+        <dependencies>
+            <!--spring boot 2.2.2-->
+            <dependency>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-dependencies</artifactId>
+                <version>${springboot.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+            <!--Spring cloud alibaba 2.1.0.RELEASE-->
+            <dependency>
+                <groupId>com.alibaba.cloud</groupId>
+                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
+                <version>${springcloud.alibaba.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+
+            <dependency>
+                <groupId>com.fasterxml.jackson.core</groupId>
+                <artifactId>jackson-annotations</artifactId>
+            </dependency>
+
+            <dependency>
+                <groupId>io.springfox</groupId>
+                <artifactId>springfox-swagger2</artifactId>
+                <version>2.9.2</version>
+            </dependency>
+
+        </dependencies>
+    </dependencyManagement>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>2.3.4.RELEASE</version>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 66 - 0
zzbusiness-common/pom.xml

@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.zhongzheng</groupId>
+        <artifactId>ZZBusiness</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>zzbusiness-common</artifactId>
+    <!--打包方式-->
+    <packaging>jar</packaging>
+
+    <dependencies>
+        <dependency>
+            <!--父POM中锁定了版本信息,只需引入G,A即可 -->
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-openfeign</artifactId>
+            <version>2.2.8.RELEASE</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.baomidou</groupId>
+            <artifactId>mybatis-plus-boot-starter</artifactId>
+            <version>${mybatis-plus.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+
+        <!-- MySQL -->
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <version>${mysql.connector.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger2</artifactId>
+            <version>2.9.2</version>
+        </dependency>
+
+        <!--jackson依赖-->
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+            <version>2.9.1</version>
+        </dependency>
+
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>${springboot.version}</version>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 214 - 0
zzbusiness-common/src/main/java/org/zhongzheng/common/doentity/BaseEntity.java

@@ -0,0 +1,214 @@
+//
+// Source code recreated from a .class file by IntelliJ IDEA
+// (powered by FernFlower decompiler)
+//
+
+package org.zhongzheng.common.doentity;
+
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import io.swagger.annotations.ApiModelProperty;
+import java.io.Serializable;
+import java.util.Date;
+import org.springframework.format.annotation.DateTimeFormat;
+
+public class BaseEntity implements Serializable {
+    @JsonSerialize(
+            using = ToStringSerializer.class
+    )
+    @ApiModelProperty("创建人")
+    private Long createUser;
+    @DateTimeFormat(
+            pattern = "yyyy-MM-dd HH:mm:ss"
+    )
+    @JsonFormat(
+            pattern = "yyyy-MM-dd HH:mm:ss"
+    )
+    @ApiModelProperty("创建时间")
+    private Date createTime;
+    @JsonSerialize(
+            using = ToStringSerializer.class
+    )
+    @ApiModelProperty("更新人")
+    private Long updateUser;
+    @DateTimeFormat(
+            pattern = "yyyy-MM-dd HH:mm:ss"
+    )
+    @JsonFormat(
+            pattern = "yyyy-MM-dd HH:mm:ss"
+    )
+    @ApiModelProperty("更新时间")
+    private Date updateTime;
+    @ApiModelProperty("业务状态")
+    private Integer status;
+    @TableLogic
+    @ApiModelProperty("是否已删除")
+    private Integer isDeleted;
+
+    public BaseEntity() {
+    }
+
+    public Long getCreateUser() {
+        return this.createUser;
+    }
+
+    public Date getCreateTime() {
+        return this.createTime;
+    }
+
+    public Long getUpdateUser() {
+        return this.updateUser;
+    }
+
+    public Date getUpdateTime() {
+        return this.updateTime;
+    }
+
+    public Integer getStatus() {
+        return this.status;
+    }
+
+    public Integer getIsDeleted() {
+        return this.isDeleted;
+    }
+
+    public void setCreateUser(final Long createUser) {
+        this.createUser = createUser;
+    }
+
+    @JsonFormat(
+            pattern = "yyyy-MM-dd HH:mm:ss"
+    )
+    public void setCreateTime(final Date createTime) {
+        this.createTime = createTime;
+    }
+
+    public void setUpdateUser(final Long updateUser) {
+        this.updateUser = updateUser;
+    }
+
+    @JsonFormat(
+            pattern = "yyyy-MM-dd HH:mm:ss"
+    )
+    public void setUpdateTime(final Date updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public void setStatus(final Integer status) {
+        this.status = status;
+    }
+
+    public void setIsDeleted(final Integer isDeleted) {
+        this.isDeleted = isDeleted;
+    }
+
+    public boolean equals(final Object o) {
+        if (o == this) {
+            return true;
+        } else if (!(o instanceof org.zhongzheng.common.doentity.BaseEntity)) {
+            return false;
+        } else {
+            org.zhongzheng.common.doentity.BaseEntity other = (org.zhongzheng.common.doentity.BaseEntity)o;
+            if (!other.canEqual(this)) {
+                return false;
+            } else {
+                Object this$createUser = this.getCreateUser();
+                Object other$createUser = other.getCreateUser();
+                if (this$createUser == null) {
+                    if (other$createUser != null) {
+                        return false;
+                    }
+                } else if (!this$createUser.equals(other$createUser)) {
+                    return false;
+                }
+
+                Object this$updateUser = this.getUpdateUser();
+                Object other$updateUser = other.getUpdateUser();
+                if (this$updateUser == null) {
+                    if (other$updateUser != null) {
+                        return false;
+                    }
+                } else if (!this$updateUser.equals(other$updateUser)) {
+                    return false;
+                }
+
+                Object this$status = this.getStatus();
+                Object other$status = other.getStatus();
+                if (this$status == null) {
+                    if (other$status != null) {
+                        return false;
+                    }
+                } else if (!this$status.equals(other$status)) {
+                    return false;
+                }
+
+                label62: {
+                    Object this$isDeleted = this.getIsDeleted();
+                    Object other$isDeleted = other.getIsDeleted();
+                    if (this$isDeleted == null) {
+                        if (other$isDeleted == null) {
+                            break label62;
+                        }
+                    } else if (this$isDeleted.equals(other$isDeleted)) {
+                        break label62;
+                    }
+
+                    return false;
+                }
+
+                label55: {
+                    Object this$createTime = this.getCreateTime();
+                    Object other$createTime = other.getCreateTime();
+                    if (this$createTime == null) {
+                        if (other$createTime == null) {
+                            break label55;
+                        }
+                    } else if (this$createTime.equals(other$createTime)) {
+                        break label55;
+                    }
+
+                    return false;
+                }
+
+                Object this$updateTime = this.getUpdateTime();
+                Object other$updateTime = other.getUpdateTime();
+                if (this$updateTime == null) {
+                    if (other$updateTime != null) {
+                        return false;
+                    }
+                } else if (!this$updateTime.equals(other$updateTime)) {
+                    return false;
+                }
+
+                return true;
+            }
+        }
+    }
+
+    protected boolean canEqual(final Object other) {
+        return other instanceof org.zhongzheng.common.doentity.BaseEntity;
+    }
+
+    public int hashCode() {
+        int result = 1;
+        Object $createUser = this.getCreateUser();
+        result = result * 59 + ($createUser == null ? 43 : $createUser.hashCode());
+        Object $updateUser = this.getUpdateUser();
+        result = result * 59 + ($updateUser == null ? 43 : $updateUser.hashCode());
+        Object $status = this.getStatus();
+        result = result * 59 + ($status == null ? 43 : $status.hashCode());
+        Object $isDeleted = this.getIsDeleted();
+        result = result * 59 + ($isDeleted == null ? 43 : $isDeleted.hashCode());
+        Object $createTime = this.getCreateTime();
+        result = result * 59 + ($createTime == null ? 43 : $createTime.hashCode());
+        Object $updateTime = this.getUpdateTime();
+        result = result * 59 + ($updateTime == null ? 43 : $updateTime.hashCode());
+        return result;
+    }
+
+    public String toString() {
+        return "BaseEntity(createUser=" + this.getCreateUser() + ", createTime=" + this.getCreateTime() + ", updateUser=" + this.getUpdateUser() + ", updateTime=" + this.getUpdateTime() + ", status=" + this.getStatus() + ", isDeleted=" + this.getIsDeleted() + ")";
+    }
+}

+ 68 - 0
zzbusiness-common/src/main/java/org/zhongzheng/common/doentity/TenantEntity.java

@@ -0,0 +1,68 @@
+
+//
+// Source code recreated from a .class file by IntelliJ IDEA
+// (powered by FernFlower decompiler)
+//
+
+package org.zhongzheng.common.doentity;
+
+import io.swagger.annotations.ApiModelProperty;
+import org.zhongzheng.common.doentity.BaseEntity;
+
+public class TenantEntity extends BaseEntity {
+    @ApiModelProperty("租户ID")
+    private String tenantId;
+
+    public TenantEntity() {
+    }
+
+    public String getTenantId() {
+        return this.tenantId;
+    }
+
+    public void setTenantId(final String tenantId) {
+        this.tenantId = tenantId;
+    }
+
+    public String toString() {
+        return "TenantEntity(tenantId=" + this.getTenantId() + ")";
+    }
+
+    public boolean equals(final Object o) {
+        if (o == this) {
+            return true;
+        } else if (!(o instanceof org.zhongzheng.common.doentity.TenantEntity)) {
+            return false;
+        } else {
+            org.zhongzheng.common.doentity.TenantEntity other = (org.zhongzheng.common.doentity.TenantEntity)o;
+            if (!other.canEqual(this)) {
+                return false;
+            } else if (!super.equals(o)) {
+                return false;
+            } else {
+                Object this$tenantId = this.getTenantId();
+                Object other$tenantId = other.getTenantId();
+                if (this$tenantId == null) {
+                    if (other$tenantId != null) {
+                        return false;
+                    }
+                } else if (!this$tenantId.equals(other$tenantId)) {
+                    return false;
+                }
+
+                return true;
+            }
+        }
+    }
+
+    protected boolean canEqual(final Object other) {
+        return other instanceof org.zhongzheng.common.doentity.TenantEntity;
+    }
+
+    public int hashCode() {
+        int result = super.hashCode();
+        Object $tenantId = this.getTenantId();
+        result = result * 59 + ($tenantId == null ? 43 : $tenantId.hashCode());
+        return result;
+    }
+}

+ 34 - 0
zzbusiness-common/src/main/java/org/zhongzheng/common/env/TokenConstants.java

@@ -0,0 +1,34 @@
+
+
+//
+// Source code recreated from a .class file by IntelliJ IDEA
+// (powered by FernFlower decompiler)
+//
+
+package org.zhongzheng.common.env;
+
+public interface TokenConstants {
+    String AVATAR = "avatar";
+    String HEADER = "zhongzheng-auth";
+    String BEARER = "bearer";
+    String CRYPTO = "crypto";
+    String ACCESS_TOKEN = "access_token";
+    String REFRESH_TOKEN = "refresh_token";
+    String TOKEN_TYPE = "token_type";
+    String EXPIRES_IN = "expires_in";
+    String ACCOUNT = "account";
+    String USER_ID = "user_id";
+    String ROLE_ID = "role_id";
+    String DEPT_ID = "dept_id";
+    String USER_NAME = "user_name";
+    String ROLE_NAME = "role_name";
+    String TENANT_ID = "tenant_id";
+    String OAUTH_ID = "oauth_id";
+    String CLIENT_ID = "client_id";
+    String LICENSE = "license";
+    String LICENSE_NAME = "powered by ZhongZheng";
+    String DEFAULT_AVATAR = "https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png";
+    Integer AUTH_LENGTH = 7;
+    String SIGN_KEY = "zhongzhengxisapowerfulmicroservicearchitectureupgradedandoptimizedfromacommercialproject";
+    int SIGN_KEY_LENGTH = 32;
+}

+ 80 - 0
zzbusiness-common/src/main/java/org/zhongzheng/common/feignclient/zzbusinessuser/IUserClient.java

@@ -0,0 +1,80 @@
+/**
+ * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
+ * <p>
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+package org.zhongzheng.common.feignclient.zzbusinessuser;
+
+
+import org.zhongzheng.common.utils.R;
+import org.zhongzheng.common.feignclient.zzbusinessuser.entity.User;
+import org.zhongzheng.common.feignclient.zzbusinessuser.entity.UserInfo;
+import org.zhongzheng.common.feignclient.zzbusinessuser.entity.UserOauth;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestParam;
+
+/**
+ * User Feign接口类
+ *
+ * @author Chill
+ */
+@FeignClient(
+	value = "SERVER-USER",
+	fallback = IUserClientFallback.class
+)
+public interface IUserClient {
+
+	String API_PREFIX = "/user";
+
+	/**
+	 * 获取用户信息
+	 *
+	 * @param userId 用户id
+	 * @return
+	 */
+	@GetMapping(API_PREFIX + "/user-info-by-id")
+	R<UserInfo> userInfo(@RequestParam("userId") Long userId);
+
+	/**
+	 * 获取用户信息
+	 *
+	 * @param tenantId 租户ID
+	 * @param account    账号
+	 * @param password   密码
+	 * @return
+	 */
+	@GetMapping(API_PREFIX + "/user-info")
+	R<UserInfo> userInfo(@RequestParam("tenantId") String tenantId, @RequestParam("account") String account, @RequestParam("password") String password);
+
+	/**
+	 * 获取第三方平台信息
+	 *
+	 * @param userOauth 第三方授权用户信息
+	 * @return UserInfo
+	 */
+	@PostMapping(API_PREFIX + "/user-auth-info")
+	R<UserInfo> userAuthInfo(@RequestBody UserOauth userOauth);
+
+	/**
+	 * 新建用户
+	 *
+	 * @param user 用户实体
+	 * @return
+	 */
+	@PostMapping(API_PREFIX + "/save-user")
+	R<Boolean> saveUser(@RequestBody User user);
+
+}

+ 51 - 0
zzbusiness-common/src/main/java/org/zhongzheng/common/feignclient/zzbusinessuser/IUserClientFallback.java

@@ -0,0 +1,51 @@
+/**
+ * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
+ * <p>
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+package org.zhongzheng.common.feignclient.zzbusinessuser;
+
+import org.zhongzheng.common.utils.R;
+import org.zhongzheng.common.feignclient.zzbusinessuser.entity.User;
+import org.zhongzheng.common.feignclient.zzbusinessuser.entity.UserInfo;
+import org.zhongzheng.common.feignclient.zzbusinessuser.entity.UserOauth;
+import org.springframework.stereotype.Component;
+
+/**
+ * Feign失败配置
+ *
+ * @author Chill
+ */
+@Component
+public class IUserClientFallback implements IUserClient {
+
+	@Override
+	public R<UserInfo> userInfo(Long userId) {
+		return R.fail("未获取到账号信息");
+	}
+
+	@Override
+	public R<UserInfo> userInfo(String tenantId, String account, String password) {
+		return R.fail("未获取到账号信息");
+	}
+
+	@Override
+	public R<UserInfo> userAuthInfo(UserOauth userOauth) {
+		return R.fail("未获取到账号信息");
+	}
+
+	@Override
+	public R<Boolean> saveUser(User user) {
+		return R.fail("创建用户失败");
+	}
+}

+ 105 - 0
zzbusiness-common/src/main/java/org/zhongzheng/common/feignclient/zzbusinessuser/entity/User.java

@@ -0,0 +1,105 @@
+/**
+ * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
+ * <p>
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+package org.zhongzheng.common.feignclient.zzbusinessuser.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.zhongzheng.common.doentity.TenantEntity;
+
+import java.util.Date;
+
+/**
+ * 实体类
+ *
+ * @author Chill
+ */
+@Data
+@TableName("zhongzheng_user")
+@EqualsAndHashCode(callSuper = true)
+public class User extends TenantEntity {
+
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * 主键id
+	 */
+	@ApiModelProperty(value = "主键")
+	@TableId(value = "id", type = IdType.ASSIGN_ID)
+	@JsonSerialize(using = ToStringSerializer.class)
+	private Long id;
+
+
+	/**
+	 * 编号
+	 */
+	private String code;
+	/**
+	 * 账号
+	 */
+	private String account;
+	/**
+	 * 密码
+	 */
+	private String password;
+	/**
+	 * 昵称
+	 */
+	private String name;
+	/**
+	 * 真名
+	 */
+	private String realName;
+	/**
+	 * 头像
+	 */
+	private String avatar;
+	/**
+	 * 邮箱
+	 */
+	private String email;
+	/**
+	 * 手机
+	 */
+	private String phone;
+	/**
+	 * 生日
+	 */
+	private Date birthday;
+	/**
+	 * 性别
+	 */
+	private Integer sex;
+	/**
+	 * 角色id
+	 */
+	private String roleId;
+	/**
+	 * 部门id
+	 */
+	private String deptId;
+	/**
+	 * 部门id
+	 */
+	private String postId;
+
+
+}

+ 60 - 0
zzbusiness-common/src/main/java/org/zhongzheng/common/feignclient/zzbusinessuser/entity/UserInfo.java

@@ -0,0 +1,60 @@
+/**
+ * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
+ * <p>
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+package org.zhongzheng.common.feignclient.zzbusinessuser.entity;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 用户信息
+ *
+ * @author Chill
+ */
+@Data
+@ApiModel(description = "用户信息")
+public class UserInfo implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * 用户基础信息
+	 */
+	@ApiModelProperty(value = "用户")
+	private User user;
+
+	/**
+	 * 权限标识集合
+	 */
+	@ApiModelProperty(value = "权限集合")
+	private List<String> permissions;
+
+	/**
+	 * 角色集合
+	 */
+	@ApiModelProperty(value = "角色集合")
+	private List<String> roles;
+
+	/**
+	 * 第三方授权id
+	 */
+	@ApiModelProperty(value = "第三方授权id")
+	private String oauthId;
+
+}

+ 107 - 0
zzbusiness-common/src/main/java/org/zhongzheng/common/feignclient/zzbusinessuser/entity/UserOauth.java

@@ -0,0 +1,107 @@
+/**
+ * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
+ * <p>
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+package org.zhongzheng.common.feignclient.zzbusinessuser.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 实体类
+ *
+ * @author Chill
+ */
+@Data
+@TableName("blade_user_oauth")
+public class UserOauth implements Serializable {
+
+	private static final long serialVersionUID = 1L;
+
+
+	/**
+	 * 主键
+	 */
+	@JsonSerialize(using = ToStringSerializer.class)
+	@ApiModelProperty(value = "主键")
+	@TableId(value = "id", type = IdType.ASSIGN_ID)
+	private Long id;
+
+	/**
+	 * 租户ID
+	 */
+	private String tenantId;
+
+	/**
+	 * 第三方系统用户ID
+	 */
+	private String uuid;
+
+	/**
+	 * 用户ID
+	 */
+	@JsonSerialize(using = ToStringSerializer.class)
+	@ApiModelProperty(value = "用户主键")
+	private Long userId;
+
+	/**
+	 * 用户名
+	 */
+	private String username;
+	/**
+	 * 用户昵称
+	 */
+	private String nickname;
+	/**
+	 * 用户头像
+	 */
+	private String avatar;
+	/**
+	 * 用户网址
+	 */
+	private String blog;
+	/**
+	 * 所在公司
+	 */
+	private String company;
+	/**
+	 * 位置
+	 */
+	private String location;
+	/**
+	 * 用户邮箱
+	 */
+	private String email;
+	/**
+	 * 用户备注(各平台中的用户个人介绍)
+	 */
+	private String remark;
+	/**
+	 * 性别
+	 */
+	private String gender;
+	/**
+	 * 用户来源
+	 */
+	private String source;
+
+
+}

+ 32 - 0
zzbusiness-common/src/main/java/org/zhongzheng/common/utils/CacheNames.java

@@ -0,0 +1,32 @@
+/**
+ * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
+ * <p>
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+package org.zhongzheng.common.utils;
+
+/**
+ * 缓存名
+ *
+ * @author Chill
+ */
+public interface CacheNames {
+
+	String NOTICE_ONE = "notice:one";
+
+	String DICT_VALUE = "dict:value";
+	String DICT_LIST = "dict:list";
+
+	String CAPTCHA_KEY = "ZhongZheng:auth::captcha:";
+
+}

+ 11 - 0
zzbusiness-common/src/main/java/org/zhongzheng/common/utils/IResultCode.java

@@ -0,0 +1,11 @@
+package org.zhongzheng.common.utils;
+
+
+
+import java.io.Serializable;
+
+public interface IResultCode extends Serializable {
+    String getMessage();
+
+    int getCode();
+}

+ 158 - 0
zzbusiness-common/src/main/java/org/zhongzheng/common/utils/R.java

@@ -0,0 +1,158 @@
+package org.zhongzheng.common.utils;
+
+//
+// Source code recreated from a .class file by IntelliJ IDEA
+// (powered by FernFlower decompiler)
+//
+
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import java.io.Serializable;
+import java.util.Optional;
+import org.springframework.util.ObjectUtils;
+import org.springframework.lang.Nullable;
+import org.zhongzheng.common.utils.impl.ResultCode;
+
+@ApiModel(
+        description = "返回信息"
+)
+public class R<T> implements Serializable {
+    private static final long serialVersionUID = 1L;
+    @ApiModelProperty(
+            value = "状态码",
+            required = true
+    )
+    private int code;
+    @ApiModelProperty(
+            value = "是否成功",
+            required = true
+    )
+    private boolean success;
+    @ApiModelProperty("承载数据")
+    private T data;
+    @ApiModelProperty(
+            value = "返回消息",
+            required = true
+    )
+    private String msg;
+
+    private R(IResultCode resultCode) {
+        this(resultCode.getCode(),  resultCode.getMessage());
+    }
+
+    private R(IResultCode resultCode, T data) {
+        this(resultCode, data, resultCode.getMessage());
+    }
+
+    private R(IResultCode resultCode, T data, String msg) {
+        this(resultCode.getCode(), data, msg);
+    }
+
+    private R(int code,  String msg) {
+        this.code = code;
+        this.data = null;
+        this.msg = msg;
+        this.success = ResultCode.SUCCESS.code == code;
+    }
+
+    private R(int code, T data, String msg) {
+        this.code = code;
+        this.data = data;
+        this.msg = msg;
+        this.success = ResultCode.SUCCESS.code == code;
+    }
+
+    public static boolean isSuccess(@Nullable R<?> result) {
+        return (Boolean)Optional.ofNullable(result).map((x) -> {
+            return ObjectUtils.nullSafeEquals(ResultCode.SUCCESS.code, x.code);
+        }).orElse(Boolean.FALSE);
+    }
+
+    public static boolean isNotSuccess(@Nullable R<?> result) {
+        return !isSuccess(result);
+    }
+
+    public static <T> R<T> data(T data) {
+        return data(data, "操作成功");
+    }
+
+    public static <T> R<T> data(T data, String msg) {
+        return data(200, data, msg);
+    }
+
+    public static <T> R<T> data(int code, T data, String msg) {
+        return new R(code, data, data == null ? "暂无承载数据" : msg);
+    }
+
+    public static <T> R<T> success(String msg) {
+        return new R(ResultCode.SUCCESS, msg);
+    }
+
+    public static <T> R<T> success(IResultCode resultCode) {
+        return new R(resultCode);
+    }
+
+    public static <T> R<T> success(IResultCode resultCode, String msg) {
+        return new R(resultCode, msg);
+    }
+
+    public static <T> R<T> fail(String msg) {
+        return new R(ResultCode.FAILURE, msg);
+    }
+
+    public static <T> R<T> fail(int code, String msg) {
+        return new R(code, (Object)null, msg);
+    }
+
+    public static <T> R<T> fail(IResultCode resultCode) {
+        return new R(resultCode);
+    }
+
+    public static <T> R<T> fail(IResultCode resultCode, String msg) {
+        return new R(resultCode, msg);
+    }
+
+    public static <T> R<T> status(boolean flag) {
+        return flag ? success("操作成功") : fail("操作失败");
+    }
+
+    public int getCode() {
+        return this.code;
+    }
+
+    public boolean isSuccess() {
+        return this.success;
+    }
+
+    public T getData() {
+        return this.data;
+    }
+
+    public String getMsg() {
+        return this.msg;
+    }
+
+    public void setCode(final int code) {
+        this.code = code;
+    }
+
+    public void setSuccess(final boolean success) {
+        this.success = success;
+    }
+
+    public void setData(final T data) {
+        this.data = data;
+    }
+
+    public void setMsg(final String msg) {
+        this.msg = msg;
+    }
+
+    public String toString() {
+        return "R(code=" + this.getCode() + ", success=" + this.isSuccess() + ", data=" + this.getData() + ", msg=" + this.getMsg() + ")";
+    }
+
+    public R() {
+    }
+}

+ 40 - 0
zzbusiness-common/src/main/java/org/zhongzheng/common/utils/impl/ResultCode.java

@@ -0,0 +1,40 @@
+//
+// Source code recreated from a .class file by IntelliJ IDEA
+// (powered by FernFlower decompiler)
+//
+
+package org.zhongzheng.common.utils.impl;
+
+import org.zhongzheng.common.utils.IResultCode;
+
+public enum ResultCode implements IResultCode {
+    SUCCESS(200, "操作成功"),
+    FAILURE(400, "业务异常"),
+    UN_AUTHORIZED(401, "请求未授权"),
+    NOT_FOUND(404, "404 没找到请求"),
+    MSG_NOT_READABLE(400, "消息不能读取"),
+    METHOD_NOT_SUPPORTED(405, "不支持当前请求方法"),
+    MEDIA_TYPE_NOT_SUPPORTED(415, "不支持当前媒体类型"),
+    REQ_REJECT(403, "请求被拒绝"),
+    INTERNAL_SERVER_ERROR(500, "服务器异常"),
+    PARAM_MISS(400, "缺少必要的请求参数"),
+    PARAM_TYPE_ERROR(400, "请求参数类型错误"),
+    PARAM_BIND_ERROR(400, "请求参数绑定错误"),
+    PARAM_VALID_ERROR(400, "参数校验失败");
+
+    public final int code;
+    public final String message;
+
+    public int getCode() {
+        return this.code;
+    }
+
+    public String getMessage() {
+        return this.message;
+    }
+
+    private ResultCode(final int code, final String message) {
+        this.code = code;
+        this.message = message;
+    }
+}

+ 82 - 0
zzbusiness-gateway/pom.xml

@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>ZZBusiness</artifactId>
+        <groupId>org.zhongzheng</groupId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>zzbusiness-gateway</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
+        </dependency>
+        <!--网关-->
+        <dependency>
+            <groupId>org.springframework.cloud</groupId>
+            <artifactId>spring-cloud-starter-gateway</artifactId>
+            <version>${springcloud.alibaba.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <!-- JWT -->
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt-impl</artifactId>
+            <version>0.11.2</version>
+        </dependency>
+        <dependency>
+            <groupId>io.jsonwebtoken</groupId>
+            <artifactId>jjwt-jackson</artifactId>
+            <version>0.11.2</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.zhongzheng</groupId>
+            <artifactId>zzbusiness-common</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+    </dependencies>
+
+    <packaging>jar</packaging>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <!--生成的jar中,不要包含pom.xml和pom.properties这两个文件-->
+                        <addMavenDescriptor>true</addMavenDescriptor>
+                        <manifest>
+                            <mainClass>org.zhongzheng.gateway.GatewayServerApplication</mainClass>
+                        </manifest>
+                    </archive>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>${springboot.version}</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+
+</project>

+ 19 - 0
zzbusiness-gateway/src/main/java/org/zhongzheng/gateway/GatewayServerApplication.java

@@ -0,0 +1,19 @@
+package org.zhongzheng.gateway;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+
+//service reg & discover
+@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
+@EnableDiscoveryClient
+public class GatewayServerApplication {
+
+
+    public static void main(String[] args) {
+
+
+        SpringApplication.run(GatewayServerApplication .class);
+    }
+}

+ 46 - 0
zzbusiness-gateway/src/main/java/org/zhongzheng/gateway/config/JwtConfiguration.java

@@ -0,0 +1,46 @@
+/**
+ * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
+ * <p>
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+
+package org.zhongzheng.gateway.config;
+
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.zhongzheng.gateway.props.JwtProperties;
+import org.zhongzheng.gateway.utils.JwtUtil;
+import org.springframework.beans.factory.SmartInitializingSingleton;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * JWT配置信息
+ *
+ * @author Chill
+ */
+@Slf4j
+@Configuration(proxyBeanMethods = false)
+@AllArgsConstructor
+@EnableConfigurationProperties({JwtProperties.class})
+public class JwtConfiguration implements SmartInitializingSingleton {
+
+	private final JwtProperties properties;
+
+	@Override
+	public void afterSingletonsInstantiated() {
+		System.out.println("signkey:" + properties.getSignKey());
+
+		JwtUtil.setJwtProperties(properties);
+	}
+}

+ 78 - 0
zzbusiness-gateway/src/main/java/org/zhongzheng/gateway/config/RouterFunctionConfiguration.java

@@ -0,0 +1,78 @@
+/**
+ * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
+ * <p>
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+
+package org.zhongzheng.gateway.config;
+
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+import org.springframework.web.cors.reactive.CorsUtils;
+import org.springframework.web.server.ServerWebExchange;
+import org.springframework.web.server.WebFilter;
+import org.springframework.web.server.WebFilterChain;
+import reactor.core.publisher.Mono;
+
+/**
+ * 路由配置信息
+ *
+ * @author Chill
+ */
+@Slf4j
+@Configuration(proxyBeanMethods = false)
+@AllArgsConstructor
+public class RouterFunctionConfiguration {
+
+	/**
+	 * supported-headers
+	 */
+	private static final String ALLOWED_HEADERS = "X-Requested-With, Tenant-Id, ZhongZheng-Auth, Content-Type, Authorization, credential, X-XSRF-TOKEN, token, username, client, knife4j-gateway-request, knife4j-gateway-code, request-origin";
+	private static final String ALLOWED_METHODS = "GET,POST,PUT,DELETE,OPTIONS,HEAD";
+	private static final String ALLOWED_ORIGIN = "*";
+	private static final String ALLOWED_EXPOSE = "*";
+	private static final String MAX_AGE = "18000L";
+
+	/**
+	 * 跨域配置
+	 */
+	@Bean
+	public WebFilter corsFilter() {
+		return (ServerWebExchange ctx, WebFilterChain chain) -> {
+			ServerHttpRequest request = ctx.getRequest();
+			if (CorsUtils.isCorsRequest(request)) {
+				ServerHttpResponse response = ctx.getResponse();
+				HttpHeaders headers = response.getHeaders();
+				headers.add("Access-Control-Allow-Headers", ALLOWED_HEADERS);
+				headers.add("Access-Control-Allow-Methods", ALLOWED_METHODS);
+				headers.add("Access-Control-Allow-Origin", ALLOWED_ORIGIN);
+				headers.add("Access-Control-Expose-Headers", ALLOWED_EXPOSE);
+				headers.add("Access-Control-Max-Age", MAX_AGE);
+				headers.add("Access-Control-Allow-Credentials", "true");
+				if (request.getMethod() == HttpMethod.OPTIONS) {
+					response.setStatusCode(HttpStatus.OK);
+					return Mono.empty();
+				}
+			}
+			return chain.filter(ctx);
+		};
+	}
+
+}

+ 57 - 0
zzbusiness-gateway/src/main/java/org/zhongzheng/gateway/controller/DiscoveryClientController.java

@@ -0,0 +1,57 @@
+/**
+ * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
+ * <p>
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+package org.zhongzheng.gateway.controller;
+
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.cloud.client.ServiceInstance;
+import org.springframework.cloud.client.discovery.DiscoveryClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 服务发现控制器
+ *
+ * @author Czhill
+ */
+@Slf4j
+@RestController
+@AllArgsConstructor
+@RequestMapping("/discovery")
+public class DiscoveryClientController {
+
+	private final DiscoveryClient discoveryClient;
+
+	/**
+	 * 获取服务实例
+	 */
+	@GetMapping("/instances")
+	public Map<String, List<ServiceInstance>> instances() {
+		Map<String, List<ServiceInstance>> instances = new HashMap<>(16);
+		List<String> services = discoveryClient.getServices();
+		services.forEach(s -> {
+			List<ServiceInstance> list = discoveryClient.getInstances(s);
+			instances.put(s, list);
+		});
+		return instances;
+	}
+
+}

+ 107 - 0
zzbusiness-gateway/src/main/java/org/zhongzheng/gateway/filter/AuthFilter.java

@@ -0,0 +1,107 @@
+/**
+ * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
+ * <p>
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+package org.zhongzheng.gateway.filter;
+
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import io.jsonwebtoken.Claims;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.zhongzheng.gateway.provider.AuthProvider;
+import org.springframework.util.ObjectUtils;
+import org.zhongzheng.gateway.provider.ResponseProvider;
+import org.zhongzheng.gateway.utils.JwtCrypto;
+import org.zhongzheng.gateway.utils.JwtUtil;
+import org.springframework.cloud.gateway.filter.GatewayFilterChain;
+import org.springframework.cloud.gateway.filter.GlobalFilter;
+import org.springframework.core.Ordered;
+import org.springframework.core.io.buffer.DataBuffer;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+import org.springframework.stereotype.Component;
+import org.springframework.util.AntPathMatcher;
+import org.springframework.web.server.ServerWebExchange;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import java.nio.charset.StandardCharsets;
+
+import static org.zhongzheng.gateway.utils.JwtCrypto.ZHONGZHENG_CRYPTO_AES_KEY;
+
+/**
+ * 鉴权认证
+ *
+ * @author Chill
+ */
+@Slf4j
+@Component
+@AllArgsConstructor
+public class AuthFilter implements GlobalFilter, Ordered {
+	private final ObjectMapper objectMapper;
+	private final AntPathMatcher antPathMatcher = new AntPathMatcher();
+
+	@Override
+	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
+		String path = exchange.getRequest().getURI().getPath();
+		System.out.println("filter url: " + path);
+
+		if (isSkip(path)) {
+			return chain.filter(exchange);
+		}
+		ServerHttpResponse resp = exchange.getResponse();
+		String headerToken = exchange.getRequest().getHeaders().getFirst(AuthProvider.AUTH_KEY);
+		String paramToken = exchange.getRequest().getQueryParams().getFirst(AuthProvider.AUTH_KEY);
+		if (ObjectUtils.isEmpty(headerToken) && ObjectUtils.isEmpty(paramToken)) {
+			return unAuth(resp, "缺失令牌,鉴权失败(no auth header)");
+		}
+		String auth = ObjectUtils.isEmpty(headerToken) ? paramToken : headerToken;
+		String token = JwtUtil.getToken(auth);
+		//校验 加密Token 合法性
+		if (JwtUtil.isCrypto(auth)) {
+			token = JwtCrypto.decryptToString(token, org.zhongzheng.gateway.utils.JwtCrypto.ZHONGZHENG_CRYPTO_AES_KEY);
+		}
+		Claims claims = JwtUtil.parseJWT(token);
+		if (claims == null) {
+			return unAuth(resp, "请求未授权(invalid auth header)");
+		}
+		return chain.filter(exchange);
+	}
+
+	private boolean isSkip(String path) {
+		return AuthProvider.getDefaultSkipUrl().stream().anyMatch(pattern -> antPathMatcher.match(pattern, path));
+			// authProperties.getSkipUrl().stream().anyMatch(pattern -> antPathMatcher.match(pattern, path));
+	}
+
+	private Mono<Void> unAuth(ServerHttpResponse resp, String msg) {
+		resp.setStatusCode(HttpStatus.UNAUTHORIZED);
+		resp.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
+		String result = "";
+		try {
+			result = objectMapper.writeValueAsString(ResponseProvider.unAuth(msg));
+		} catch (JsonProcessingException e) {
+			log.error(e.getMessage(), e);
+		}
+		DataBuffer buffer = resp.bufferFactory().wrap(result.getBytes(StandardCharsets.UTF_8));
+		return resp.writeWith(Flux.just(buffer));
+	}
+
+	@Override
+	public int getOrder() {
+		return -100;
+	}
+
+}

+ 58 - 0
zzbusiness-gateway/src/main/java/org/zhongzheng/gateway/props/JwtProperties.java

@@ -0,0 +1,58 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.zhongzheng.gateway.props;
+
+import io.jsonwebtoken.JwtException;
+import lombok.Data;
+import org.zhongzheng.common.env.TokenConstants;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * JWT配置
+ *
+ * @author Chill
+ */
+@Data
+@ConfigurationProperties("zhongzheng.token")
+public class JwtProperties {
+
+	/**
+	 * token是否有状态
+	 */
+	private Boolean state = Boolean.FALSE;
+
+	/**
+	 * 是否只可同时在线一人
+	 */
+	private Boolean single = Boolean.FALSE;
+
+	/**
+	 * token签名
+	 */
+	private String signKey = "";
+
+	/**
+	 * 获取签名规则
+	 */
+	public String getSignKey() {
+		if (this.signKey.length() < TokenConstants.SIGN_KEY_LENGTH) {
+			throw new JwtException("请配置 zhongzheng.token.sign-key 的值, 长度32位以上");
+		}
+		return this.signKey;
+	}
+
+}

+ 59 - 0
zzbusiness-gateway/src/main/java/org/zhongzheng/gateway/provider/AuthProvider.java

@@ -0,0 +1,59 @@
+/**
+ * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
+ * <p>
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+package org.zhongzheng.gateway.provider;
+
+import org.zhongzheng.common.env.TokenConstants;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 鉴权配置
+ *
+ * @author Chill
+ */
+public class AuthProvider {
+
+	public static String AUTH_KEY = TokenConstants.HEADER;
+	private static final List<String> DEFAULT_SKIP_URL = new ArrayList<>();
+
+	static {
+		DEFAULT_SKIP_URL.add("/example");
+		DEFAULT_SKIP_URL.add("/token/**");
+		DEFAULT_SKIP_URL.add("/captcha/**");
+		DEFAULT_SKIP_URL.add("/actuator/health/**");
+		DEFAULT_SKIP_URL.add("/v2/api-docs/**");
+		DEFAULT_SKIP_URL.add("/auth/**");
+		DEFAULT_SKIP_URL.add("/oauth/**");
+		DEFAULT_SKIP_URL.add("/log/**");
+		DEFAULT_SKIP_URL.add("/menu/routes");
+		DEFAULT_SKIP_URL.add("/menu/auth-routes");
+		DEFAULT_SKIP_URL.add("/tenant/info");
+		DEFAULT_SKIP_URL.add("/order/create/**");
+		DEFAULT_SKIP_URL.add("/storage/deduct/**");
+		DEFAULT_SKIP_URL.add("/error/**");
+		DEFAULT_SKIP_URL.add("/assets/**");
+		DEFAULT_SKIP_URL.add("/zzbusiness-user/**");
+	}
+
+	/**
+	 * 默认无需鉴权的API
+	 */
+	public static List<String> getDefaultSkipUrl() {
+		return DEFAULT_SKIP_URL;
+	}
+
+}

+ 83 - 0
zzbusiness-gateway/src/main/java/org/zhongzheng/gateway/provider/ResponseProvider.java

@@ -0,0 +1,83 @@
+/**
+ * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
+ * <p>
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+package org.zhongzheng.gateway.provider;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 请求响应返回
+ *
+ * @author Chill
+ */
+public class ResponseProvider {
+
+	/**
+	 * 成功
+	 *
+	 * @param message 信息
+	 * @return
+	 */
+	public static Map<String, Object> success(String message) {
+		return response(200, message);
+	}
+
+	/**
+	 * 失败
+	 *
+	 * @param message 信息
+	 * @return
+	 */
+	public static Map<String, Object> fail(String message) {
+		return response(400, message);
+	}
+
+	/**
+	 * 未授权
+	 *
+	 * @param message 信息
+	 * @return
+	 */
+	public static Map<String, Object> unAuth(String message) {
+		return response(401, message);
+	}
+
+	/**
+	 * 服务器异常
+	 *
+	 * @param message 信息
+	 * @return
+	 */
+	public static Map<String, Object> error(String message) {
+		return response(500, message);
+	}
+
+	/**
+	 * 构建返回的JSON数据格式
+	 *
+	 * @param status  状态码
+	 * @param message 信息
+	 * @return
+	 */
+	public static Map<String, Object> response(int status, String message) {
+		Map<String, Object> map = new HashMap<>(16);
+		map.put("code", status);
+		map.put("msg", message);
+		map.put("data", null);
+		return map;
+	}
+
+}

+ 203 - 0
zzbusiness-gateway/src/main/java/org/zhongzheng/gateway/utils/JwtCrypto.java

@@ -0,0 +1,203 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package org.zhongzheng.gateway.utils;
+
+import lombok.SneakyThrows;
+import org.springframework.util.Assert;
+import org.springframework.util.Base64Utils;
+import org.springframework.util.StringUtils;
+import reactor.util.annotation.Nullable;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * JwtCrypto
+ *
+ * @author Chill
+ */
+public class JwtCrypto {
+
+	public static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8;
+	public static final String ZHONGZHENG_CRYPTO_AES_KEY = "zhongzheng.token.aes-key";
+
+
+	/**
+	 * Base64加密
+	 *
+	 * @param content    文本内容
+	 * @param aesTextKey 文本密钥
+	 * @return {String}
+	 */
+	public static String encryptToString(String content, String aesTextKey) {
+		return Base64Utils.encodeToString(encrypt(content, aesTextKey));
+	}
+
+	/**
+	 * Base64加密
+	 *
+	 * @param content    内容
+	 * @param aesTextKey 文本密钥
+	 * @return {String}
+	 */
+	public static String encryptToString(byte[] content, String aesTextKey) {
+		return Base64Utils.encodeToString(encrypt(content, aesTextKey));
+	}
+
+	/**
+	 * 加密
+	 *
+	 * @param content    文本内容
+	 * @param aesTextKey 文本密钥
+	 * @return byte[]
+	 */
+	public static byte[] encrypt(String content, String aesTextKey) {
+		return encrypt(content.getBytes(DEFAULT_CHARSET), aesTextKey);
+	}
+
+	/**
+	 * 加密
+	 *
+	 * @param content    文本内容
+	 * @param charset    编码
+	 * @param aesTextKey 文本密钥
+	 * @return byte[]
+	 */
+	public static byte[] encrypt(String content, Charset charset, String aesTextKey) {
+		return encrypt(content.getBytes(charset), aesTextKey);
+	}
+
+	/**
+	 * 加密
+	 *
+	 * @param content    内容
+	 * @param aesTextKey 文本密钥
+	 * @return byte[]
+	 */
+	public static byte[] encrypt(byte[] content, String aesTextKey) {
+		return encrypt(content, Objects.requireNonNull(aesTextKey).getBytes(DEFAULT_CHARSET));
+	}
+
+	/**
+	 * Base64解密
+	 *
+	 * @param content    文本内容
+	 * @param aesTextKey 文本密钥
+	 * @return {String}
+	 */
+	@Nullable
+	public static String decryptToString(@Nullable String content, @Nullable String aesTextKey) {
+		if (!StringUtils.hasText(content) || !StringUtils.hasText(aesTextKey)) {
+			return null;
+		}
+		byte[] hexBytes = decrypt(Base64Utils.decode(content.getBytes(DEFAULT_CHARSET)), aesTextKey);
+		return new String(hexBytes, DEFAULT_CHARSET);
+	}
+
+
+	/**
+	 * 解密
+	 *
+	 * @param content    内容
+	 * @param aesTextKey 文本密钥
+	 * @return byte[]
+	 */
+	public static byte[] decrypt(byte[] content, String aesTextKey) {
+		return decrypt(content, Objects.requireNonNull(aesTextKey).getBytes(DEFAULT_CHARSET));
+	}
+
+
+	/**
+	 * 解密
+	 *
+	 * @param content 内容
+	 * @param aesKey  密钥
+	 * @return byte[]
+	 */
+	public static byte[] encrypt(byte[] content, byte[] aesKey) {
+		return aes(Pkcs7Encoder.encode(content), aesKey, Cipher.ENCRYPT_MODE);
+	}
+
+	/**
+	 * 加密
+	 *
+	 * @param encrypted 内容
+	 * @param aesKey    密钥
+	 * @return byte[]
+	 */
+	public static byte[] decrypt(byte[] encrypted, byte[] aesKey) {
+		return Pkcs7Encoder.decode(aes(encrypted, aesKey, Cipher.DECRYPT_MODE));
+	}
+
+	/**
+	 * ase加密
+	 *
+	 * @param encrypted 内容
+	 * @param aesKey    密钥
+	 * @param mode      模式
+	 * @return byte[]
+	 */
+	@SneakyThrows
+	private static byte[] aes(byte[] encrypted, byte[] aesKey, int mode) {
+		Assert.isTrue(aesKey.length == 32, "IllegalAesKey, aesKey's length must be 32");
+		Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
+		SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES");
+		IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey, 0, 16));
+		cipher.init(mode, keySpec, iv);
+		return cipher.doFinal(encrypted);
+	}
+
+	/**
+	 * 提供基于PKCS7算法的加解密接口.
+	 */
+	private static class Pkcs7Encoder {
+		private static final int BLOCK_SIZE = 32;
+
+		private static byte[] encode(byte[] src) {
+			int count = src.length;
+			// count padding bytes count for AES
+			int amountToPad = BLOCK_SIZE - (count % BLOCK_SIZE);
+			// calc padding byte
+			byte pad = (byte) (amountToPad & 0xFF);
+			byte[] pads = new byte[amountToPad];
+			for (int index = 0; index < amountToPad; index++) {
+				pads[index] = pad;
+			}
+			int length = count + amountToPad;
+			byte[] dest = new byte[length];
+			System.arraycopy(src, 0, dest, 0, count);
+			System.arraycopy(pads, 0, dest, count, amountToPad);
+			return dest;
+		}
+
+		private static byte[] decode(byte[] decrypted) {
+			int pad = decrypted[decrypted.length - 1];
+			if (pad < 1 || pad > BLOCK_SIZE) {
+				pad = 0;
+			}
+			if (pad > 0) {
+				return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad);
+			}
+			return decrypted;
+		}
+	}
+}

+ 115 - 0
zzbusiness-gateway/src/main/java/org/zhongzheng/gateway/utils/JwtUtil.java

@@ -0,0 +1,115 @@
+/**
+ * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
+ * <p>
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.
+ */
+package org.zhongzheng.gateway.utils;
+
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jwts;
+import lombok.Getter;
+import org.zhongzheng.common.env.TokenConstants;
+import org.zhongzheng.gateway.props.JwtProperties;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+
+/**
+ * JwtUtil
+ *
+ * @author Chill
+ */
+public class JwtUtil {
+
+	public static String BEARER = TokenConstants.BEARER;
+	public static String CRYPTO = TokenConstants.CRYPTO;
+	public static Integer AUTH_LENGTH = 7;
+
+	/**
+	 * jwt配置
+	 */
+	@Getter
+	private static JwtProperties jwtProperties;
+
+	public static void setJwtProperties(JwtProperties properties) {
+		if (JwtUtil.jwtProperties == null) {
+			System.out.println("----------JwtProperties:: setJwtProperties");
+			JwtUtil.jwtProperties = properties;
+		}
+	}
+
+	/**
+	 * 签名加密
+	 */
+	public static String getBase64Security() {
+		return Base64.getEncoder().encodeToString(getJwtProperties().getSignKey().getBytes(StandardCharsets.UTF_8));
+	}
+
+	/**
+	 * 获取请求传递的token串
+	 *
+	 * @param auth token
+	 * @return String
+	 */
+	public static String getToken(String auth) {
+		if (isBearer(auth) || isCrypto(auth)) {
+			return auth.substring(AUTH_LENGTH);
+		}
+		return null;
+	}
+
+	/**
+	 * 判断token类型为bearer
+	 *
+	 * @param auth token
+	 * @return String
+	 */
+	public static Boolean isBearer(String auth) {
+		if ((auth != null) && (auth.length() > AUTH_LENGTH)) {
+			String headStr = auth.substring(0, 6).toLowerCase();
+			return headStr.compareTo(BEARER) == 0;
+		}
+		return false;
+	}
+
+	/**
+	 * 判断token类型为crypto
+	 *
+	 * @param auth token
+	 * @return String
+	 */
+	public static Boolean isCrypto(String auth) {
+		if ((auth != null) && (auth.length() > AUTH_LENGTH)) {
+			String headStr = auth.substring(0, 6).toLowerCase();
+			return headStr.compareTo(CRYPTO) == 0;
+		}
+		return false;
+	}
+
+	/**
+	 * 解析jsonWebToken
+	 *
+	 * @param jsonWebToken token串
+	 * @return Claims
+	 */
+	public static Claims parseJWT(String jsonWebToken) {
+		try {
+			return Jwts.parserBuilder()
+				.setSigningKey(Base64.getDecoder().decode(getBase64Security())).build()
+				.parseClaimsJws(jsonWebToken).getBody();
+		} catch (Exception ex) {
+			return null;
+		}
+	}
+
+}

+ 47 - 0
zzbusiness-gateway/src/main/resources/application.yml

@@ -0,0 +1,47 @@
+server:
+  port: 9100
+
+
+zhongzheng:
+  token:
+    state: false
+    single: false
+    signKey: "zhongzheng-sign-key-padding-bytes-tobe-enough-2024"
+
+spring:
+  application:
+    name: ZZBUSINESS-GATEWAY
+  cloud:
+    nacos:
+      discovery:
+        server-addr: localhost:8848    #Nacos注册中心地址
+    gateway:
+      discovery:
+        locator:
+          enabled: true #开放服务名访问方式
+          lower-case-service-id: false #服务名小写
+      routes:
+      - id: zzbusiness-user #指定服务名
+        uri: lb://ZZBUSINESS-USER #去注册中心找这个服务名
+        predicates:    #断言,匹配访问的路径
+          - Path=/zzbusiness-user/**    #服务访问路径
+        filters:
+          - StripPrefix=1    #请求转发的时候会去掉 /serv-con访问路径
+      globalcors: #跨域配置
+        cors-configurations:
+          '[/**]':
+            allowedOrigins:
+            - "http://127.0.0.1:9001" #允许跨域
+            - "http://127.0.0.1:9002"
+            allow-credentials: true
+            allowed-headers: "*"
+            allowedMethods:
+            - GET
+            - POST
+            - DELETE
+            - PUT
+            - PATCH
+            - OPTIONS
+            - HEAD
+            - CONNECT
+            - TRACE

+ 79 - 0
zzbusiness-user/pom.xml

@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.zhongzheng</groupId>
+        <artifactId>ZZBusiness</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>zzbusiness-user</artifactId>
+
+    <dependencies>
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
+        </dependency>
+        <!-- 配置中心 -->
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+            <version>${mysql.connector.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.zhongzheng</groupId>
+            <artifactId>zzbusiness-common</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+
+    </dependencies>
+
+    <packaging>jar</packaging>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <configuration>
+                    <archive>
+                        <!--生成的jar中,不要包含pom.xml和pom.properties这两个文件-->
+                        <addMavenDescriptor>true</addMavenDescriptor>
+                        <manifest>
+                            <mainClass>org.zhongzheng.user.UserApplication</mainClass>
+                        </manifest>
+                    </archive>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>${springboot.version}</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 49 - 0
zzbusiness-user/src/main/java/org/zhongzheng/user/UserApplication.java

@@ -0,0 +1,49 @@
+package org.zhongzheng.user;
+
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
+import org.springframework.cloud.client.loadbalancer.LoadBalanced;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+import org.springframework.context.annotation.Bean;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.client.RestTemplate;
+
+
+@SpringBootApplication
+@EnableFeignClients
+@EnableDiscoveryClient  //开启服务注册发现功能
+@RestController
+public class UserApplication {
+
+    public static void main(String[] args) {
+        SpringApplication.run(UserApplication.class, args);
+    }
+
+
+    @Autowired
+    private RestTemplate restTemplate;
+
+
+
+
+    /**
+     * 注入RestTemplate调用server-provider服务;
+     * LoadBalanced注解表示如果被调用的服务有多个节点,则默认采用轮询调用,实现负载均衡
+     */
+    @Bean
+    @LoadBalanced
+    public RestTemplate getRestTemplate(){
+        return new RestTemplate();
+    }
+
+    @GetMapping("/consumer")
+    public String test() {
+        //url拼写规则:  传输协议://服务名/访问路径
+        return restTemplate.getForObject("http://SERVER-PROVIDER/hello",String.class);
+    }
+
+}

+ 43 - 0
zzbusiness-user/src/main/java/org/zhongzheng/user/controller/UserController.java

@@ -0,0 +1,43 @@
+package org.zhongzheng.user.controller;
+
+import org.springframework.beans.factory.annotation.Autowired;
+
+import org.zhongzheng.common.feignclient.zzbusinessuser.IUserClient;
+import lombok.AllArgsConstructor;
+import org.zhongzheng.common.utils.R;
+import org.zhongzheng.common.feignclient.zzbusinessuser.entity.User;
+import org.zhongzheng.common.feignclient.zzbusinessuser.entity.UserInfo;
+import org.zhongzheng.common.feignclient.zzbusinessuser.entity.UserOauth;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@RestController
+@RequestMapping("/user")
+public class UserController implements IUserClient {
+    //private IUserService service;
+
+    @Override
+    public R<UserInfo> userInfo(Long userId) {
+        return R.data( new UserInfo());
+    }
+
+    @Override
+    @GetMapping(API_PREFIX + "/user-info")
+    public R<UserInfo> userInfo(String tenantId, String account, String password) {
+        return R.data( new UserInfo());
+    }
+
+    @Override
+    @PostMapping(API_PREFIX + "/user-auth-info")
+    public R<UserInfo> userAuthInfo(UserOauth userOauth) {
+        return R.data( new UserInfo());
+    }
+
+    @Override
+    @PostMapping(API_PREFIX + "/save-user")
+    public R<Boolean> saveUser(User user) {
+        return R.data( false );
+    }
+}

+ 14 - 0
zzbusiness-user/src/main/resources/application.yml

@@ -0,0 +1,14 @@
+server:
+  port: 9009
+spring:
+  application:
+    name: ZZBUSINESS-USER
+  datasource:
+    url: jdbc:mysql://192.168.1.222:3306/test_saas?useUnicode=true&characterEncoding=UTF-8&useSSL=false
+    username: root
+    password: zhongzheng2021
+    driver-class-name: com.mysql.cj.jdbc.Driver
+  cloud:
+    nacos:
+      discovery:
+        server-addr: localhost:8848