Browse Source

钉钉事件注册

hanzhuoyue 10 months ago
parent
commit
9f9247032f
29 changed files with 1906 additions and 1260 deletions
  1. BIN
      lib/taobao-sdk-java-auto_1479188381469-20180525-source.jar
  2. BIN
      lib/taobao-sdk-java-auto_1479188381469-20180525.jar
  3. 162 152
      ruoyi-admin/pom.xml
  4. 34 21
      ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java
  5. 27 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/dingding/Constant.java
  6. 219 68
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/dingding/DingAuthController.java
  7. 50 0
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/dingding/DingTalkEventListener.java
  8. 40 6
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/ResumeController.java
  9. 3 1
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/mobile/ResumeMobileController.java
  10. BIN
      ruoyi-admin/src/main/lib/lippi-oapi-encrpt.jar
  11. 60 60
      ruoyi-admin/src/main/resources/application-druid.yml
  12. 151 150
      ruoyi-admin/src/main/resources/application.yml
  13. 2 2
      ruoyi-admin/src/main/resources/hanlp.properties
  14. 5 0
      ruoyi-common/pom.xml
  15. 309 266
      ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java
  16. 122 120
      ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java
  17. 67 63
      ruoyi-framework/pom.xml
  18. 4 0
      ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java
  19. 56 44
      ruoyi-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java
  20. 65 0
      ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/DingAuthenticationProvider.java
  21. 85 0
      ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/DingDingAuthService.java
  22. 74 0
      ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/DingToken.java
  23. 289 236
      ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java
  24. 66 66
      ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java
  25. 4 0
      ruoyi-system/src/main/java/com/ruoyi/system/domain/resume/Resume.java
  26. 1 1
      ruoyi-system/src/main/java/com/ruoyi/system/mapper/resume/ResumeMapper.java
  27. 1 1
      ruoyi-system/src/main/java/com/ruoyi/system/service/resume/IResumeService.java
  28. 2 2
      ruoyi-system/src/main/java/com/ruoyi/system/service/resume/impl/ResumeServiceImpl.java
  29. 8 1
      ruoyi-system/src/main/resources/mapper/resume/ResumeMapper.xml

BIN
lib/taobao-sdk-java-auto_1479188381469-20180525-source.jar


BIN
lib/taobao-sdk-java-auto_1479188381469-20180525.jar


+ 162 - 152
ruoyi-admin/pom.xml

@@ -1,153 +1,163 @@
-<?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>ruoyi</artifactId>
-        <groupId>com.ruoyi</groupId>
-        <version>3.8.6</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-    <packaging>jar</packaging>
-    <artifactId>ruoyi-admin</artifactId>
-
-    <description>
-        web服务入口
-    </description>
-
-    <dependencies>
-
-        <!-- spring-boot-devtools -->
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-devtools</artifactId>
-            <optional>true</optional> <!-- 表示依赖不会传递 -->
-        </dependency>
-
-        <!-- swagger3-->
-        <dependency>
-            <groupId>io.springfox</groupId>
-            <artifactId>springfox-boot-starter</artifactId>
-        </dependency>
-
-        <!-- 防止进入swagger页面报类型转换错误,排除3.0.0中的引用,手动增加1.6.2版本 -->
-        <dependency>
-            <groupId>io.swagger</groupId>
-            <artifactId>swagger-models</artifactId>
-            <version>1.6.2</version>
-        </dependency>
-
-         <!-- Mysql驱动包 -->
-        <dependency>
-            <groupId>mysql</groupId>
-            <artifactId>mysql-connector-java</artifactId>
-        </dependency>
-
-        <!-- 核心模块-->
-        <dependency>
-            <groupId>com.ruoyi</groupId>
-            <artifactId>ruoyi-framework</artifactId>
-        </dependency>
-
-        <!-- 定时任务-->
-        <dependency>
-            <groupId>com.ruoyi</groupId>
-            <artifactId>ruoyi-quartz</artifactId>
-        </dependency>
-
-        <!-- 代码生成-->
-        <dependency>
-            <groupId>com.ruoyi</groupId>
-            <artifactId>ruoyi-generator</artifactId>
-        </dependency>
-
-        <dependency>
-            <groupId>com.ruoyi</groupId>
-            <artifactId>ruoyi-flowable</artifactId>
-        </dependency>
-
-        <!--
-			jxl中文支持比较好;
-			poi 的效率高于 jxl,支持的格式多余jxl;
-			随着excel的变大 poi性能会直线下降,jxl会有提升
-		 -->
-        <dependency>
-            <groupId>org.apache.poi</groupId>
-            <artifactId>poi</artifactId>
-            <version>3.12</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.poi</groupId>
-            <artifactId>poi-ooxml</artifactId>
-            <version>3.12</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.poi</groupId>
-            <artifactId>poi-ooxml-schemas</artifactId>
-            <version>3.12</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.poi</groupId>
-            <artifactId>poi-scratchpad</artifactId>
-            <version>3.12</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.poi</groupId>
-            <artifactId>poi-excelant</artifactId>
-            <version>3.12</version>
-        </dependency>
-        <dependency>
-            <groupId>com.deepoove</groupId>
-            <artifactId>poi-tl</artifactId>
-            <version>1.3.1</version>
-        </dependency>
-        <!-- end poi api 依赖 -->
-
-        <!-- google java lib -->
-        <dependency>
-            <groupId>com.google.guava</groupId>
-            <artifactId>guava</artifactId>
-            <version>17.0</version>
-        </dependency>
-
-        <!-- hanlp lib -->
-        <dependency>
-            <groupId>com.hanlp</groupId>
-            <artifactId>hanlp</artifactId>
-            <version>1.8.3</version>
-            <scope>system</scope>
-            <systemPath>${basedir}/src/main/lib/hanlp-1.8.3.jar</systemPath>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.springframework.boot</groupId>
-                <artifactId>spring-boot-maven-plugin</artifactId>
-                <version>2.5.15</version>
-                <configuration>
-                    <fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
-                </configuration>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>repackage</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>   
-                <groupId>org.apache.maven.plugins</groupId>   
-                <artifactId>maven-war-plugin</artifactId>   
-                <version>3.1.0</version>   
-                <configuration>
-                    <failOnMissingWebXml>false</failOnMissingWebXml>
-                    <warName>${project.artifactId}</warName>
-                </configuration>   
-           </plugin>   
-        </plugins>
-        <finalName>${project.artifactId}</finalName>
-    </build>
-
+<?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>ruoyi</artifactId>
+        <groupId>com.ruoyi</groupId>
+        <version>3.8.6</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <packaging>jar</packaging>
+    <artifactId>ruoyi-admin</artifactId>
+
+    <description>
+        web服务入口
+    </description>
+
+    <dependencies>
+
+        <!-- spring-boot-devtools -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-devtools</artifactId>
+            <optional>true</optional> <!-- 表示依赖不会传递 -->
+        </dependency>
+
+        <!-- swagger3-->
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-boot-starter</artifactId>
+        </dependency>
+
+        <!-- 防止进入swagger页面报类型转换错误,排除3.0.0中的引用,手动增加1.6.2版本 -->
+        <dependency>
+            <groupId>io.swagger</groupId>
+            <artifactId>swagger-models</artifactId>
+            <version>1.6.2</version>
+        </dependency>
+
+         <!-- Mysql驱动包 -->
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+        </dependency>
+
+        <!-- 核心模块-->
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-framework</artifactId>
+        </dependency>
+
+        <!-- 定时任务-->
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-quartz</artifactId>
+        </dependency>
+
+        <!-- 代码生成-->
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-generator</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-flowable</artifactId>
+        </dependency>
+
+        <!--
+			jxl中文支持比较好;
+			poi 的效率高于 jxl,支持的格式多余jxl;
+			随着excel的变大 poi性能会直线下降,jxl会有提升
+		 -->
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi</artifactId>
+            <version>3.12</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml</artifactId>
+            <version>3.12</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-ooxml-schemas</artifactId>
+            <version>3.12</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-scratchpad</artifactId>
+            <version>3.12</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.poi</groupId>
+            <artifactId>poi-excelant</artifactId>
+            <version>3.12</version>
+        </dependency>
+        <dependency>
+            <groupId>com.deepoove</groupId>
+            <artifactId>poi-tl</artifactId>
+            <version>1.3.1</version>
+        </dependency>
+        <!-- end poi api 依赖 -->
+
+        <!-- google java lib -->
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+            <version>17.0</version>
+        </dependency>
+
+        <!-- hanlp lib -->
+        <dependency>
+            <groupId>com.hanlp</groupId>
+            <artifactId>hanlp</artifactId>
+            <version>1.8.3</version>
+            <scope>system</scope>
+            <systemPath>${basedir}/src/main/lib/hanlp-1.8.3.jar</systemPath>
+        </dependency>
+        <dependency>
+            <groupId>com.taobao.top</groupId>
+            <artifactId>lippi-oapi-encrpt</artifactId>
+            <version>dingtalk-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>com.dingtalk.open</groupId>
+            <artifactId>app-stream-client</artifactId>
+            <version>1.3.2</version>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>2.5.15</version>
+                <configuration>
+                    <fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>   
+                <groupId>org.apache.maven.plugins</groupId>   
+                <artifactId>maven-war-plugin</artifactId>   
+                <version>3.1.0</version>   
+                <configuration>
+                    <failOnMissingWebXml>false</failOnMissingWebXml>
+                    <warName>${project.artifactId}</warName>
+                </configuration>   
+           </plugin>   
+        </plugins>
+        <finalName>${project.artifactId}</finalName>
+    </build>
+
 </project>

+ 34 - 21
ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java

@@ -1,21 +1,34 @@
-package com.ruoyi;
-
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
-
-/**
- * 启动程序
- * 
- * @author ruoyi
- */
-@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
-public class RuoYiApplication
-{
-    public static void main(String[] args)
-    {
-        // System.setProperty("spring.devtools.restart.enabled", "false");
-        SpringApplication.run(RuoYiApplication.class, args);
-        System.out.println("-----启动成功-----");
-    }
-}
+package com.ruoyi;
+
+import com.dingtalk.open.app.api.GenericEventListener;
+import com.dingtalk.open.app.api.OpenDingTalkStreamClientBuilder;
+import com.dingtalk.open.app.api.message.GenericOpenDingTalkEvent;
+import com.dingtalk.open.app.api.security.AuthClientCredential;
+import com.dingtalk.open.app.stream.protocol.event.EventAckStatus;
+import com.ruoyi.common.core.redis.RedisCache;
+import com.ruoyi.common.utils.dingding.config.DingAppConfig;
+import com.ruoyi.web.controller.dingding.DingTalkEventListener;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+
+import javax.annotation.Resource;
+
+import static com.ruoyi.framework.datasource.DynamicDataSourceContextHolder.log;
+
+/**
+ * 启动程序
+ *
+ * @author ruoyi
+ */
+@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
+public class RuoYiApplication {
+    @Resource
+    private RedisCache redisCache;
+
+    public static void main(String[] args) {
+        SpringApplication.run(RuoYiApplication.class, args);
+
+        System.out.println("-----启动成功-----");
+    }
+}

+ 27 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/dingding/Constant.java

@@ -0,0 +1,27 @@
+package com.ruoyi.web.controller.dingding;
+
+/**
+ * 项目中的常量定义类
+ */
+public class Constant {
+    /**
+     * 应用的SuiteKey,登录开发者后台,点击应用管理,进入应用详情可见
+     */
+    public static final String SUITE_KEY="suiteyjd6ikxpg8629ydr";
+
+    /**
+     * 应用的SuiteSecret,登录开发者后台,点击应用管理,进入应用详情可见
+     */
+    public static final String SUITE_SECRET="znq4BDYYX4vFLxtjfknEoId6j84LT2xpW7gkRTvpVZVoMfbfHXZvZX3cQ2cLQzON";
+
+    /**
+     * 回调URL签名用。应用的签名Token, 登录开发者后台,点击应用管理,进入应用详情可见
+     */
+    public static final String TOKEN = "foHrAyOAp4kIeNvi";
+
+    /**
+     * 回调URL加解密用。应用的"数据加密密钥",登录开发者后台,点击应用管理,进入应用详情可见
+     */
+    public static final String ENCODING_AES_KEY = "o13UDrSomxLeKRhwWtOgjjYpwLkzFS10HXz408Jt7OI";
+
+}

+ 219 - 68
ruoyi-admin/src/main/java/com/ruoyi/web/controller/dingding/DingAuthController.java

@@ -1,5 +1,7 @@
 package com.ruoyi.web.controller.dingding;
 
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
 import com.aliyun.dingtalkcontact_1_0.models.GetUserHeaders;
 import com.aliyun.dingtalkcontact_1_0.models.GetUserResponse;
 import com.aliyun.dingtalkcontact_1_0.Client;
@@ -11,13 +13,24 @@ import com.dingtalk.api.DefaultDingTalkClient;
 import com.dingtalk.api.DingTalkClient;
 import com.dingtalk.api.request.*;
 import com.dingtalk.api.response.*;
+import com.dingtalk.oapi.lib.aes.DingTalkEncryptException;
+import com.dingtalk.oapi.lib.aes.DingTalkEncryptor;
+import com.dingtalk.open.app.api.GenericEventListener;
+import com.dingtalk.open.app.api.OpenDingTalkStreamClientBuilder;
+import com.dingtalk.open.app.api.message.GenericOpenDingTalkEvent;
+import com.dingtalk.open.app.api.security.AuthClientCredential;
+import com.dingtalk.open.app.stream.protocol.event.EventAckStatus;
 import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.core.domain.entity.SysRole;
 import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.domain.model.LoginUser;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.dingding.config.DingAppConfig;
 import com.ruoyi.common.utils.dingding.config.DingUrlConstant;
+import com.ruoyi.framework.web.service.DingAuthenticationProvider;
+import com.ruoyi.framework.web.service.DingToken;
 import com.ruoyi.framework.web.service.SysLoginService;
 import com.ruoyi.system.domain.resume.CompanyInfo;
 import com.ruoyi.system.domain.resume.CompanyUser;
@@ -28,6 +41,7 @@ import com.ruoyi.system.service.dingding.DingTokenService;
 import com.ruoyi.system.service.resume.ICompanyInfoService;
 import com.ruoyi.system.service.resume.ICompanyUserService;
 import com.taobao.api.ApiException;
+import com.taobao.api.TaobaoResponse;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -51,7 +65,8 @@ import static com.ruoyi.framework.datasource.DynamicDataSourceContextHolder.log;
 @Controller
 @RequestMapping(value = "/ding")
 public class DingAuthController {
-
+    @Resource
+    private DingAppConfig dingAppConfig;
 
     @Resource
     private DingTokenService dingTokenService;
@@ -73,36 +88,112 @@ public class DingAuthController {
 
     @Autowired
     private ICompanyUserService companyUserService;
+    @Autowired
+    private DingAuthenticationProvider dingAuthenticationProvider;
+
 
     /**
-     * 钉钉用户登录,显示当前登录用户的userId和名称
-     *
-     * @param authCode 免登临时authCode
-     * @return 当前用户
+     * 创建应用,验证回调URL创建有效事件(第一次保存回调URL之前)
      */
-    @ApiOperation(value = "钉钉用户登录,显示当前登录用户的userId和名称")
-    @PostMapping("/avoidLogin")
-    @ResponseBody
-    public AjaxResult login(@RequestBody String authCode) {
-        String accessToken;
+    private static final String EVENT_CHECK_CREATE_SUITE_URL = "check_create_suite_url";
 
-        // 获取accessToken
-        AjaxResult accessTokenSr = dingTokenService.getAccessToken();
-        if (!accessTokenSr.isSuccess()) {
-            return accessTokenSr;
-        }
-        accessToken = accessTokenSr.get(accessTokenSr.MSG_TAG).toString();
+    /**
+     * 创建应用,验证回调URL变更有效事件(第一次保存回调URL之后)
+     */
+    private static final String EVENT_CHECK_UPADTE_SUITE_URL = "check_update_suite_url";
 
-        // 获取用户userId
-        AjaxResult userIdSr = getUserInfo(accessToken, authCode);
-        if (!userIdSr.isSuccess()) {
-            return userIdSr;
+    /**
+     * suite_ticket推送事件
+     */
+    private static final String EVENT_SUITE_TICKET = "suite_ticket";
+
+    /**
+     * 企业授权开通应用事件
+     */
+    private static final String EVENT_TMP_AUTH_CODE = "tmp_auth_code";
+
+    @PostMapping(value = "dingCallback2")
+    public Object dingCallback2(
+            @RequestParam(value = "signature") String signature,
+            @RequestParam(value = "timestamp") Long timestamp,
+            @RequestParam(value = "nonce") String nonce,
+            @RequestBody(required = false) JSONObject body
+    ) {
+        String params = "signature:" + signature + " timestamp:" + timestamp + " nonce:" + nonce + " body:" + body;
+        DingTalkEncryptor dingTalkEncryptor = null;
+        try {
+            dingTalkEncryptor = new DingTalkEncryptor(Constant.TOKEN, Constant.ENCODING_AES_KEY, Constant.SUITE_KEY);
+            // 从post请求的body中获取回调信息的加密数据进行解密处理,消息加解密参见下文
+            String encrypt = body.getString("encrypt");
+            String plainText = dingTalkEncryptor.getDecryptMsg(signature, timestamp.toString(), nonce, encrypt);
+            log.info("应用suite_ticket数据推送: " + plainText);
+            JSONObject callBackContent = JSON.parseObject(plainText);
+            log.info("begin callback encrypt:" + callBackContent.toString());
+            // 根据回调事件类型做不同的业务处理
+            String eventType = callBackContent.getString("EventType");
+            //TODO 将数据持久化
+            return plainText;
+        } catch (Exception e) {
+            log.error("process callback fail." + params, e);
+            return "fail";
         }
+    }
+    @GetMapping(value = "send")
+    public void send() {
+        try {
 
-        // 获取用户详情
-        AjaxResult userInfo = this.getUser(accessToken, userIdSr.get(userIdSr.MSG_TAG).toString());
+        } catch (Exception e) {
+            log.info("start fail."+e.getMessage());
+            throw new RuntimeException(e);
+        }
+    }
 
-        return userInfo;
+    @PostMapping(value = "callback")
+    public Object dingCallback(
+            @RequestParam(value = "signature") String signature,
+            @RequestParam(value = "timestamp") Long timestamp,
+            @RequestParam(value = "nonce") String nonce,
+            @RequestBody(required = false) JSONObject body
+    ) {
+        String params = "signature:" + signature + " timestamp:" + timestamp + " nonce:" + nonce + " body:" + body;
+        try {
+            log.info("begin callback:" + params);
+            DingTalkEncryptor dingTalkEncryptor = new DingTalkEncryptor(Constant.TOKEN, Constant.ENCODING_AES_KEY, Constant.SUITE_KEY);
+
+            // 从post请求的body中获取回调信息的加密数据进行解密处理
+            String encrypt = body.getString("encrypt");
+            String plainText = dingTalkEncryptor.getDecryptMsg(signature, timestamp.toString(), nonce, encrypt);
+            JSONObject callBackContent = JSON.parseObject(plainText);
+            log.info("begin callback encrypt:" + callBackContent.toString());
+            // 根据回调事件类型做不同的业务处理
+            String eventType = callBackContent.getString("EventType");
+            if (EVENT_CHECK_CREATE_SUITE_URL.equals(eventType)) {
+                log.info("验证新创建的回调URL有效性: " + plainText);
+            } else if (EVENT_CHECK_UPADTE_SUITE_URL.equals(eventType)) {
+                log.info("验证更新回调URL有效性: " + plainText);
+            } else if (EVENT_SUITE_TICKET.equals(eventType)) {
+                // suite_ticket用于用签名形式生成accessToken(访问钉钉服务端的凭证),需要保存到应用的db。
+                // 钉钉会定期向本callback url推送suite_ticket新值用以提升安全性。
+                // 应用在获取到新的时值时,保存db成功后,返回给钉钉success加密串(如本demo的return)
+                log.info("应用suite_ticket数据推送: " + plainText);
+            } else if (EVENT_TMP_AUTH_CODE.equals(eventType)) {
+                // 本事件应用应该异步进行授权开通企业的初始化,目的是尽最大努力快速返回给钉钉服务端。用以提升企业管理员开通应用体验
+                // 即使本接口没有收到数据或者收到事件后处理初始化失败都可以后续再用户试用应用时从前端获取到corpId并拉取授权企业信息,进而初始化开通及企业。
+                log.info("企业授权开通应用事件: " + plainText);
+            } else {
+                // 其他类型事件处理
+            }
+            log.info("callback 成功");
+            log.info("plainText:" + plainText);
+            // 返回success的加密信息表示回调处理成功
+            Map<String, String> success = dingTalkEncryptor.getEncryptedMap("success", timestamp, nonce);
+            log.info("success:" + JSON.toJSONString(success));
+            return success;
+        } catch (Exception e) {
+            //失败的情况,应用的开发者应该通过告警感知,并干预修复
+            log.error("process callback fail." + params, e);
+            return "fail";
+        }
     }
 
     /**
@@ -111,34 +202,92 @@ public class DingAuthController {
      * @param authCode 免登临时authCode
      * @return 当前用户
      */
+//    @ApiOperation(value = "钉钉用户登录,显示当前登录用户的userId和名称")
+//    @PostMapping("/avoidLogin")
+//    @ResponseBody
+//    public AjaxResult login(@RequestBody String authCode) {
+//        String accessToken;
+//
+//        // 获取accessToken
+//        AjaxResult accessTokenSr = dingTokenService.getAccessToken();
+//        if (!accessTokenSr.isSuccess()) {
+//            return accessTokenSr;
+//        }
+//        accessToken = accessTokenSr.get(accessTokenSr.MSG_TAG).toString();
+//
+//        // 获取用户userId
+//        AjaxResult userIdSr = getUserInfo(accessToken, authCode);
+//        if (!userIdSr.isSuccess()) {
+//            return userIdSr;
+//        }
+//
+//        // 获取用户详情
+//        AjaxResult userInfo = this.getUser(accessToken, userIdSr.get(userIdSr.MSG_TAG).toString());
+//
+//        return userInfo;
+//    }
+
+//    @ApiOperation(value = "11111")
+//    @PostMapping("/avoidLogin")
+//    @ResponseBody
+//    public AjaxResult login2() {
+//        String accessToken;
+
+    // 获取accessToken
+//        AjaxResult accessTokenSr = dingTokenService.getAccessToken();
+//        if (!accessTokenSr.isSuccess()) {
+//            return accessTokenSr;
+//        }
+//        accessToken = accessTokenSr.get(accessTokenSr.MSG_TAG).toString();
+//        AjaxResult userIdSr = getUserInfo(accessToken, "authCode");
+//        if (!userIdSr.isSuccess()) {
+//            return userIdSr;
+//        }
+//         loginService.authSingleSignIn2(accessToken, authCode);
+//        String token = loginService.authSingleSignIn2("123", "123");
+//
+//        if (StringUtils.isNotEmpty(token)){
+//            userIdSr.put(Constants.TOKEN, token);
+//        }
+//        return userIdSr;
+//    }
+
+    /**
+     * 钉钉用户登录,显示当前登录用户的userId和名称
+     *
+     * @param authCode 免登临时authCode
+     * @return 当前用户
+     */
+
     @ApiOperation(value = "钉钉用户登录第三方企业应用,显示当前登录用户的userId和名称")
     @PostMapping("/authLogin")
     @ResponseBody
     public AjaxResult authLogin(@RequestBody String authCode) {
         String accessToken = dingTokenService.getCorpAccessToken();
-        if(StringUtils.isNotEmpty(accessToken)){
+        if (StringUtils.isNotEmpty(accessToken)) {
             // 获取用户userId
             AjaxResult userIdSr = getUserInfo(accessToken, authCode);
             if (!userIdSr.isSuccess()) {
                 return userIdSr;
             }
-            OapiV2UserGetResponse response = this.getAuthUser(accessToken, userIdSr.get(userIdSr.MSG_TAG).toString());
-            SysUser sysUser = dingAuthService.getUserByUsername(response.getResult().getMobile());
-            if(StringUtils.isNull(sysUser)){
-                // todo 生成用户信息进行登录
-                sysUser = addUserAndOrg(response);
-            }
-            userIdSr.put("sysUser",sysUser);
-            String token = loginService.authSingleSignIn(sysUser.getUserName());
-            if (StringUtils.isNotEmpty(token)){
-                userIdSr.put(Constants.TOKEN, token);
+            Map<String, Object> stringObjectMap = loginService.authSingleSignIn2(accessToken, userIdSr.get(userIdSr.MSG_TAG).toString());
+            DingToken dingToken = (DingToken) stringObjectMap.get("authentication");
+            if (StringUtils.isNull(dingToken)) {
+                OapiV2UserGetResponse oapiV2UserGetResponse = (OapiV2UserGetResponse) dingToken.getTaobaoResponse();
+                SysUser sysUser = dingAuthService.getUserByUsername(oapiV2UserGetResponse.getResult().getMobile());
+                if (StringUtils.isNull(sysUser)) {
+                    // todo 生成用户信息进行登录
+                    addUserAndOrg(oapiV2UserGetResponse);
+                }
             }
+            String token = stringObjectMap.get("token").toString();
             return userIdSr;
-        }else{
+        } else {
             return AjaxResult.error("getAccessToken failed");
         }
     }
 
+
     /**
      * 访问/user/getuserinfo接口获取用户userId
      *
@@ -233,38 +382,37 @@ public class DingAuthController {
     }
 
 
-
     @RequestMapping(value = "/getAdminInfo", method = RequestMethod.GET)
-    public AjaxResult getAdminInfo(@RequestParam("authCode")String authCode) {
-            try {
-                com.aliyun.dingtalkoauth2_1_0.Client client = this.createClientNew();
-                String accessToken = dingTokenService.getAdminUserAccessToken();
-                GetSsoUserInfoHeaders getSsoUserInfoHeaders = new GetSsoUserInfoHeaders();
-                getSsoUserInfoHeaders.xAcsDingtalkAccessToken = accessToken;
-                GetSsoUserInfoRequest getSsoUserInfoRequest = new GetSsoUserInfoRequest()
-                        .setCode(authCode);
-                // 获取应用管理员的身份信息
-                GetSsoUserInfoResponse response = client.getSsoUserInfoWithOptions(getSsoUserInfoRequest, getSsoUserInfoHeaders, new RuntimeOptions());
-            } catch (TeaException err) {
-                if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
-                    // err 中含有 code 和 message 属性,可帮助开发定位问题
-                }
-            } catch (Exception _err) {
-                TeaException err = new TeaException(_err.getMessage(), _err);
-                if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
-                    // err 中含有 code 和 message 属性,可帮助开发定位问题
-                }
+    public AjaxResult getAdminInfo(@RequestParam("authCode") String authCode) {
+        try {
+            com.aliyun.dingtalkoauth2_1_0.Client client = this.createClientNew();
+            String accessToken = dingTokenService.getAdminUserAccessToken();
+            GetSsoUserInfoHeaders getSsoUserInfoHeaders = new GetSsoUserInfoHeaders();
+            getSsoUserInfoHeaders.xAcsDingtalkAccessToken = accessToken;
+            GetSsoUserInfoRequest getSsoUserInfoRequest = new GetSsoUserInfoRequest()
+                    .setCode(authCode);
+            // 获取应用管理员的身份信息
+            GetSsoUserInfoResponse response = client.getSsoUserInfoWithOptions(getSsoUserInfoRequest, getSsoUserInfoHeaders, new RuntimeOptions());
+        } catch (TeaException err) {
+            if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
+                // err 中含有 code 和 message 属性,可帮助开发定位问题
+            }
+        } catch (Exception _err) {
+            TeaException err = new TeaException(_err.getMessage(), _err);
+            if (!com.aliyun.teautil.Common.empty(err.code) && !com.aliyun.teautil.Common.empty(err.message)) {
+                // err 中含有 code 和 message 属性,可帮助开发定位问题
             }
+        }
         return AjaxResult.success();
     }
 
     /**
      * 根据保存的code值和获取的access_token,获取应用管理身份信息
      * openapi@dingtalk
+     *
      * @param code
      * @param access_token
-     * @return
-     * OapiSsoGetuserinfoResponse
+     * @return OapiSsoGetuserinfoResponse
      * 2020-11-3
      */
     public OapiSsoGetuserinfoResponse getAdminUserInfo(String code, String access_token) {
@@ -289,10 +437,10 @@ public class DingAuthController {
      * @param authCode 免登临时authCode
      * @return 当前用户
      */
-    @ApiOperation(value = "钉钉用户登录")
+    @ApiOperation(value = "钉钉内部应用-用户登录")
     @PostMapping("/authToken2")
     @ResponseBody
-    public AjaxResult authToken2(@RequestBody String authCode){
+    public AjaxResult authToken2(@RequestBody String authCode) {
         // 获取accessToken
         try {
             AjaxResult accessTokenSr = dingTokenService.getUserAccessToken(authCode);
@@ -302,22 +450,22 @@ public class DingAuthController {
             getUserHeaders.xAcsDingtalkAccessToken = accessTokenSr.get(accessTokenSr.MSG_TAG).toString();
             try {
                 GetUserResponse response = client.getUserWithOptions("me", getUserHeaders, new RuntimeOptions());
-                accessTokenSr.put("sysUser",response.getBody());
+                accessTokenSr.put("sysUser", response.getBody());
 
                 SysUser sysUser = dingAuthService.getUserByUsername(response.getBody().getMobile());
 
-                if(StringUtils.isNull(sysUser) ){
+                if (StringUtils.isNull(sysUser)) {
                     // todo 生成用户信息进行登录
                 }
 
                 String token = loginService.authSingleSignIn(sysUser.getUserName());
-                if (StringUtils.isNotEmpty(token)){
+                if (StringUtils.isNotEmpty(token)) {
                     accessTokenSr.put(Constants.TOKEN, token);
                 }
             } catch (TeaException e) {
-                return AjaxResult.error(e.getMessage(),e);
+                return AjaxResult.error(e.getMessage(), e);
             } catch (Exception e) {
-                return AjaxResult.error(e.getMessage(),e);
+                return AjaxResult.error(e.getMessage(), e);
             }
             return accessTokenSr;
         } catch (Exception e) {
@@ -325,12 +473,14 @@ public class DingAuthController {
         }
     }
 
+
     /**
      * 钉钉登录不存在用户自动增加用户以及组织信息
+     *
      * @param response
      * @return
      */
-    private SysUser addUserAndOrg(OapiV2UserGetResponse response){
+    private SysUser addUserAndOrg(OapiV2UserGetResponse response) {
         SysUser newUser = new SysUser();
         newUser.setUserName(response.getResult().getMobile());
         newUser.setAvatar(response.getResult().getAvatar());
@@ -341,7 +491,7 @@ public class DingAuthController {
         //角色自动赋值为简历管理角色
         Long[] roleIds = new Long[1];
         SysRole role = roleService.selectRoleByKey("resume");
-        if(role != null){
+        if (role != null) {
             roleIds[0] = role.getRoleId();
         }
         newUser.setRoleIds(roleIds);
@@ -352,7 +502,7 @@ public class DingAuthController {
         CompanyInfo companyInfo = new CompanyInfo();
         companyInfo.setCorpId(corpId);
         List<CompanyInfo> companyInfoList = companyInfoService.selectCompanyInfoList(companyInfo);
-        if(companyInfoList != null && !companyInfoList.isEmpty()){
+        if (companyInfoList != null && !companyInfoList.isEmpty()) {
             CompanyUser companyUser = new CompanyUser();
             companyUser.setCompanyId(companyInfoList.get(0).getId());
             companyUser.setUserId(newUser.getUserId());
@@ -363,6 +513,7 @@ public class DingAuthController {
 
     /**
      * 使用 Token 初始化账号Client
+     *
      * @return Client
      * @throws Exception
      */
@@ -375,6 +526,7 @@ public class DingAuthController {
 
     /**
      * 使用 Token 初始化账号后台Client
+     *
      * @return Client
      * @throws Exception
      */
@@ -386,5 +538,4 @@ public class DingAuthController {
     }
 
 
-
 }

+ 50 - 0
ruoyi-admin/src/main/java/com/ruoyi/web/controller/dingding/DingTalkEventListener.java

@@ -0,0 +1,50 @@
+package com.ruoyi.web.controller.dingding;
+
+import com.alibaba.fastjson2.JSONObject;
+import com.dingtalk.open.app.api.GenericEventListener;
+import com.dingtalk.open.app.api.message.GenericOpenDingTalkEvent;
+import com.dingtalk.open.app.stream.protocol.event.EventAckStatus;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.core.redis.RedisCache;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.spring.SpringUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.context.ApplicationEvent;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+import java.util.concurrent.TimeUnit;
+
+import static com.ruoyi.framework.datasource.DynamicDataSourceContextHolder.log;
+
+@Component
+@Slf4j
+public class DingTalkEventListener implements GenericEventListener {
+
+    @Override
+    public EventAckStatus onEvent(GenericOpenDingTalkEvent event) {
+        log.info("收到事件: " + event);
+        try {
+            //事件的唯一Id
+            String eventId = event.getEventId();
+            //事件类型
+            String eventType = event.getEventType();
+            //事件产生时间
+            Long bornTime = event.getEventBornTime();
+            //获取事件体
+            log.info("eventId: " + eventId + ", eventType: " + eventType + ", bornTime: " + bornTime);
+            SpringUtils.getBean(RedisCache.class).setCacheObject(Constants.DAILY_DING_SUITE_TICKET, event.getData().get("suiteTicket"), 5, TimeUnit.HOURS);
+            //处理事件
+
+            //消费成功
+            return EventAckStatus.SUCCESS;
+        } catch (Exception e) {
+            //消费失败
+            return EventAckStatus.LATER;
+        }
+    }
+}

+ 40 - 6
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/ResumeController.java

@@ -1,13 +1,15 @@
 package com.ruoyi.web.controller.tool;
 
 import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import javax.servlet.http.HttpServletResponse;
 
+import com.alibaba.druid.support.json.JSONUtils;
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.dingtalk.api.response.OapiUserAssociatedUnionidTransferResponse;
 import com.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.file.FileUploadUtils;
 import com.ruoyi.framework.config.ServerConfig;
@@ -19,8 +21,11 @@ import com.ruoyi.utils.resumeAnalysis.ResumeAnalysisUtil;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.Base64Utils;
+import org.springframework.util.CollectionUtils;
 import org.springframework.web.bind.annotation.*;
 import com.ruoyi.common.annotation.Log;
 import com.ruoyi.common.core.controller.BaseController;
@@ -28,6 +33,7 @@ import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.common.core.page.TableDataInfo;
+import org.springframework.web.client.RestTemplate;
 import org.springframework.web.multipart.MultipartFile;
 
 /**
@@ -46,6 +52,7 @@ public class ResumeController extends BaseController
 
     @Autowired
     private ServerConfig serverConfig;
+    private static final List<String> TYPE_LIST = Arrays.asList(".jpg", ".jpe", ".jpeg", ".jfif", ".png", ".webp", ".bmp", ".tif", ".tiff");
 
     /**
      * 查询简历管理列表
@@ -56,6 +63,7 @@ public class ResumeController extends BaseController
     public TableDataInfo list(Resume resume)
     {
         startPage();
+        resume.setCorpId(SecurityUtils.getLoginUser().getCorpid());
         List<Resume> list = resumeService.selectResumeList(resume);
         return getDataTable(list);
     }
@@ -68,6 +76,7 @@ public class ResumeController extends BaseController
     @PostMapping("/export")
     public void export(HttpServletResponse response, Resume resume)
     {
+        resume.setCorpId(SecurityUtils.getLoginUser().getCorpid());
         List<Resume> list = resumeService.selectResumeList(resume);
         ExcelUtil<Resume> util = new ExcelUtil<Resume>(Resume.class);
         util.exportExcel(response, list, "简历管理数据");
@@ -81,7 +90,8 @@ public class ResumeController extends BaseController
     @GetMapping(value = "/{resumeId}")
     public AjaxResult getInfo(@PathVariable("resumeId") Long resumeId)
     {
-        return success(resumeService.selectResumeByResumeId(resumeId));
+        String corpid = SecurityUtils.getLoginUser().getCorpid();
+        return success(resumeService.selectResumeByResumeId(resumeId,corpid));
     }
 
     /**
@@ -93,6 +103,7 @@ public class ResumeController extends BaseController
     @PostMapping
     public AjaxResult add(@RequestBody Resume resume)
     {
+        resume.setCorpId(SecurityUtils.getLoginUser().getCorpid());
         return toAjax(resumeService.insertResume(resume));
     }
 
@@ -104,6 +115,7 @@ public class ResumeController extends BaseController
     @ApiOperation(value = "上传简历并进行解析")
     @PostMapping(value = "/uploadResumeSimilarity",consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
     public AjaxResult uploadResumeSimilarity(MultipartFile file) {
+        String corpid = SecurityUtils.getLoginUser().getCorpid();
         try{
             if (file == null || StringUtils.isBlank(file.getOriginalFilename())) {
                 return AjaxResult.error("请上传简历");
@@ -120,19 +132,41 @@ public class ResumeController extends BaseController
             String lastPath = "/" + ymd + "/";
             String fileUrl = path + lastPath + newFileName;
 
-            if(suffix.equals(".doc")||suffix.equals(".docx")){
+            if(suffix.equals(".doc")||suffix.equals(".docx")||TYPE_LIST.contains(suffix)){
                 List<String> content = null;
                 try {
                     if(suffix.equals(".doc")){
                         content = FileUtils.readWord(fileUrl);
                     } else if (suffix.equals(".docx")) {
                         content = FileUtils.readWordDocx(fileUrl);
+                    }else if (TYPE_LIST.contains(suffix)){
+                        String encodeToString = Base64Utils.encodeToString(file.getBytes());
+                        RestTemplate restTemplate = new RestTemplate();
+                        Map<String,Object> map = new HashMap<>();
+                        map.put("base64",encodeToString);
+                        Map<String,Object> options = new HashMap<>();
+                        options.put("tbpu.parser","single_line");
+                        options.put("data.format","text");
+                        options.put("ocr.angle",false);
+                        options.put("ocr.language","简体中文");
+                        options.put("ocr.maxSideLen",1024);
+                        map.put("options",options);
+                        ResponseEntity<String> responseEntity = restTemplate.postForEntity(
+                                "http://127.0.0.1:1224/api/ocr", map, String.class);
+                        JSONObject parse = JSONObject.parse(responseEntity.getBody());
+                        if (100 != parse.getInteger("code")) {
+                            return AjaxResult.error("文件不存在解析失败");
+                        }
+                        content=new ArrayList<>();
+                        String[] split = parse.getString("data").split("\n");
+                        content.addAll(Arrays.asList(split));
                     }
                 } catch (Exception e) {
                     return AjaxResult.error("文件不存在解析失败");
                 }
                 //处理标识分段,并判断内容情况
                 Resume resume = ResumeAnalysisUtil.toResumeAnalysis(content);
+                resume.setCorpId(SecurityUtils.getLoginUser().getCorpid());
                 //处理文件信息
                 String url = serverConfig.getUrl() + fileName;
                 ResumeFile resumeFile = new ResumeFile();

+ 3 - 1
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/mobile/ResumeMobileController.java

@@ -6,6 +6,7 @@ import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.file.FileUploadUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
@@ -61,7 +62,8 @@ public class ResumeMobileController extends BaseController
     @GetMapping(value = "/{resumeId}")
     public AjaxResult getInfo(@PathVariable("resumeId") Long resumeId)
     {
-        return success(resumeService.selectResumeByResumeId(resumeId));
+
+        return success(resumeService.selectResumeByResumeId(resumeId,SecurityUtils.getLoginUser().getCorpid()));
     }
 
     /**

BIN
ruoyi-admin/src/main/lib/lippi-oapi-encrpt.jar


+ 60 - 60
ruoyi-admin/src/main/resources/application-druid.yml

@@ -1,61 +1,61 @@
-# 数据源配置
-spring:
-    datasource:
-        type: com.alibaba.druid.pool.DruidDataSource
-        driverClassName: com.mysql.cj.jdbc.Driver
-        druid:
-            # 主库数据源
-            master:
-                url: jdbc:mysql://10.32.2.215:3306/tony-flowable?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true
-                username: oneportal
-                password: Shanghai_1
-            # 从库数据源
-            slave:
-                # 从数据源开关/默认关闭
-                enabled: false
-                url: 
-                username: 
-                password: 
-            # 初始连接数
-            initialSize: 5
-            # 最小连接池数量
-            minIdle: 10
-            # 最大连接池数量
-            maxActive: 20
-            # 配置获取连接等待超时的时间
-            maxWait: 60000
-            # 配置连接超时时间
-            connectTimeout: 30000
-            # 配置网络超时时间
-            socketTimeout: 60000
-            # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
-            timeBetweenEvictionRunsMillis: 60000
-            # 配置一个连接在池中最小生存的时间,单位是毫秒
-            minEvictableIdleTimeMillis: 300000
-            # 配置一个连接在池中最大生存的时间,单位是毫秒
-            maxEvictableIdleTimeMillis: 900000
-            # 配置检测连接是否有效
-            validationQuery: SELECT 1 FROM DUAL
-            testWhileIdle: true
-            testOnBorrow: false
-            testOnReturn: false
-            webStatFilter: 
-                enabled: true
-            statViewServlet:
-                enabled: true
-                # 设置白名单,不填则允许所有访问
-                allow:
-                url-pattern: /druid/*
-                # 控制台管理用户名和密码
-                login-username: ruoyi
-                login-password: 123456
-            filter:
-                stat:
-                    enabled: true
-                    # 慢SQL记录
-                    log-slow-sql: true
-                    slow-sql-millis: 10000
-                    merge-sql: true
-                wall:
-                    config:
+# 数据源配置
+spring:
+    datasource:
+        type: com.alibaba.druid.pool.DruidDataSource
+        driverClassName: com.mysql.cj.jdbc.Driver
+        druid:
+            # 主库数据源
+            master:
+                url: jdbc:mysql://47.103.79.143:3306/tony-resume?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true
+                username: oneportal
+                password: Dgtis_oneportal
+            # 从库数据源
+            slave:
+                # 从数据源开关/默认关闭
+                enabled: false
+                url: 
+                username: 
+                password: 
+            # 初始连接数
+            initialSize: 5
+            # 最小连接池数量
+            minIdle: 10
+            # 最大连接池数量
+            maxActive: 20
+            # 配置获取连接等待超时的时间
+            maxWait: 60000
+            # 配置连接超时时间
+            connectTimeout: 30000
+            # 配置网络超时时间
+            socketTimeout: 60000
+            # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
+            timeBetweenEvictionRunsMillis: 60000
+            # 配置一个连接在池中最小生存的时间,单位是毫秒
+            minEvictableIdleTimeMillis: 300000
+            # 配置一个连接在池中最大生存的时间,单位是毫秒
+            maxEvictableIdleTimeMillis: 900000
+            # 配置检测连接是否有效
+            validationQuery: SELECT 1 FROM DUAL
+            testWhileIdle: true
+            testOnBorrow: false
+            testOnReturn: false
+            webStatFilter: 
+                enabled: true
+            statViewServlet:
+                enabled: true
+                # 设置白名单,不填则允许所有访问
+                allow:
+                url-pattern: /druid/*
+                # 控制台管理用户名和密码
+                login-username: ruoyi
+                login-password: 123456
+            filter:
+                stat:
+                    enabled: true
+                    # 慢SQL记录
+                    log-slow-sql: true
+                    slow-sql-millis: 10000
+                    merge-sql: true
+                wall:
+                    config:
                         multi-statement-allow: true

+ 151 - 150
ruoyi-admin/src/main/resources/application.yml

@@ -1,150 +1,151 @@
-# 项目相关配置
-ruoyi:
-  # 名称
-  name: RuoYi
-  # 版本
-  version: 3.8.6
-  # 版权年份
-  copyrightYear: 2023
-  # 实例演示开关
-  demoEnabled: true
-  # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
-  profile: D:/ruoyi/uploadPath
-  # 获取ip地址开关
-  addressEnabled: false
-  # 验证码类型 math 数字计算 char 字符验证
-  captchaType: math
-
-# 开发环境配置
-server:
-  # 服务器的HTTP端口,默认为8080
-  port: 8080
-  servlet:
-    # 应用的访问路径
-    context-path: /
-  tomcat:
-    # tomcat的URI编码
-    uri-encoding: UTF-8
-    # 连接数满后的排队数,默认为100
-    accept-count: 1000
-    threads:
-      # tomcat最大线程数,默认为200
-      max: 800
-      # Tomcat启动初始化的线程数,默认值10
-      min-spare: 100
-
-# 日志配置
-logging:
-  level:
-    com.ruoyi: debug
-    org.springframework: warn
-
-# 用户配置
-user:
-  password:
-    # 密码最大错误次数
-    maxRetryCount: 5
-    # 密码锁定时间(默认10分钟)
-    lockTime: 10
-
-# Spring配置
-spring:
-  # 资源信息
-  messages:
-    # 国际化资源文件路径
-    basename: i18n/messages
-  profiles:
-    active: druid
-  # 文件上传
-  servlet:
-    multipart:
-      # 单个文件大小
-      max-file-size: 10MB
-      # 设置总上传的文件大小
-      max-request-size: 20MB
-  # 服务模块
-  devtools:
-    restart:
-      # 热部署开关
-      enabled: true
-  # redis 配置
-  redis:
-    # 地址
-    host: localhost
-    # 端口,默认为6379
-    port: 6379
-    # 数据库索引
-    database: 0
-    # 密码
-    password: 123456
-    # 连接超时时间
-    timeout: 10s
-    lettuce:
-      pool:
-        # 连接池中的最小空闲连接
-        min-idle: 0
-        # 连接池中的最大空闲连接
-        max-idle: 8
-        # 连接池的最大数据库连接数
-        max-active: 8
-        # #连接池最大阻塞等待时间(使用负值表示没有限制)
-        max-wait: -1ms
-
-# token配置
-token:
-  # 令牌自定义标识
-  header: Authorization
-  # 令牌密钥
-  secret: abcdefghijklmnopqrstuvwxyz
-  # 令牌有效期(默认30分钟)
-  expireTime: 30
-
-# MyBatis配置
-mybatis:
-  # 搜索指定包别名
-  typeAliasesPackage: com.ruoyi.**.domain
-  # 配置mapper的扫描,找到所有的mapper.xml映射文件
-  mapperLocations: classpath*:mapper/**/*Mapper.xml
-  # 加载全局的配置文件
-  configLocation: classpath:mybatis/mybatis-config.xml
-
-# PageHelper分页插件
-pagehelper:
-  helperDialect: mysql
-  supportMethodsArguments: true
-  params: count=countSql
-
-# Swagger配置
-swagger:
-  # 是否开启swagger
-  enabled: true
-  # 请求前缀
-  pathMapping: /dev-api
-
-# 防止XSS攻击
-xss:
-  # 过滤开关
-  enabled: true
-  # 排除链接(多个用逗号分隔)
-  excludes: /system/notice
-  # 匹配链接
-  urlPatterns: /system/*,/monitor/*,/tool/*
-
-# flowable相关表
-flowable:
-  # true 会对数据库中所有表进行更新操作。如果表不存在,则自动创建(建议开发时使用)
-  database-schema-update: false
-  # 关闭定时任务JOB
-  async-executor-activate: false
-
-# DingDing配置
-dingtalk:
-  # 应用的唯一标识key。
-  app_key: dingwlimimzllguvqf8x
-  # 应用的密钥。
-  app_secret: pH4lgZ_k8lgkAU9jboz0SBpybX2kpGKotzL_sg5Gu8Whd-s7n3S_5rrziiK2Hde9
-  # 应用的标识
-  agent_id: 2803464118
-  # 企业ID
-  corp_id: ding4ab75ecd53106cde4ac5d6980864d335
-
+# 项目相关配置
+ruoyi:
+  # 名称
+  name: RuoYi
+  # 版本
+  version: 3.8.6
+  # 版权年份
+  copyrightYear: 2023
+  # 实例演示开关
+  demoEnabled: true
+  # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
+  profile: /home/ruoyi/uploadPath
+  # 获取ip地址开关
+  addressEnabled: false
+  # 验证码类型 math 数字计算 char 字符验证
+  captchaType: math
+
+# 开发环境配置
+server:
+  # 服务器的HTTP端口,默认为8080
+  port: 8080
+  servlet:
+    # 应用的访问路径
+    context-path: /
+  tomcat:
+    # tomcat的URI编码
+    uri-encoding: UTF-8
+    # 连接数满后的排队数,默认为100
+    accept-count: 1000
+    threads:
+      # tomcat最大线程数,默认为200
+      max: 800
+      # Tomcat启动初始化的线程数,默认值10
+      min-spare: 100
+
+# 日志配置
+logging:
+  level:
+    com.ruoyi: debug
+    org.springframework: warn
+
+# 用户配置
+user:
+  password:
+    # 密码最大错误次数
+    maxRetryCount: 5
+    # 密码锁定时间(默认10分钟)
+    lockTime: 10
+
+# Spring配置
+spring:
+  # 资源信息
+  messages:
+    # 国际化资源文件路径
+    basename: i18n/messages
+  profiles:
+    active: druid
+  # 文件上传
+  servlet:
+    multipart:
+      # 单个文件大小
+      max-file-size: 10MB
+      # 设置总上传的文件大小
+      max-request-size: 20MB
+  # 服务模块
+  devtools:
+    restart:
+      # 热部署开关
+      enabled: true
+  # redis 配置
+  redis:
+    # 地址
+    host: localhost
+    # 端口,默认为6379
+    port: 6379
+    # 数据库索引
+    database: 0
+    # 密码
+    password:
+    # 连接超时时间
+    timeout: 10s
+    lettuce:
+      pool:
+        # 连接池中的最小空闲连接
+        min-idle: 0
+        # 连接池中的最大空闲连接
+        max-idle: 8
+        # 连接池的最大数据库连接数
+        max-active: 8
+        # #连接池最大阻塞等待时间(使用负值表示没有限制)
+        max-wait: -1ms
+
+# token配置
+token:
+  # 令牌自定义标识
+  header: Authorization
+  # 令牌密钥
+  secret: abcdefghijklmnopqrstuvwxyz
+  # 令牌有效期(默认30分钟)
+  expireTime: 30
+
+# MyBatis配置
+mybatis:
+  # 搜索指定包别名
+  typeAliasesPackage: com.ruoyi.**.domain
+  # 配置mapper的扫描,找到所有的mapper.xml映射文件
+  mapperLocations: classpath*:mapper/**/*Mapper.xml
+  # 加载全局的配置文件
+  configLocation: classpath:mybatis/mybatis-config.xml
+
+# PageHelper分页插件
+pagehelper:
+  helperDialect: mysql
+  supportMethodsArguments: true
+  params: count=countSql
+
+# Swagger配置
+swagger:
+  # 是否开启swagger
+  enabled: true
+  # 请求前缀
+  pathMapping: /dev-api
+
+# 防止XSS攻击
+xss:
+  # 过滤开关
+  enabled: true
+  # 排除链接(多个用逗号分隔)
+  excludes: /system/notice
+  # 匹配链接
+  urlPatterns: /system/*,/monitor/*,/tool/*
+
+# flowable相关表
+flowable:
+  # true 会对数据库中所有表进行更新操作。如果表不存在,则自动创建(建议开发时使用)
+  database-schema-update: false
+  # 关闭定时任务JOB
+  async-executor-activate: false
+
+# DingDing配置
+dingtalk:
+  # 应用的唯一标识key。
+  app_key: suiteyjd6ikxpg8629ydr
+  # 应用的密钥。
+  app_secret: znq4BDYYX4vFLxtjfknEoId6j84LT2xpW7gkRTvpVZVoMfbfHXZvZX3cQ2cLQzON
+  # 应用的标识
+  agent_id: 2955933829
+  # 企业ID
+  corp_id: ding870ccf3c4d8fc1bc
+  sso_secret: 123
+

+ 2 - 2
ruoyi-admin/src/main/resources/hanlp.properties

@@ -1,8 +1,8 @@
 #本配置文件中的路径的根目录,根目录+其他路径=完整路径(支持相对路径,请参考:https://github.com/hankcs/HanLP/pull/254)
 #Windows用户请注意,路径分隔符统一使用/
 #root=C:/Users/zjc/Desktop/工作文件/
-root=D:/JavaProjects/HanLP/
-#root=/home/quizgo/HanLP/
+#root=D:/JavaProjects/HanLP/
+root=/home/quizgo/HanLP/
 
 #好了,以上为唯一需要修改的部分,以下配置项按需反注释编辑。
 

+ 5 - 0
ruoyi-common/pom.xml

@@ -145,6 +145,11 @@
             <artifactId>alibaba-dingtalk-service-sdk</artifactId>
             <version>2.0.0</version>
         </dependency>
+        <dependency>
+            <groupId>com.dingtalk.open</groupId>
+            <artifactId>app-stream-client</artifactId>
+            <version>1.3.2</version>
+        </dependency>
 
         <!-- okhttp3 -->
         <dependency>

+ 309 - 266
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java

@@ -1,266 +1,309 @@
-package com.ruoyi.common.core.domain.model;
-
-import com.alibaba.fastjson2.annotation.JSONField;
-import com.ruoyi.common.core.domain.entity.SysUser;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.userdetails.UserDetails;
-import java.util.Collection;
-import java.util.Set;
-
-/**
- * 登录用户身份权限
- * 
- * @author ruoyi
- */
-public class LoginUser implements UserDetails
-{
-    private static final long serialVersionUID = 1L;
-
-    /**
-     * 用户ID
-     */
-    private Long userId;
-
-    /**
-     * 部门ID
-     */
-    private Long deptId;
-
-    /**
-     * 用户唯一标识
-     */
-    private String token;
-
-    /**
-     * 登录时间
-     */
-    private Long loginTime;
-
-    /**
-     * 过期时间
-     */
-    private Long expireTime;
-
-    /**
-     * 登录IP地址
-     */
-    private String ipaddr;
-
-    /**
-     * 登录地点
-     */
-    private String loginLocation;
-
-    /**
-     * 浏览器类型
-     */
-    private String browser;
-
-    /**
-     * 操作系统
-     */
-    private String os;
-
-    /**
-     * 权限列表
-     */
-    private Set<String> permissions;
-
-    /**
-     * 用户信息
-     */
-    private SysUser user;
-
-    public LoginUser()
-    {
-    }
-
-    public LoginUser(SysUser user, Set<String> permissions)
-    {
-        this.user = user;
-        this.permissions = permissions;
-    }
-
-    public LoginUser(Long userId, Long deptId, SysUser user, Set<String> permissions)
-    {
-        this.userId = userId;
-        this.deptId = deptId;
-        this.user = user;
-        this.permissions = permissions;
-    }
-
-    public Long getUserId()
-    {
-        return userId;
-    }
-
-    public void setUserId(Long userId)
-    {
-        this.userId = userId;
-    }
-
-    public Long getDeptId()
-    {
-        return deptId;
-    }
-
-    public void setDeptId(Long deptId)
-    {
-        this.deptId = deptId;
-    }
-
-    public String getToken()
-    {
-        return token;
-    }
-
-    public void setToken(String token)
-    {
-        this.token = token;
-    }
-
-    @JSONField(serialize = false)
-    @Override
-    public String getPassword()
-    {
-        return user.getPassword();
-    }
-
-    @Override
-    public String getUsername()
-    {
-        return user.getUserName();
-    }
-
-    /**
-     * 账户是否未过期,过期无法验证
-     */
-    @JSONField(serialize = false)
-    @Override
-    public boolean isAccountNonExpired()
-    {
-        return true;
-    }
-
-    /**
-     * 指定用户是否解锁,锁定的用户无法进行身份验证
-     * 
-     * @return
-     */
-    @JSONField(serialize = false)
-    @Override
-    public boolean isAccountNonLocked()
-    {
-        return true;
-    }
-
-    /**
-     * 指示是否已过期的用户的凭据(密码),过期的凭据防止认证
-     * 
-     * @return
-     */
-    @JSONField(serialize = false)
-    @Override
-    public boolean isCredentialsNonExpired()
-    {
-        return true;
-    }
-
-    /**
-     * 是否可用 ,禁用的用户不能身份验证
-     * 
-     * @return
-     */
-    @JSONField(serialize = false)
-    @Override
-    public boolean isEnabled()
-    {
-        return true;
-    }
-
-    public Long getLoginTime()
-    {
-        return loginTime;
-    }
-
-    public void setLoginTime(Long loginTime)
-    {
-        this.loginTime = loginTime;
-    }
-
-    public String getIpaddr()
-    {
-        return ipaddr;
-    }
-
-    public void setIpaddr(String ipaddr)
-    {
-        this.ipaddr = ipaddr;
-    }
-
-    public String getLoginLocation()
-    {
-        return loginLocation;
-    }
-
-    public void setLoginLocation(String loginLocation)
-    {
-        this.loginLocation = loginLocation;
-    }
-
-    public String getBrowser()
-    {
-        return browser;
-    }
-
-    public void setBrowser(String browser)
-    {
-        this.browser = browser;
-    }
-
-    public String getOs()
-    {
-        return os;
-    }
-
-    public void setOs(String os)
-    {
-        this.os = os;
-    }
-
-    public Long getExpireTime()
-    {
-        return expireTime;
-    }
-
-    public void setExpireTime(Long expireTime)
-    {
-        this.expireTime = expireTime;
-    }
-
-    public Set<String> getPermissions()
-    {
-        return permissions;
-    }
-
-    public void setPermissions(Set<String> permissions)
-    {
-        this.permissions = permissions;
-    }
-
-    public SysUser getUser()
-    {
-        return user;
-    }
-
-    public void setUser(SysUser user)
-    {
-        this.user = user;
-    }
-
-    @Override
-    public Collection<? extends GrantedAuthority> getAuthorities()
-    {
-        return null;
-    }
-}
+package com.ruoyi.common.core.domain.model;
+
+import com.alibaba.fastjson2.annotation.JSONField;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * 登录用户身份权限
+ * 
+ * @author ruoyi
+ */
+public class LoginUser implements UserDetails
+{
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 用户ID
+     */
+    private Long userId;
+
+    /**
+     * 部门ID
+     */
+    private Long deptId;
+
+    /**
+     * 用户唯一标识
+     */
+    private String token;
+
+    /**
+     * 登录时间
+     */
+    private Long loginTime;
+
+    /**
+     * 过期时间
+     */
+    private Long expireTime;
+
+    /**
+     * 登录IP地址
+     */
+    private String ipaddr;
+
+    /**
+     * 登录地点
+     */
+    private String loginLocation;
+
+    /**
+     * 浏览器类型
+     */
+    private String browser;
+
+    /**
+     * 操作系统
+     */
+    private String os;
+
+    /**
+     * 权限列表
+     */
+    private Set<String> permissions;
+
+
+
+    /**
+     * 用户信息
+     */
+    private SysUser user;
+
+    private String corpid;
+
+    /*
+    登陆方式 password 、dingtalk、
+     */
+    private String authType;
+
+    private String principal;
+    private String credentials;
+    public LoginUser()
+    {
+    }
+
+    public LoginUser(SysUser user, Set<String> permissions)
+    {
+        this.user = user;
+        this.permissions = permissions;
+    }
+
+    public LoginUser(Long userId, Long deptId, SysUser user, Set<String> permissions)
+    {
+        this.userId = userId;
+        this.deptId = deptId;
+        this.user = user;
+        this.permissions = permissions;
+    }
+
+    public Long getUserId()
+    {
+        return userId;
+    }
+
+    public void setUserId(Long userId)
+    {
+        this.userId = userId;
+    }
+
+    public Long getDeptId()
+    {
+        return deptId;
+    }
+
+    public void setDeptId(Long deptId)
+    {
+        this.deptId = deptId;
+    }
+
+    public String getToken()
+    {
+        return token;
+    }
+
+    public void setToken(String token)
+    {
+        this.token = token;
+    }
+
+    @JSONField(serialize = false)
+    @Override
+    public String getPassword()
+    {
+        return user.getPassword();
+    }
+
+    @Override
+    public String getUsername()
+    {
+        return user.getUserName();
+    }
+
+    /**
+     * 账户是否未过期,过期无法验证
+     */
+    @JSONField(serialize = false)
+    @Override
+    public boolean isAccountNonExpired()
+    {
+        return true;
+    }
+
+    /**
+     * 指定用户是否解锁,锁定的用户无法进行身份验证
+     * 
+     * @return
+     */
+    @JSONField(serialize = false)
+    @Override
+    public boolean isAccountNonLocked()
+    {
+        return true;
+    }
+
+    /**
+     * 指示是否已过期的用户的凭据(密码),过期的凭据防止认证
+     * 
+     * @return
+     */
+    @JSONField(serialize = false)
+    @Override
+    public boolean isCredentialsNonExpired()
+    {
+        return true;
+    }
+
+    /**
+     * 是否可用 ,禁用的用户不能身份验证
+     * 
+     * @return
+     */
+    @JSONField(serialize = false)
+    @Override
+    public boolean isEnabled()
+    {
+        return true;
+    }
+
+    public Long getLoginTime()
+    {
+        return loginTime;
+    }
+
+    public void setLoginTime(Long loginTime)
+    {
+        this.loginTime = loginTime;
+    }
+
+    public String getIpaddr()
+    {
+        return ipaddr;
+    }
+
+    public void setIpaddr(String ipaddr)
+    {
+        this.ipaddr = ipaddr;
+    }
+
+    public String getLoginLocation()
+    {
+        return loginLocation;
+    }
+
+    public void setLoginLocation(String loginLocation)
+    {
+        this.loginLocation = loginLocation;
+    }
+
+    public String getBrowser()
+    {
+        return browser;
+    }
+
+    public void setBrowser(String browser)
+    {
+        this.browser = browser;
+    }
+
+    public String getOs()
+    {
+        return os;
+    }
+
+    public void setOs(String os)
+    {
+        this.os = os;
+    }
+
+    public Long getExpireTime()
+    {
+        return expireTime;
+    }
+
+    public void setExpireTime(Long expireTime)
+    {
+        this.expireTime = expireTime;
+    }
+
+    public Set<String> getPermissions()
+    {
+        return permissions;
+    }
+
+    public void setPermissions(Set<String> permissions)
+    {
+        this.permissions = permissions;
+    }
+
+    public SysUser getUser()
+    {
+        return user;
+    }
+
+    public void setUser(SysUser user)
+    {
+        this.user = user;
+    }
+
+    @Override
+    public Collection<? extends GrantedAuthority> getAuthorities()
+    {
+        return null;
+    }
+
+    public String getCorpid() {
+        return corpid;
+    }
+
+    public void setCorpid(String corpid) {
+        this.corpid = corpid;
+    }
+
+    public String getAuthType() {
+        return authType;
+    }
+
+    public void setAuthType(String authType) {
+        this.authType = authType;
+    }
+
+    public String getPrincipal() {
+        return principal;
+    }
+
+    public void setPrincipal(String principal) {
+        this.principal = principal;
+    }
+
+    public String getCredentials() {
+        return credentials;
+    }
+
+    public void setCredentials(String credentials) {
+        this.credentials = credentials;
+    }
+}

+ 122 - 120
ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java

@@ -1,120 +1,122 @@
-package com.ruoyi.common.utils;
-
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
-import com.ruoyi.common.constant.HttpStatus;
-import com.ruoyi.common.core.domain.model.LoginUser;
-import com.ruoyi.common.exception.ServiceException;
-
-/**
- * 安全服务工具类
- * 
- * @author ruoyi
- */
-public class SecurityUtils
-{
-    /**
-     * 用户ID
-     **/
-    public static Long getUserId()
-    {
-        try
-        {
-            return getLoginUser().getUserId();
-        }
-        catch (Exception e)
-        {
-            throw new ServiceException("获取用户ID异常", HttpStatus.UNAUTHORIZED);
-        }
-    }
-
-    /**
-     * 获取部门ID
-     **/
-    public static Long getDeptId()
-    {
-        try
-        {
-            return getLoginUser().getDeptId();
-        }
-        catch (Exception e)
-        {
-            throw new ServiceException("获取部门ID异常", HttpStatus.UNAUTHORIZED);
-        }
-    }
-    
-    /**
-     * 获取用户账户
-     **/
-    public static String getUsername()
-    {
-        try
-        {
-            return getLoginUser().getUsername();
-        }
-        catch (Exception e)
-        {
-            throw new ServiceException("获取用户账户异常", HttpStatus.UNAUTHORIZED);
-        }
-    }
-
-    /**
-     * 获取用户
-     **/
-    public static LoginUser getLoginUser()
-    {
-        try
-        {
-            return (LoginUser) getAuthentication().getPrincipal();
-        }
-        catch (Exception e)
-        {
-            throw new ServiceException("获取用户信息异常", HttpStatus.UNAUTHORIZED);
-        }
-    }
-
-    /**
-     * 获取Authentication
-     */
-    public static Authentication getAuthentication()
-    {
-        return SecurityContextHolder.getContext().getAuthentication();
-    }
-
-    /**
-     * 生成BCryptPasswordEncoder密码
-     *
-     * @param password 密码
-     * @return 加密字符串
-     */
-    public static String encryptPassword(String password)
-    {
-        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
-        return passwordEncoder.encode(password);
-    }
-
-    /**
-     * 判断密码是否相同
-     *
-     * @param rawPassword 真实密码
-     * @param encodedPassword 加密后字符
-     * @return 结果
-     */
-    public static boolean matchesPassword(String rawPassword, String encodedPassword)
-    {
-        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
-        return passwordEncoder.matches(rawPassword, encodedPassword);
-    }
-
-    /**
-     * 是否为管理员
-     * 
-     * @param userId 用户ID
-     * @return 结果
-     */
-    public static boolean isAdmin(Long userId)
-    {
-        return userId != null && 1L == userId;
-    }
-}
+package com.ruoyi.common.utils;
+
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import com.ruoyi.common.constant.HttpStatus;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.exception.ServiceException;
+
+/**
+ * 安全服务工具类
+ * 
+ * @author ruoyi
+ */
+public class SecurityUtils
+{
+    /**
+     * 用户ID
+     **/
+    public static Long getUserId()
+    {
+        try
+        {
+            return getLoginUser().getUserId();
+        }
+        catch (Exception e)
+        {
+            throw new ServiceException("获取用户ID异常", HttpStatus.UNAUTHORIZED);
+        }
+    }
+
+    /**
+     * 获取部门ID
+     **/
+    public static Long getDeptId()
+    {
+        try
+        {
+            return getLoginUser().getDeptId();
+        }
+        catch (Exception e)
+        {
+            throw new ServiceException("获取部门ID异常", HttpStatus.UNAUTHORIZED);
+        }
+    }
+    
+    /**
+     * 获取用户账户
+     **/
+    public static String getUsername()
+    {
+        try
+        {
+            return getLoginUser().getUsername();
+        }
+        catch (Exception e)
+        {
+            throw new ServiceException("获取用户账户异常", HttpStatus.UNAUTHORIZED);
+        }
+    }
+
+    /**
+     * 获取用户
+     **/
+    public static LoginUser getLoginUser()
+    {
+        LoginUser loginUser;
+        try {
+            loginUser = (LoginUser) getAuthentication().getDetails();
+
+            return loginUser;
+        }
+        catch (Exception e)
+        {
+            throw new ServiceException("获取用户信息异常", HttpStatus.UNAUTHORIZED);
+        }
+    }
+
+    /**
+     * 获取Authentication
+     */
+    public static Authentication getAuthentication()
+    {
+        return SecurityContextHolder.getContext().getAuthentication();
+    }
+
+    /**
+     * 生成BCryptPasswordEncoder密码
+     *
+     * @param password 密码
+     * @return 加密字符串
+     */
+    public static String encryptPassword(String password)
+    {
+        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
+        return passwordEncoder.encode(password);
+    }
+
+    /**
+     * 判断密码是否相同
+     *
+     * @param rawPassword 真实密码
+     * @param encodedPassword 加密后字符
+     * @return 结果
+     */
+    public static boolean matchesPassword(String rawPassword, String encodedPassword)
+    {
+        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
+        return passwordEncoder.matches(rawPassword, encodedPassword);
+    }
+
+    /**
+     * 是否为管理员
+     * 
+     * @param userId 用户ID
+     * @return 结果
+     */
+    public static boolean isAdmin(Long userId)
+    {
+        return userId != null && 1L == userId;
+    }
+}

+ 67 - 63
ruoyi-framework/pom.xml

@@ -1,64 +1,68 @@
-<?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>ruoyi</artifactId>
-        <groupId>com.ruoyi</groupId>
-        <version>3.8.6</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>ruoyi-framework</artifactId>
-
-    <description>
-        framework框架核心
-    </description>
-
-    <dependencies>
-
-        <!-- SpringBoot Web容器 -->
-         <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-web</artifactId>
-        </dependency>
-
-        <!-- SpringBoot 拦截器 -->
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-aop</artifactId>
-        </dependency>
-
-        <!-- 阿里数据库连接池 -->
-        <dependency>
-            <groupId>com.alibaba</groupId>
-            <artifactId>druid-spring-boot-starter</artifactId>
-        </dependency>
-
-        <!-- 验证码 -->
-        <dependency>
-            <groupId>pro.fessional</groupId>
-            <artifactId>kaptcha</artifactId>
-            <exclusions>
-                <exclusion>
-                    <artifactId>servlet-api</artifactId>
-                    <groupId>javax.servlet</groupId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-
-        <!-- 获取系统信息 -->
-        <dependency>
-            <groupId>com.github.oshi</groupId>
-            <artifactId>oshi-core</artifactId>
-        </dependency>
-
-        <!-- 系统模块-->
-        <dependency>
-            <groupId>com.ruoyi</groupId>
-            <artifactId>ruoyi-system</artifactId>
-        </dependency>
-
-    </dependencies>
-
+<?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>ruoyi</artifactId>
+        <groupId>com.ruoyi</groupId>
+        <version>3.8.6</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>ruoyi-framework</artifactId>
+
+    <description>
+        framework框架核心
+    </description>
+
+    <dependencies>
+
+        <!-- SpringBoot Web容器 -->
+         <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-web</artifactId>
+        </dependency>
+
+        <!-- SpringBoot 拦截器 -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-aop</artifactId>
+        </dependency>
+
+        <!-- 阿里数据库连接池 -->
+        <dependency>
+            <groupId>com.alibaba</groupId>
+            <artifactId>druid-spring-boot-starter</artifactId>
+        </dependency>
+
+        <!-- 验证码 -->
+        <dependency>
+            <groupId>pro.fessional</groupId>
+            <artifactId>kaptcha</artifactId>
+            <exclusions>
+                <exclusion>
+                    <artifactId>servlet-api</artifactId>
+                    <groupId>javax.servlet</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <!-- 获取系统信息 -->
+        <dependency>
+            <groupId>com.github.oshi</groupId>
+            <artifactId>oshi-core</artifactId>
+        </dependency>
+
+        <!-- 系统模块-->
+        <dependency>
+            <groupId>com.ruoyi</groupId>
+            <artifactId>ruoyi-system</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.projectlombok</groupId>
+            <artifactId>lombok</artifactId>
+        </dependency>
+
+    </dependencies>
+
 </project>

+ 4 - 0
ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java

@@ -1,5 +1,6 @@
 package com.ruoyi.framework.config;
 
+import com.ruoyi.framework.web.service.DingAuthenticationProvider;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Bean;
 import org.springframework.http.HttpMethod;
@@ -33,6 +34,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
      */
     @Autowired
     private UserDetailsService userDetailsService;
+    @Autowired
+    private DingAuthenticationProvider dingAuthenticationProvider;
     
     /**
      * 认证失败处理类
@@ -143,6 +146,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
     @Override
     protected void configure(AuthenticationManagerBuilder auth) throws Exception
     {
+//        auth.authenticationProvider(dingAuthenticationProvider);
         auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
     }
 }

+ 56 - 44
ruoyi-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java

@@ -1,44 +1,56 @@
-package com.ruoyi.framework.security.filter;
-
-import java.io.IOException;
-import javax.servlet.FilterChain;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
-import org.springframework.stereotype.Component;
-import org.springframework.web.filter.OncePerRequestFilter;
-import com.ruoyi.common.core.domain.model.LoginUser;
-import com.ruoyi.common.utils.SecurityUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.framework.web.service.TokenService;
-
-/**
- * token过滤器 验证token有效性
- * 
- * @author ruoyi
- */
-@Component
-public class JwtAuthenticationTokenFilter extends OncePerRequestFilter
-{
-    @Autowired
-    private TokenService tokenService;
-
-    @Override
-    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
-            throws ServletException, IOException
-    {
-        LoginUser loginUser = tokenService.getLoginUser(request);
-        if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication()))
-        {
-            tokenService.verifyToken(loginUser);
-            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
-            authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
-            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
-        }
-        chain.doFilter(request, response);
-    }
-}
+package com.ruoyi.framework.security.filter;
+
+import java.io.IOException;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.framework.web.service.DingToken;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.AbstractAuthenticationToken;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
+import org.springframework.stereotype.Component;
+import org.springframework.web.filter.OncePerRequestFilter;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.web.service.TokenService;
+
+/**
+ * token过滤器 验证token有效性
+ *
+ * @author ruoyi
+ */
+@Component
+public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
+    @Autowired
+    private TokenService tokenService;
+
+
+    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
+            throws ServletException, IOException {
+        LoginUser loginUser = tokenService.getLoginUser(request);
+        if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication())) {
+            tokenService.verifyToken(loginUser);
+            String authType = loginUser.getAuthType();
+            AbstractAuthenticationToken authRequest = null;
+            switch (authType) {
+                case "dingtalk":
+                    authRequest = new DingToken(loginUser.getPrincipal(), loginUser.getCredentials(),loginUser);
+                    authRequest.setDetails(loginUser);
+                    break;
+                case "password":
+                    authRequest = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
+                    authRequest.setDetails(loginUser);
+            }
+
+            SecurityContextHolder.getContext().setAuthentication(authRequest);
+        }
+        chain.doFilter(request, response);
+    }
+}
+

+ 65 - 0
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/DingAuthenticationProvider.java

@@ -0,0 +1,65 @@
+package com.ruoyi.framework.web.service;
+
+import com.alibaba.fastjson2.JSONObject;
+import com.dingtalk.api.response.OapiUserGetuserinfoResponse;
+import com.dingtalk.api.response.OapiV2UserGetResponse;
+import com.dingtalk.api.response.OapiV2UserGetuserinfoResponse;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.AuthenticationProvider;
+import org.springframework.security.authentication.InternalAuthenticationServiceException;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.stereotype.Component;
+
+import java.util.Objects;
+
+
+@Component
+@Slf4j
+@RequiredArgsConstructor
+public class DingAuthenticationProvider implements AuthenticationProvider {
+
+    @Autowired
+    private UserDetailsService userDetailsService;
+    @Autowired
+    private DingDingAuthService dingAuthService;
+
+
+    @Override
+    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
+        DingToken token = (DingToken) authentication;
+        String accessToken = (String) token.getPrincipal();
+        String userId = (String) token.getCredentials();
+        //根据accessToken 获取用户信息
+        OapiV2UserGetResponse response = dingAuthService.getAuthUser(accessToken, userId);
+        JSONObject parse = JSONObject.parseObject(response.getBody());
+        JSONObject user_info = parse.getJSONObject("user_info");
+        JSONObject corp_info = parse.getJSONObject("corp_info");
+        //然后,根据github用户,查询对应系统用户信息
+        LoginUser user = (LoginUser) userDetailsService.loadUserByUsername(user_info.getString("userid"));
+//        LoginUser user = (LoginUser) userDetailsService.loadUserByUsername("13621761774");
+        if (Objects.isNull(user)) {
+            throw new InternalAuthenticationServiceException("根据accessToken:" + accessToken + ",无法获取对应的用户信息!");
+        }
+        user.setCorpid(corp_info.getString("corpid"));
+        user.setAuthType("dingtalk");
+        user.setPrincipal(accessToken);
+        user.setCredentials(userId);
+        token.setDetails(user);
+        DingToken authenticationResult = new DingToken(user.getAuthorities(), accessToken, userId);
+        authenticationResult.setDetails(token.getDetails());
+        authenticationResult.setTaobaoResponse(response);
+        return authenticationResult;
+    }
+
+    @Override
+    public boolean supports(Class<?> authentication) {
+        return DingToken.class.isAssignableFrom(authentication);
+    }
+
+}

+ 85 - 0
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/DingDingAuthService.java

@@ -0,0 +1,85 @@
+package com.ruoyi.framework.web.service;
+
+import com.dingtalk.api.DefaultDingTalkClient;
+import com.dingtalk.api.DingTalkClient;
+import com.dingtalk.api.request.OapiUserGetRequest;
+import com.dingtalk.api.request.OapiUserGetuserinfoRequest;
+import com.dingtalk.api.request.OapiV2UserGetRequest;
+import com.dingtalk.api.response.OapiUserGetResponse;
+import com.dingtalk.api.response.OapiUserGetuserinfoResponse;
+import com.dingtalk.api.response.OapiV2UserGetResponse;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.dingding.config.DingUrlConstant;
+import com.ruoyi.system.service.dingding.DingAuthService;
+import com.taobao.api.ApiException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.Optional;
+
+import static com.ruoyi.framework.datasource.DynamicDataSourceContextHolder.log;
+
+/**
+ * @author hanzy
+ * @description
+ * @date 2024年04月29日 14:01
+ */
+@Service
+public class DingDingAuthService {
+    @Autowired
+    private DingAuthService dingAuthService;
+    public OapiV2UserGetResponse getAuthUser(String accessToken, String userId) {
+        DingTalkClient client = new DefaultDingTalkClient(DingUrlConstant.URL_USER_GET_V2);
+        OapiV2UserGetResponse response;
+        OapiV2UserGetRequest request = new OapiV2UserGetRequest();
+        request.setUserid(userId);
+        request.setLanguage("en_US");
+        try {
+            response = client.execute(request, accessToken);
+        } catch (ApiException e) {
+            log.error("Failed to getUserName: " + e.getErrMsg());
+            return null;
+        }
+        return response;
+    }
+    /**
+     * 访问/user/getuserinfo接口获取用户userId
+     *
+     * @param accessToken access_token
+     * @param authCode    临时授权码
+     * @return 用户userId或错误信息
+     */
+    public OapiUserGetuserinfoResponse getUserInfo(String accessToken, String authCode) {
+        DingTalkClient client = new DefaultDingTalkClient(DingUrlConstant.URL_GET_USER_INFO);
+        OapiUserGetuserinfoRequest request = new OapiUserGetuserinfoRequest();
+        request.setCode(authCode);
+        request.setHttpMethod("GET");
+        OapiUserGetuserinfoResponse response;
+        try {
+            response = client.execute(request, accessToken);
+        } catch (ApiException e) {
+            throw new ServiceException("Failed to getUserInfo: " + e.getMessage());
+        }
+        if (!response.isSuccess()) {
+            throw new ServiceException("Failed to getUserInfo: " + response.getMessage());
+        }
+        return response;
+    }
+    private SysUser assembleUserDTO(OapiUserGetResponse response, String accessToken) {
+        String userid = response.getUserid();
+        String mobile = response.getMobile();
+        try {
+            SysUser sysUser = Optional.ofNullable(dingAuthService.getUserByUserId(userid))
+                    .orElse(dingAuthService.getUserByUsername(mobile));
+            sysUser.setAccessToken(accessToken);
+            sysUser.setNickName(response.getName());
+            sysUser.setAvatar(response.getAvatar());
+            return sysUser;
+        } catch (Exception e) {
+            return new SysUser();
+        }
+    }
+
+}

+ 74 - 0
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/DingToken.java

@@ -0,0 +1,74 @@
+package com.ruoyi.framework.web.service;
+
+import com.taobao.api.TaobaoResponse;
+import org.springframework.security.authentication.AbstractAuthenticationToken;
+import org.springframework.security.core.GrantedAuthority;
+
+import java.util.Collection;
+
+/**
+ * @author hanzy
+ * @description
+ * @date 2024年04月29日 13:10
+ */
+
+public class DingToken extends AbstractAuthenticationToken {
+    public DingToken(Collection<? extends GrantedAuthority> authorities, String accessToken, String code) {
+        super(authorities);
+        this.accessToken = accessToken;
+        this.code = code;
+    }
+
+    public DingToken(String accessToken, String code) {
+        super(null);
+        this.accessToken = accessToken;
+        this.code = code;
+    }
+
+    public DingToken(String accessToken, String code,Object details) {
+        super(null);
+        this.accessToken = accessToken;
+        this.code = code;
+        super.setDetails(details);
+    }
+
+    private String accessToken;
+
+    private String code;
+
+    private TaobaoResponse taobaoResponse;
+
+    public String getAccessToken() {
+        return accessToken;
+    }
+
+    public void setAccessToken(String accessToken) {
+        this.accessToken = accessToken;
+    }
+
+    public String getCode() {
+        return code;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    @Override
+    public Object getCredentials() {
+        return this.code;
+    }
+
+    @Override
+    public Object getPrincipal() {
+        return this.accessToken;
+    }
+
+    public TaobaoResponse getTaobaoResponse() {
+        return taobaoResponse;
+    }
+
+    public void setTaobaoResponse(TaobaoResponse taobaoResponse) {
+        this.taobaoResponse = taobaoResponse;
+    }
+}

+ 289 - 236
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java

@@ -1,236 +1,289 @@
-package com.ruoyi.framework.web.service;
-
-import javax.annotation.Resource;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.authentication.AuthenticationManager;
-import org.springframework.security.authentication.BadCredentialsException;
-import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
-import org.springframework.security.core.Authentication;
-import org.springframework.stereotype.Component;
-import com.ruoyi.common.constant.CacheConstants;
-import com.ruoyi.common.constant.Constants;
-import com.ruoyi.common.constant.UserConstants;
-import com.ruoyi.common.core.domain.entity.SysUser;
-import com.ruoyi.common.core.domain.model.LoginUser;
-import com.ruoyi.common.core.redis.RedisCache;
-import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.common.exception.user.BlackListException;
-import com.ruoyi.common.exception.user.CaptchaException;
-import com.ruoyi.common.exception.user.CaptchaExpireException;
-import com.ruoyi.common.exception.user.UserNotExistsException;
-import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
-import com.ruoyi.common.utils.DateUtils;
-import com.ruoyi.common.utils.MessageUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.common.utils.ip.IpUtils;
-import com.ruoyi.framework.manager.AsyncManager;
-import com.ruoyi.framework.manager.factory.AsyncFactory;
-import com.ruoyi.framework.security.context.AuthenticationContextHolder;
-import com.ruoyi.system.service.ISysConfigService;
-import com.ruoyi.system.service.ISysUserService;
-
-/**
- * 登录校验方法
- * 
- * @author ruoyi
- */
-@Component
-public class SysLoginService
-{
-    @Autowired
-    private TokenService tokenService;
-
-    @Resource
-    private AuthenticationManager authenticationManager;
-
-    @Autowired
-    private RedisCache redisCache;
-    
-    @Autowired
-    private ISysUserService userService;
-
-    @Autowired
-    private ISysConfigService configService;
-
-    /**
-     * 登录验证
-     * 
-     * @param username 用户名
-     * @param password 密码
-     * @param code 验证码
-     * @param uuid 唯一标识
-     * @return 结果
-     */
-    public String login(String username, String password, String code, String uuid)
-    {
-        // 验证码校验
-        validateCaptcha(username, code, uuid);
-        // 登录前置校验
-        loginPreCheck(username, password);
-        // 用户验证
-        Authentication authentication = null;
-        try
-        {
-            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
-            AuthenticationContextHolder.setContext(authenticationToken);
-            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
-            authentication = authenticationManager.authenticate(authenticationToken);
-        }
-        catch (Exception e)
-        {
-            if (e instanceof BadCredentialsException)
-            {
-                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
-                throw new UserPasswordNotMatchException();
-            }
-            else
-            {
-                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
-                throw new ServiceException(e.getMessage());
-            }
-        }
-        finally
-        {
-            AuthenticationContextHolder.clearContext();
-        }
-        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
-        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
-        recordLoginInfo(loginUser.getUserId());
-        // 生成token
-        return tokenService.createToken(loginUser);
-    }
-
-
-    /**
-     * 校验验证码
-     * 
-     * @param username 用户名
-     * @param code 验证码
-     * @param uuid 唯一标识
-     * @return 结果
-     */
-    public void validateCaptcha(String username, String code, String uuid)
-    {
-        boolean captchaEnabled = configService.selectCaptchaEnabled();
-        if (captchaEnabled)
-        {
-            String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
-            String captcha = redisCache.getCacheObject(verifyKey);
-            redisCache.deleteObject(verifyKey);
-            if (captcha == null)
-            {
-                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
-                throw new CaptchaExpireException();
-            }
-            if (!code.equalsIgnoreCase(captcha))
-            {
-                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
-                throw new CaptchaException();
-            }
-        }
-    }
-
-    /**
-     * 登录前置校验
-     * @param username 用户名
-     * @param password 用户密码
-     */
-    public void loginPreCheck(String username, String password)
-    {
-        // 用户名或密码为空 错误
-        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password))
-        {
-            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
-            throw new UserNotExistsException();
-        }
-        // 密码如果不在指定范围内 错误
-        if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
-                || password.length() > UserConstants.PASSWORD_MAX_LENGTH)
-        {
-            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
-            throw new UserPasswordNotMatchException();
-        }
-        // 用户名不在指定范围内 错误
-        if (username.length() < UserConstants.USERNAME_MIN_LENGTH
-                || username.length() > UserConstants.USERNAME_MAX_LENGTH)
-        {
-            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
-            throw new UserPasswordNotMatchException();
-        }
-        // IP黑名单校验
-        String blackStr = configService.selectConfigByKey("sys.login.blackIPList");
-        if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr()))
-        {
-            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("login.blocked")));
-            throw new BlackListException();
-        }
-    }
-
-    /**
-     * 记录登录信息
-     *
-     * @param userId 用户ID
-     */
-    public void recordLoginInfo(Long userId)
-    {
-        SysUser sysUser = new SysUser();
-        sysUser.setUserId(userId);
-        sysUser.setLoginIp(IpUtils.getIpAddr());
-        sysUser.setLoginDate(DateUtils.getNowDate());
-        userService.updateUserProfile(sysUser);
-    }
-
-
-    /**
-     * 单点登录验证
-     *
-     * @param username 用户名
-     * @return 结果
-     */
-    public String authSingleSignIn(String username)
-    {
-        if (StringUtils.isEmpty(username))
-        {
-            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
-            throw new UserNotExistsException();
-        }
-        SysUser sysUser = userService.selectUserByUserName(username);
-        // 登录前置校验
-        loginPreCheck(username, "admin123");
-
-        // 用户验证
-        Authentication authentication = null;
-        try
-        {
-            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, "admin123");
-            AuthenticationContextHolder.setContext(authenticationToken);
-            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
-            authentication = authenticationManager.authenticate(authenticationToken);
-        }
-        catch (Exception e)
-        {
-            if (e instanceof BadCredentialsException)
-            {
-                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
-                throw new UserPasswordNotMatchException();
-            }
-            else
-            {
-                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
-                throw new ServiceException(e.getMessage());
-            }
-        }
-        finally
-        {
-            AuthenticationContextHolder.clearContext();
-        }
-        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
-        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
-        recordLoginInfo(loginUser.getUserId());
-        // 生成token
-        return tokenService.createToken(loginUser);
-    }
-
-
-
-}
+package com.ruoyi.framework.web.service;
+
+import javax.annotation.Resource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.stereotype.Component;
+import com.ruoyi.common.constant.CacheConstants;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.core.redis.RedisCache;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.exception.user.BlackListException;
+import com.ruoyi.common.exception.user.CaptchaException;
+import com.ruoyi.common.exception.user.CaptchaExpireException;
+import com.ruoyi.common.exception.user.UserNotExistsException;
+import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.ip.IpUtils;
+import com.ruoyi.framework.manager.AsyncManager;
+import com.ruoyi.framework.manager.factory.AsyncFactory;
+import com.ruoyi.framework.security.context.AuthenticationContextHolder;
+import com.ruoyi.system.service.ISysConfigService;
+import com.ruoyi.system.service.ISysUserService;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 登录校验方法
+ * 
+ * @author ruoyi
+ */
+@Component
+public class SysLoginService
+{
+    @Autowired
+    private TokenService tokenService;
+
+    @Resource
+    private AuthenticationManager authenticationManager;
+    @Resource
+    private DingAuthenticationProvider dingAuthenticationProvider;
+
+    @Autowired
+    private RedisCache redisCache;
+    
+    @Autowired
+    private ISysUserService userService;
+
+    @Autowired
+    private ISysConfigService configService;
+
+    /**
+     * 登录验证
+     * 
+     * @param username 用户名
+     * @param password 密码
+     * @param code 验证码
+     * @param uuid 唯一标识
+     * @return 结果
+     */
+    public String login(String username, String password, String code, String uuid)
+    {
+        // 验证码校验
+        validateCaptcha(username, code, uuid);
+        // 登录前置校验
+        loginPreCheck(username, password);
+        // 用户验证
+        Authentication authentication = null;
+        try
+        {
+            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
+            AuthenticationContextHolder.setContext(authenticationToken);
+            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
+            authentication = authenticationManager.authenticate(authenticationToken);
+        }
+        catch (Exception e)
+        {
+            if (e instanceof BadCredentialsException)
+            {
+                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
+                throw new UserPasswordNotMatchException();
+            }
+            else
+            {
+                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
+                throw new ServiceException(e.getMessage());
+            }
+        }
+        finally
+        {
+            AuthenticationContextHolder.clearContext();
+        }
+        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
+        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
+        recordLoginInfo(loginUser.getUserId());
+        // 生成token
+        return tokenService.createToken(loginUser);
+    }
+
+
+    /**
+     * 校验验证码
+     * 
+     * @param username 用户名
+     * @param code 验证码
+     * @param uuid 唯一标识
+     * @return 结果
+     */
+    public void validateCaptcha(String username, String code, String uuid)
+    {
+        boolean captchaEnabled = configService.selectCaptchaEnabled();
+        if (captchaEnabled)
+        {
+            String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
+            String captcha = redisCache.getCacheObject(verifyKey);
+            redisCache.deleteObject(verifyKey);
+            if (captcha == null)
+            {
+                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
+                throw new CaptchaExpireException();
+            }
+            if (!code.equalsIgnoreCase(captcha))
+            {
+                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
+                throw new CaptchaException();
+            }
+        }
+    }
+
+    /**
+     * 登录前置校验
+     * @param username 用户名
+     * @param password 用户密码
+     */
+    public void loginPreCheck(String username, String password)
+    {
+        // 用户名或密码为空 错误
+        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password))
+        {
+            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
+            throw new UserNotExistsException();
+        }
+        // 密码如果不在指定范围内 错误
+        if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
+                || password.length() > UserConstants.PASSWORD_MAX_LENGTH)
+        {
+            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
+            throw new UserPasswordNotMatchException();
+        }
+        // 用户名不在指定范围内 错误
+        if (username.length() < UserConstants.USERNAME_MIN_LENGTH
+                || username.length() > UserConstants.USERNAME_MAX_LENGTH)
+        {
+            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
+            throw new UserPasswordNotMatchException();
+        }
+        // IP黑名单校验
+        String blackStr = configService.selectConfigByKey("sys.login.blackIPList");
+        if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr()))
+        {
+            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("login.blocked")));
+            throw new BlackListException();
+        }
+    }
+
+    /**
+     * 记录登录信息
+     *
+     * @param userId 用户ID
+     */
+    public void recordLoginInfo(Long userId)
+    {
+        SysUser sysUser = new SysUser();
+        sysUser.setUserId(userId);
+        sysUser.setLoginIp(IpUtils.getIpAddr());
+        sysUser.setLoginDate(DateUtils.getNowDate());
+        userService.updateUserProfile(sysUser);
+    }
+
+
+    /**
+     * 单点登录验证
+     *
+     * @param username 用户名
+     * @return 结果
+     */
+    public String authSingleSignIn(String username)
+    {
+        if (StringUtils.isEmpty(username))
+        {
+            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
+            throw new UserNotExistsException();
+        }
+        SysUser sysUser = userService.selectUserByUserName(username);
+        // 登录前置校验
+        loginPreCheck(username, "admin123");
+
+        // 用户验证
+        Authentication authentication = null;
+        try
+        {
+            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, "admin123");
+            AuthenticationContextHolder.setContext(authenticationToken);
+            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
+            authenticationToken.setDetails(authentication.getPrincipal());
+            authentication = authenticationManager.authenticate(authenticationToken);
+        }
+        catch (Exception e)
+        {
+            if (e instanceof BadCredentialsException)
+            {
+                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
+                throw new UserPasswordNotMatchException();
+            }
+            else
+            {
+                AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
+                throw new ServiceException(e.getMessage());
+            }
+        }
+        finally
+        {
+            AuthenticationContextHolder.clearContext();
+        }
+        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
+        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
+
+        loginUser.setAuthType("password");
+        recordLoginInfo(loginUser.getUserId());
+        // 生成token
+        return tokenService.createToken(loginUser);
+    }
+
+    /**
+     * 单点登录验证
+     *
+     * @param username 用户名
+     * @return 结果
+     */
+    public Map<String,Object> authSingleSignIn2(String accessToken, String userId)
+    {
+        if (StringUtils.isEmpty(accessToken))
+        {
+            AsyncManager.me().execute(AsyncFactory.recordLogininfor(accessToken, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
+            throw new UserNotExistsException();
+        }
+
+        // 用户验证
+        Authentication authentication = null;
+        try
+        {
+            authentication =  dingAuthenticationProvider.authenticate(new DingToken(accessToken, userId));
+        }
+        catch (Exception e)
+        {
+            if (e instanceof BadCredentialsException)
+            {
+                AsyncManager.me().execute(AsyncFactory.recordLogininfor(accessToken, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
+                throw new UserPasswordNotMatchException();
+            }
+            else
+            {
+                AsyncManager.me().execute(AsyncFactory.recordLogininfor(accessToken, Constants.LOGIN_FAIL, e.getMessage()));
+                throw new ServiceException(e.getMessage());
+            }
+        }
+        finally
+        {
+            AuthenticationContextHolder.clearContext();
+        }
+        AsyncManager.me().execute(AsyncFactory.recordLogininfor(accessToken, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
+        LoginUser loginUser = (LoginUser) authentication.getDetails();
+        recordLoginInfo(loginUser.getUserId());
+        Map <String,Object> result = new HashMap<>();
+        result.put("token", tokenService.createToken(loginUser));
+        result.put("authentication", authentication);
+        // 生成token
+        return result;
+    }
+
+}

+ 66 - 66
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java

@@ -1,66 +1,66 @@
-package com.ruoyi.framework.web.service;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.core.userdetails.UserDetails;
-import org.springframework.security.core.userdetails.UserDetailsService;
-import org.springframework.security.core.userdetails.UsernameNotFoundException;
-import org.springframework.stereotype.Service;
-import com.ruoyi.common.core.domain.entity.SysUser;
-import com.ruoyi.common.core.domain.model.LoginUser;
-import com.ruoyi.common.enums.UserStatus;
-import com.ruoyi.common.exception.ServiceException;
-import com.ruoyi.common.utils.MessageUtils;
-import com.ruoyi.common.utils.StringUtils;
-import com.ruoyi.system.service.ISysUserService;
-
-/**
- * 用户验证处理
- *
- * @author ruoyi
- */
-@Service
-public class UserDetailsServiceImpl implements UserDetailsService
-{
-    private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class);
-
-    @Autowired
-    private ISysUserService userService;
-    
-    @Autowired
-    private SysPasswordService passwordService;
-
-    @Autowired
-    private SysPermissionService permissionService;
-
-    @Override
-    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
-    {
-        SysUser user = userService.selectUserByUserName(username);
-        if (StringUtils.isNull(user))
-        {
-            log.info("登录用户:{} 不存在.", username);
-            throw new ServiceException(MessageUtils.message("user.not.exists"));
-        }
-        else if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
-        {
-            log.info("登录用户:{} 已被删除.", username);
-            throw new ServiceException(MessageUtils.message("user.password.delete"));
-        }
-        else if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
-        {
-            log.info("登录用户:{} 已被停用.", username);
-            throw new ServiceException(MessageUtils.message("user.blocked"));
-        }
-
-        passwordService.validate(user);
-
-        return createLoginUser(user);
-    }
-
-    public UserDetails createLoginUser(SysUser user)
-    {
-        return new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user));
-    }
-}
+package com.ruoyi.framework.web.service;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.enums.UserStatus;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.service.ISysUserService;
+
+/**
+ * 用户验证处理
+ *
+ * @author ruoyi
+ */
+@Service("")
+public class UserDetailsServiceImpl implements UserDetailsService
+{
+    private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class);
+
+    @Autowired
+    private ISysUserService userService;
+    
+    @Autowired
+    private SysPasswordService passwordService;
+
+    @Autowired
+    private SysPermissionService permissionService;
+
+    @Override
+    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
+    {
+        SysUser user = userService.selectUserByUserName(username);
+        if (StringUtils.isNull(user))
+        {
+            log.info("登录用户:{} 不存在.", username);
+            throw new ServiceException(MessageUtils.message("user.not.exists"));
+        }
+        else if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
+        {
+            log.info("登录用户:{} 已被删除.", username);
+            throw new ServiceException(MessageUtils.message("user.password.delete"));
+        }
+        else if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
+        {
+            log.info("登录用户:{} 已被停用.", username);
+            throw new ServiceException(MessageUtils.message("user.blocked"));
+        }
+
+        return createLoginUser(user);
+    }
+
+    public UserDetails createLoginUser(SysUser user)
+    {
+        return new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user));
+    }
+
+
+}

+ 4 - 0
ruoyi-system/src/main/java/com/ruoyi/system/domain/resume/Resume.java

@@ -146,8 +146,12 @@ public class Resume {
 
     private Boolean isEnabled;// 是否可用
 
+    private String corpId;//钉钉用户所属的组织的企业corpId
+
     private Long primaryScreeningUserId;// 简历初筛人员
 
     private ResumeFile resumeFile;//简历附件
 
+
+
 }

+ 1 - 1
ruoyi-system/src/main/java/com/ruoyi/system/mapper/resume/ResumeMapper.java

@@ -17,7 +17,7 @@ public interface ResumeMapper
      * @param resumeId 简历管理主键
      * @return 简历管理
      */
-    public Resume selectResumeByResumeId(Long resumeId);
+    public Resume selectResumeByResumeId(Long resumeId,String corpId);
 
     /**
      * 查询简历管理列表

+ 1 - 1
ruoyi-system/src/main/java/com/ruoyi/system/service/resume/IResumeService.java

@@ -18,7 +18,7 @@ public interface IResumeService
      * @param resumeId 简历管理主键
      * @return 简历管理
      */
-    public Resume selectResumeByResumeId(Long resumeId);
+    public Resume selectResumeByResumeId(Long resumeId,String corpId);
 
     /**
      * 查询简历管理列表

+ 2 - 2
ruoyi-system/src/main/java/com/ruoyi/system/service/resume/impl/ResumeServiceImpl.java

@@ -42,9 +42,9 @@ public class ResumeServiceImpl implements IResumeService
      * @return 简历管理
      */
     @Override
-    public Resume selectResumeByResumeId(Long resumeId)
+    public Resume selectResumeByResumeId(Long resumeId,String corpId)
     {
-        Resume resume = resumeMapper.selectResumeByResumeId(resumeId);
+        Resume resume = resumeMapper.selectResumeByResumeId(resumeId,corpId);
         if(!Objects.isNull(resume)){
             //简历附件处理
             ResumeFile resumeFile = new ResumeFile();

+ 8 - 1
ruoyi-system/src/main/resources/mapper/resume/ResumeMapper.xml

@@ -53,6 +53,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="selfEvaluation"    column="self_evaluation"    />
         <result property="exceptedSalary"    column="excepted_salary"    />
         <result property="isEnabled"    column="is_enabled"    />
+        <result property="corpId"    column="corp_id"    />
     </resultMap>
 
     <sql id="selectResumeVo">
@@ -105,6 +106,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             r.self_evaluation,
             r.excepted_salary,
             r.is_enabled,
+            r.corp_id,
             su.user_name AS createUserName
         FROM
             resume r
@@ -164,13 +166,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="selfEvaluation != null  and selfEvaluation != ''"> and r.self_evaluation = #{selfEvaluation}</if>
             <if test="exceptedSalary != null  and exceptedSalary != ''"> and r.excepted_salary = #{exceptedSalary}</if>
             <if test="isEnabled != null "> and r.is_enabled = #{isEnabled}</if>
+            <if test="corpId != null  and corpId != '' "> and r.corp_id = #{corpId}</if>
         </where>
         order by r.create_date desc
     </select>
-    
+
     <select id="selectResumeByResumeId" parameterType="Long" resultMap="ResumeResult">
         <include refid="selectResumeVo"/>
         where r.resume_id = #{resumeId}
+          and r.corp_id = #{corpId}
     </select>
         
     <insert id="insertResume" parameterType="Resume" useGeneratedKeys="true" keyProperty="resumeId">
@@ -223,6 +227,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="selfEvaluation != null">self_evaluation,</if>
             <if test="exceptedSalary != null">excepted_salary,</if>
             <if test="isEnabled != null">is_enabled,</if>
+            <if test="corpId != null">corp_id,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="resumeName != null">#{resumeName},</if>
@@ -272,6 +277,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="selfEvaluation != null">#{selfEvaluation},</if>
             <if test="exceptedSalary != null">#{exceptedSalary},</if>
             <if test="isEnabled != null">#{isEnabled},</if>
+            <if test="corpId != null">#{corpId},</if>
          </trim>
     </insert>
 
@@ -325,6 +331,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="selfEvaluation != null">self_evaluation = #{selfEvaluation},</if>
             <if test="exceptedSalary != null">excepted_salary = #{exceptedSalary},</if>
             <if test="isEnabled != null">is_enabled = #{isEnabled},</if>
+            <if test="corpId != null">corp_id = #{corpId},</if>
         </trim>
         where resume_id = #{resumeId}
     </update>