Compare commits

..

29 Commits

Author SHA1 Message Date
曾文豪
a1c75d010b publish 2.0.0.rc21 2024-08-09 17:20:56 +08:00
曾文豪
9b6b3af33e publish 2.0.0.rc20 2024-08-08 16:20:34 +08:00
曾文豪
91833a44bb feat:增加RoleIgnore 2024-08-08 16:20:05 +08:00
曾文豪
8dc8709499 perf:代码结构调整 2024-08-08 16:16:21 +08:00
曾文豪
b34d9d6242 publish 2.0.0.rc19 2024-08-08 11:27:50 +08:00
曾文豪
2c9519a35e publish 2.0.0.rc18 2024-08-08 11:11:40 +08:00
曾文豪
f5dfce08ed publish 2.0.0.rc17 2024-08-08 09:24:00 +08:00
曾文豪
5d4e97b206 feat:增加权限校验 2024-08-08 09:23:30 +08:00
曾文豪
82d3f471f9 perf:TokenBean移除无用的属性 2024-08-07 23:43:57 +08:00
曾文豪
316909dd61 perf:调整授权缓存 2024-08-07 23:13:55 +08:00
曾文豪
5e308be3ba publish 2.0.0.rc16 2024-08-07 22:16:12 +08:00
曾文豪
ba80cebc45 feat:提交角色授权 2024-08-07 22:15:40 +08:00
曾文豪
0f5cdb49c0 feat:增加权限校验 2024-08-07 19:02:54 +08:00
曾文豪
1ee4b4af30 perf:请求时将通过getCurrentUserName()方法返回的对象检验用户是否非法 2024-08-07 14:09:28 +08:00
曾文豪
bb38428708 publish 2.0.0.rc15 2024-08-05 19:11:17 +08:00
曾文豪
a22467d4f1 publish 2.0.0.rc14 2024-08-05 14:59:55 +08:00
曾文豪
ad90c83cf7 perf:调整消息日志相关代码 2024-08-05 14:46:54 +08:00
曾文豪
cdae6a9868 publish 2.0.0.rc13 2024-08-05 14:19:06 +08:00
曾文豪
be08001f3f publish 2.0.0.rc13 2024-08-05 14:18:50 +08:00
曾文豪
333d283e24 perf:移除hutool的http模块,使用okhttp3 2024-07-30 13:39:45 +08:00
曾文豪
450d1fb869 publish 2.0.0.rc12 2024-07-29 14:28:21 +08:00
曾文豪
1412782327 publish 2.0.0.rc11 2024-07-29 10:31:03 +08:00
曾文豪
6127cd50a9 publish 2.0.0.rc10 2024-07-29 09:53:44 +08:00
曾文豪
19f4d0395e publish 2.0.0.rc9 2024-07-29 09:42:53 +08:00
曾文豪
d52edbb23c perf:钉钉对接调整 2024-07-26 16:12:29 +08:00
曾文豪
6c6d713c01 publish 2.0.0.rc8 2024-07-25 17:35:51 +08:00
曾文豪
8ea34c3ee0 perf:移除TimedCacheService、TimedCacheHelper,新增TsCacheService,同时实现了内存缓存、Redis缓存 2024-07-25 17:35:01 +08:00
曾文豪
d357fa7c85 publish 2.0.0.rc7 2024-07-12 11:17:04 +08:00
曾文豪
6332d1486b publish 2.0.0.rc6 2024-07-12 11:16:46 +08:00
95 changed files with 2360 additions and 1277 deletions

22
pom.xml
View File

@@ -6,7 +6,7 @@
<groupId>com.tiesheng.springboot-parent</groupId> <groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId> <artifactId>springboot-parent</artifactId>
<version>2.0.0.rc6</version> <version>2.0.0.rc21</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<name>springboot-parent</name> <name>springboot-parent</name>
<description>杭州铁晟科技有限公司基础依赖</description> <description>杭州铁晟科技有限公司基础依赖</description>
@@ -58,61 +58,61 @@
<dependency> <dependency>
<groupId>com.tiesheng.springboot-parent</groupId> <groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-database</artifactId> <artifactId>springboot-database</artifactId>
<version>2.0.0.rc6</version> <version>2.0.0.rc21</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.tiesheng.springboot-parent</groupId> <groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-login</artifactId> <artifactId>springboot-login</artifactId>
<version>2.0.0.rc6</version> <version>2.0.0.rc21</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.tiesheng.springboot-parent</groupId> <groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-web</artifactId> <artifactId>springboot-web</artifactId>
<version>2.0.0.rc6</version> <version>2.0.0.rc21</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.tiesheng.springboot-parent</groupId> <groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-util</artifactId> <artifactId>springboot-util</artifactId>
<version>2.0.0.rc6</version> <version>2.0.0.rc21</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.tiesheng.springboot-parent</groupId> <groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-platform</artifactId> <artifactId>springboot-platform</artifactId>
<version>2.0.0.rc6</version> <version>2.0.0.rc21</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.tiesheng.springboot-parent</groupId> <groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-message</artifactId> <artifactId>springboot-message</artifactId>
<version>2.0.0.rc6</version> <version>2.0.0.rc21</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.tiesheng.springboot-parent</groupId> <groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-encrypt</artifactId> <artifactId>springboot-encrypt</artifactId>
<version>2.0.0.rc6</version> <version>2.0.0.rc21</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.tiesheng.springboot-parent</groupId> <groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-role</artifactId> <artifactId>springboot-role</artifactId>
<version>2.0.0.rc6</version> <version>2.0.0.rc21</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.tiesheng.springboot-parent</groupId> <groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-annotation</artifactId> <artifactId>springboot-annotation</artifactId>
<version>2.0.0.rc6</version> <version>2.0.0.rc21</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.tiesheng.springboot-parent</groupId> <groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-poi</artifactId> <artifactId>springboot-poi</artifactId>
<version>2.0.0.rc6</version> <version>2.0.0.rc21</version>
</dependency> </dependency>
<dependency> <dependency>

View File

@@ -6,11 +6,11 @@
<parent> <parent>
<groupId>com.tiesheng.springboot-parent</groupId> <groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId> <artifactId>springboot-parent</artifactId>
<version>2.0.0.rc6</version> <version>2.0.0.rc21</version>
</parent> </parent>
<artifactId>springboot-ademo</artifactId> <artifactId>springboot-ademo</artifactId>
<version>2.0.0.rc6</version> <version>2.0.0.rc21</version>
<properties> <properties>
<maven.compiler.source>8</maven.compiler.source> <maven.compiler.source>8</maven.compiler.source>
@@ -36,6 +36,12 @@
<artifactId>easyexcel</artifactId> <artifactId>easyexcel</artifactId>
</dependency> </dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.7.0</version>
</dependency>
</dependencies> </dependencies>
<repositories> <repositories>

View File

@@ -1,11 +1,12 @@
package com.tiesheng.demo.config; package com.tiesheng.demo.config;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.tiesheng.web.pojos.RequestUserInfo; import com.tiesheng.login.pojos.RequestUserInfo;
import com.tiesheng.web.pojos.dao.CorePlatformUnique; import com.tiesheng.login.pojos.dao.CorePlatformUnique;
import com.tiesheng.web.service.TieshengWebConfigurer; import com.tiesheng.login.service.TsLoginConfigurer;
import com.tiesheng.util.pojos.TokenBean;
import com.tiesheng.util.config.GlobalConfig; import com.tiesheng.util.config.GlobalConfig;
import com.tiesheng.util.pojos.TokenBean;
import com.tiesheng.web.service.TieshengWebConfigurer;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -13,24 +14,31 @@ import javax.servlet.http.HttpServletResponse;
import java.util.Objects; import java.util.Objects;
@Component @Component
public class DemoWebConfigurer implements TieshengWebConfigurer { public class DemoWebConfigurer implements TieshengWebConfigurer, TsLoginConfigurer {
@Autowired @Autowired
GlobalConfig globalConfig; GlobalConfig globalConfig;
@Override @Override
public RequestUserInfo getCurrentUserName(TokenBean tokenBean) { public RequestUserInfo getCurrentUserName(TokenBean tokenBean) {
RequestUserInfo info = new RequestUserInfo(); RequestUserInfo info = new RequestUserInfo();
info.setId("1"); if (Objects.equals(tokenBean.getId(), "1")) {
info.setName("test"); return info;
}
return info; return info;
} }
@Override
public TokenBean login(CorePlatformUnique platformUnique) { public TokenBean login(CorePlatformUnique platformUnique) {
TokenBean tokenBean = null; TokenBean tokenBean = null;
if (!StrUtil.isEmpty(platformUnique.getUserId())) { if (!StrUtil.isEmpty(platformUnique.getUserId())) {
tokenBean = new TokenBean(platformUnique.getUserId(), "", globalConfig.getService()); tokenBean = new TokenBean(platformUnique.getUserId(), "super");
} else if (Objects.equals(platformUnique.getUniqueId(), "1110290049")) {
tokenBean = new TokenBean("1", "super");
}
if (tokenBean != null) {
tokenBean.setExtra("1110290049");
} }
return tokenBean; return tokenBean;
@@ -39,13 +47,11 @@ public class DemoWebConfigurer implements TieshengWebConfigurer {
@Override @Override
public void redirect(TokenBean bean, String to, String extra, HttpServletResponse response) { public void redirect(TokenBean bean, String to, String extra, HttpServletResponse response) {
// 默认跳转到mobile
to = StrUtil.emptyToDefault(to, "static/mobile");
bean.setEnvironmentType(to);
if (Objects.equals(bean.getEnvironmentType(), "static/mobile")) {
globalConfig.redirect("static/mobile", "/?token=" + bean.toToken(), response);
}
} }
@Override
public TsLoginConfigurer configureLogin() {
return this;
}
} }

View File

@@ -1,15 +0,0 @@
package com.tiesheng.demo.config;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Component
public class DemoWebMvcConfigurer implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/mobile/**").addResourceLocations("classpath:/mobile/0.0.13/");
}
}

View File

@@ -2,41 +2,45 @@ package com.tiesheng.demo.controller;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.TimeInterval; import cn.hutool.core.date.TimeInterval;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.LogFactory; import cn.hutool.log.LogFactory;
import cn.hutool.poi.excel.ExcelUtil; import cn.hutool.poi.excel.ExcelUtil;
import com.alibaba.excel.EasyExcel; import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext; import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.read.listener.ReadListener; import com.alibaba.excel.read.listener.ReadListener;
import com.tiesheng.annotation.role.RoleAuthority;
import com.tiesheng.annotation.token.TokenIgnore; import com.tiesheng.annotation.token.TokenIgnore;
import com.tiesheng.util.pojos.TokenBean;
import com.tiesheng.web.service.CoreLogService;
import com.tiesheng.web.service.CoreMessageService;
import com.tiesheng.web.util.ProcessImportConsumer;
import com.tiesheng.database.config.DbBackupConfig; import com.tiesheng.database.config.DbBackupConfig;
import com.tiesheng.demo.pojos.PoiBean; import com.tiesheng.demo.pojos.PoiBean;
import com.tiesheng.demo.pojos.TestFile; import com.tiesheng.demo.pojos.TestFile;
import com.tiesheng.util.config.TsTokenConfig; import com.tiesheng.platform.config.ding.PlatformDingConfig;
import com.tiesheng.message.pojos.MessageReqResp; import com.tiesheng.platform.config.ding.bean.DingUserInfo;
import com.tiesheng.message.pojos.UserChannel;
import com.tiesheng.util.config.EncryptConfig; import com.tiesheng.util.config.EncryptConfig;
import com.tiesheng.util.config.GlobalConfig; import com.tiesheng.util.config.GlobalConfig;
import com.tiesheng.util.config.Ip2regionConfig; import com.tiesheng.util.config.Ip2regionConfig;
import com.tiesheng.util.config.TsTokenConfig;
import com.tiesheng.util.pojos.ApiResp; import com.tiesheng.util.pojos.ApiResp;
import com.tiesheng.util.pojos.FileUploadPath; import com.tiesheng.util.pojos.FileUploadPath;
import com.tiesheng.util.service.TsCacheService;
import com.tiesheng.web.service.CoreLogService;
import com.tiesheng.web.util.ProcessImportConsumer;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.File; import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.Consumer;
/** /**
* @author hao * @author hao
*/ */
@RestController @RestController
@RequestMapping("/test") @RequestMapping("/test")
@RoleAuthority(value = "test", group = "test")
public class TestController { public class TestController {
@Autowired @Autowired
@@ -48,11 +52,13 @@ public class TestController {
@Autowired @Autowired
EncryptConfig encryptConfig; EncryptConfig encryptConfig;
@Autowired @Autowired
CoreMessageService coreMessageService;
@Autowired
CoreLogService coreLogService; CoreLogService coreLogService;
@Autowired @Autowired
DbBackupConfig dbBackupConfig; DbBackupConfig dbBackupConfig;
@Autowired
TsCacheService tsCacheService;
@Autowired
PlatformDingConfig platformDingConfig;
@RequestMapping("/index") @RequestMapping("/index")
@@ -63,45 +69,58 @@ public class TestController {
@RequestMapping("/redirect") @RequestMapping("/redirect")
@TokenIgnore @TokenIgnore
public void redirect(HttpServletResponse response) { @RoleAuthority("redirect")
public ApiResp<String> redirect(HttpServletResponse response) {
ArrayList<String> strings = CollUtil.newArrayList("11111", "22222"); // ArrayList<String> strings = CollUtil.newArrayList("11111", "22222");
coreLogService.addProcess("fdfd", strings, new ProcessImportConsumer<String>() { // coreLogService.addProcess("fdfd", strings, new ProcessImportConsumer<String>() {
@Override // @Override
public int accept(List<String> list) { // public int accept(List<String> list) {
LogFactory.get().info("list: " + list.size()); // LogFactory.get().info("list: " + list.size());
return 0; // return 0;
} // }
//
@Override // @Override
public String getFailFile() { // public String getFailFile() {
LogFactory.get().info("getFailFile: " + strings.size()); // LogFactory.get().info("getFailFile: " + strings.size());
return null; // return null;
} // }
}); // });
//
LogFactory.get().info("strings: " + strings.size()); // LogFactory.get().info("strings: " + strings.size());
// tsTokenConfig.validToken("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2NzYwMDY4NzUsImlkIjoiMSIsImVudmlyb25tZW50VHlwZSI6Im1vYmlsZSIsInNlcnZpY2UiOiJjb250ZXN0LXJlc2VydmUiLCJleHRyYSI6IiJ9.nsfxEFpCNHC7eNCS5DJXdu1VDdnHrTjSfgrozND70Lc", true); // tsTokenConfig.validToken("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2NzYwMDY4NzUsImlkIjoiMSIsImVudmlyb25tZW50VHlwZSI6Im1vYmlsZSIsInNlcnZpY2UiOiJjb250ZXN0LXJlc2VydmUiLCJleHRyYSI6IiJ9.nsfxEFpCNHC7eNCS5DJXdu1VDdnHrTjSfgrozND70Lc", true);
globalConfig.redirect("mobile", "/test", response); // globalConfig.redirect("mobile", "/test", response);
return ApiResp.respOK("");
} }
@GetMapping("/send") @GetMapping("/send")
@TokenIgnore @TokenIgnore
public ApiResp<MessageReqResp> sendMessage() { public ApiResp<String> sendMessage() {
MessageReqResp reqResp = coreMessageService.send(new UserChannel("13567116463", "sms"), // MessageReqResp reqResp = coreMessageService.send(new UserChannel("13567116463", "sms"),
JSONUtil.createObj().putOpt("action", "sms-visitor-invite")); // JSONUtil.createObj().putOpt("action", "sms-visitor-invite"));
return ApiResp.respOK(reqResp); return ApiResp.respOK(null);
} }
@RequestMapping("/export") @RequestMapping("/export")
@TokenIgnore
public ApiResp<String> export() { public ApiResp<String> export() {
// tsCacheService.put("fdfhdfd", "fdfdfdfd");
// String s = tsCacheService.get("fdfhdfd");
// LogFactory.get().info("export: " + s);
platformDingConfig.syncDeptUser("", null, new Consumer<DingUserInfo>() {
@Override
public void accept(DingUserInfo dingUserInfo) {
}
});
// List<TestFile> list = new ArrayList<>(); // List<TestFile> list = new ArrayList<>();
// list.add(new TestFile("11111")); // list.add(new TestFile("11111"));
// list.add(new TestFile("22222")); // list.add(new TestFile("22222"));
@@ -122,14 +141,13 @@ public class TestController {
} }
@RequestMapping("searchIP") @PostMapping("searchIP")
@TokenIgnore @TokenIgnore
public ApiResp<String> searchIp() { public ApiResp<String> searchIp() {
String search = ip2regionConfig.search("127.0.0.1"); String search = ip2regionConfig.search("127.0.0.1");
return ApiResp.respOK(search); return ApiResp.respOK(search);
} }
@RequestMapping("desensitize") @RequestMapping("desensitize")
@TokenIgnore @TokenIgnore
public ApiResp<List<TestFile>> desensitize() { public ApiResp<List<TestFile>> desensitize() {

View File

@@ -4,7 +4,7 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import com.tiesheng.message.config.aliyun.AliyunSmsHandler; import com.tiesheng.message.config.aliyun.AliyunSmsHandler;
import com.tiesheng.message.pojos.AliyunTempParam; import com.tiesheng.message.config.aliyun.AliyunTempParam;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.Objects; import java.util.Objects;

View File

@@ -7,8 +7,16 @@ spring:
url: jdbc:mysql://47.96.30.85:3306/com_tiesheng_web?useSSL=false&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&queryTimeout=5400&allowMultiQueries=true&serverTimezone=GMT%2B8 url: jdbc:mysql://47.96.30.85:3306/com_tiesheng_web?useSSL=false&useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&queryTimeout=5400&allowMultiQueries=true&serverTimezone=GMT%2B8
username: com_tiesheng_web username: com_tiesheng_web
password: 4Xo$XheGFc password: 4Xo$XheGFc
# redis:
# url: redis://kyF0zUL3011111@47.96.30.85:6234
platform: platform:
ding:
global:
corpId: dingebe664cb3baf3a52a39a90f97fcb1e09
agentId: 2474444028
appKey: dingyvf1niiajfaajyo5
appSecret: y6SGZ4fvPbdbj4RVbDWLeMBkGgplaOdnTA_9wN5TDdOV_Y47alYc1LDlIHjsBJE1
wxmp: wxmp:
global: global:
app-id: wxa0343fe519824651 app-id: wxa0343fe519824651
@@ -18,11 +26,12 @@ tiesheng:
token: token:
test-map: test-map:
"1111": "1111":
id: "1111" id: "1"
role-id: "student_bks" role-id: "super"
global: global:
version: 2 version: 2
host: http://localhost:8100 host: http://localhost:8100
service: demo
aliyun: aliyun:
access-key-id: LTAI5tJtbgBCnTY5eS4SmrTf access-key-id: LTAI5tJtbgBCnTY5eS4SmrTf
access-key-secret: JIHqpRUFffCHhXaJEVvWN31WcexWqG access-key-secret: JIHqpRUFffCHhXaJEVvWN31WcexWqG

View File

@@ -6,7 +6,7 @@
<parent> <parent>
<groupId>com.tiesheng.springboot-parent</groupId> <groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId> <artifactId>springboot-parent</artifactId>
<version>2.0.0.rc6</version> <version>2.0.0.rc21</version>
</parent> </parent>
<artifactId>springboot-annotation</artifactId> <artifactId>springboot-annotation</artifactId>

View File

@@ -0,0 +1,33 @@
package com.tiesheng.annotation.role;
import java.lang.annotation.*;
@Target({ElementType.METHOD, ElementType.TYPE})
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface RoleAuthority {
/**
* 编号
*
* @return
*/
String value();
/**
* 平台类型
*
* @return
*/
String platform() default "web";
/**
* 分组
*
* @return
*/
String[] group() default {};
}

View File

@@ -0,0 +1,9 @@
package com.tiesheng.annotation.role;
import java.lang.annotation.*;
@Target({ElementType.METHOD})
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface RoleIgnore {
}

View File

@@ -6,7 +6,7 @@
<parent> <parent>
<groupId>com.tiesheng.springboot-parent</groupId> <groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId> <artifactId>springboot-parent</artifactId>
<version>2.0.0.rc6</version> <version>2.0.0.rc21</version>
</parent> </parent>
<artifactId>springboot-database</artifactId> <artifactId>springboot-database</artifactId>

View File

@@ -6,7 +6,7 @@
<parent> <parent>
<groupId>com.tiesheng.springboot-parent</groupId> <groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId> <artifactId>springboot-parent</artifactId>
<version>2.0.0.rc6</version> <version>2.0.0.rc21</version>
</parent> </parent>
<artifactId>springboot-encrypt</artifactId> <artifactId>springboot-encrypt</artifactId>

View File

@@ -6,7 +6,7 @@
<parent> <parent>
<groupId>com.tiesheng.springboot-parent</groupId> <groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId> <artifactId>springboot-parent</artifactId>
<version>2.0.0.rc6</version> <version>2.0.0.rc21</version>
</parent> </parent>
<artifactId>springboot-login</artifactId> <artifactId>springboot-login</artifactId>

View File

@@ -1,16 +0,0 @@
package com.tiesheng.login;
import com.tiesheng.platform.PlatformAutoConfigurer;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
/**
* @author hao
*/
@ComponentScan({
"com.tiesheng.login.**.*",
})
@Import(PlatformAutoConfigurer.class)
public class LoginAutoConfigurer {
}

View File

@@ -3,8 +3,12 @@ package com.tiesheng.login.config;
import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.tiesheng.annotation.token.TokenIgnore; import com.tiesheng.annotation.token.TokenIgnore;
import com.tiesheng.login.pojos.RequestUserInfo;
import com.tiesheng.login.service.TsLoginConfigurer;
import com.tiesheng.util.config.TsTokenConfig; import com.tiesheng.util.config.TsTokenConfig;
import com.tiesheng.util.exception.ApiException;
import com.tiesheng.util.pojos.TokenBean; import com.tiesheng.util.pojos.TokenBean;
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.MethodParameter; import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory; import org.springframework.web.bind.support.WebDataBinderFactory;
@@ -28,6 +32,8 @@ public class TokenWebMvcConfigurer implements WebMvcConfigurer {
@Resource @Resource
TsTokenConfig tsTokenConfig; TsTokenConfig tsTokenConfig;
@Resource
TsLoginConfigurer tsLoginConfigurer;
@Override @Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) { public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
@@ -82,6 +88,10 @@ public class TokenWebMvcConfigurer implements WebMvcConfigurer {
// 过滤不要需要验证的接口(注解) // 过滤不要需要验证的接口(注解)
HandlerMethod handlerMethod = (HandlerMethod) handler; HandlerMethod handlerMethod = (HandlerMethod) handler;
if (handlerMethod.getBeanType() == BasicErrorController.class) {
return true;
}
TokenIgnore annotation = handlerMethod.getBeanType().getAnnotation(TokenIgnore.class); TokenIgnore annotation = handlerMethod.getBeanType().getAnnotation(TokenIgnore.class);
if (annotation != null) { if (annotation != null) {
return true; return true;
@@ -91,8 +101,14 @@ public class TokenWebMvcConfigurer implements WebMvcConfigurer {
return true; return true;
} }
// token验证 // 验证TOKEN是否存在
tsTokenConfig.validToken(request, true); TokenBean tokenBean = tsTokenConfig.validToken(request, true);
// 验证用户是否存在
RequestUserInfo cachedUserInfo = tsLoginConfigurer.getCachedUserInfo(tokenBean);
if (cachedUserInfo == null) {
throw new ApiException("非法TOKEN请重新登录");
}
return true; return true;
} }

View File

@@ -6,13 +6,11 @@ import cn.hutool.core.util.URLUtil;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.tiesheng.annotation.operation.OperationIgnore; import com.tiesheng.annotation.operation.OperationIgnore;
import com.tiesheng.annotation.token.TokenIgnore; import com.tiesheng.annotation.token.TokenIgnore;
import com.tiesheng.util.config.TsTokenConfig;
import com.tiesheng.util.pojos.TokenBean;
import com.tiesheng.login.pojos.CodeExtraDTO; import com.tiesheng.login.pojos.CodeExtraDTO;
import com.tiesheng.login.pojos.DoLoginInfo; import com.tiesheng.login.pojos.DoLoginInfo;
import com.tiesheng.login.pojos.UniqueIndexDTO; import com.tiesheng.login.pojos.UniqueIndexDTO;
import com.tiesheng.login.pojos.WxminiLoginVo; import com.tiesheng.login.pojos.WxminiLoginVo;
import com.tiesheng.login.service.TieshengLoginConfigurer; import com.tiesheng.login.service.CorePlatformUniqueService;
import com.tiesheng.platform.config.ding.PlatformDingConfig; import com.tiesheng.platform.config.ding.PlatformDingConfig;
import com.tiesheng.platform.config.ding.bean.DingJsapiSignature; import com.tiesheng.platform.config.ding.bean.DingJsapiSignature;
import com.tiesheng.platform.config.ding.bean.DingUserInfo; import com.tiesheng.platform.config.ding.bean.DingUserInfo;
@@ -23,8 +21,10 @@ import com.tiesheng.platform.config.wxmp.bean.WxConfigBean;
import com.tiesheng.platform.config.wxmp.bean.WxJsapiSignature; import com.tiesheng.platform.config.wxmp.bean.WxJsapiSignature;
import com.tiesheng.platform.config.wxmp.bean.WxUserInfo; import com.tiesheng.platform.config.wxmp.bean.WxUserInfo;
import com.tiesheng.util.config.GlobalConfig; import com.tiesheng.util.config.GlobalConfig;
import com.tiesheng.util.config.TsTokenConfig;
import com.tiesheng.util.exception.ApiException; import com.tiesheng.util.exception.ApiException;
import com.tiesheng.util.pojos.ApiResp; import com.tiesheng.util.pojos.ApiResp;
import com.tiesheng.util.pojos.TokenBean;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@@ -49,7 +49,7 @@ public class LoginController {
@Autowired @Autowired
PlatformWxminiConfig platformWxminiConfig; PlatformWxminiConfig platformWxminiConfig;
@Autowired @Autowired
TieshengLoginConfigurer tieshengLoginConfigurer; CorePlatformUniqueService corePlatformUniqueService;
@Autowired @Autowired
GlobalConfig globalConfig; GlobalConfig globalConfig;
@Autowired @Autowired
@@ -65,13 +65,13 @@ public class LoginController {
@OperationIgnore @OperationIgnore
public void uniqueIndex(UniqueIndexDTO dto, HttpServletResponse response) { public void uniqueIndex(UniqueIndexDTO dto, HttpServletResponse response) {
if (tsTokenConfig.isValidLoginSign() && !dto.validSign()) { if (tsTokenConfig.isValidLoginSign() && !dto.validSign()) {
tieshengLoginConfigurer.onSignError(response); corePlatformUniqueService.onSignError(response);
return; return;
} }
TokenBean tokenBean = tieshengLoginConfigurer.doLogin(new DoLoginInfo("web_unique_redirect", TokenBean tokenBean = corePlatformUniqueService.login(new DoLoginInfo("web_unique_redirect",
dto.getNo(), dto.getPlatform(), dto.getInfo())); dto.getNo(), dto.getPlatform(), dto.getInfo()));
tieshengLoginConfigurer.onLoginRedirect(tokenBean, dto.getTo(), dto.getExtra(), response); corePlatformUniqueService.redirect(tokenBean, dto.getTo(), dto.getExtra(), response);
} }
@@ -84,7 +84,7 @@ public class LoginController {
@PostMapping("/unique/index") @PostMapping("/unique/index")
@OperationIgnore @OperationIgnore
public ApiResp<String> uniqueIndex(@RequestBody UniqueIndexDTO dto) { public ApiResp<String> uniqueIndex(@RequestBody UniqueIndexDTO dto) {
TokenBean tokenBean = tieshengLoginConfigurer.doLogin(new DoLoginInfo("web_unique_index", TokenBean tokenBean = corePlatformUniqueService.login(new DoLoginInfo("web_unique_index",
dto.getNo(), dto.getPlatform(), dto.getInfo())); dto.getNo(), dto.getPlatform(), dto.getInfo()));
if (tokenBean == null || StrUtil.isEmpty(tokenBean.getId())) { if (tokenBean == null || StrUtil.isEmpty(tokenBean.getId())) {
throw new ApiException("登录失败"); throw new ApiException("登录失败");
@@ -134,9 +134,9 @@ public class LoginController {
public void dingOauth2(@PathVariable String service, CodeExtraDTO dto, HttpServletResponse response) { public void dingOauth2(@PathVariable String service, CodeExtraDTO dto, HttpServletResponse response) {
DingUserSimple userSimple = platformDingConfig.getUserIdByCode(service, dto.getCode()); DingUserSimple userSimple = platformDingConfig.getUserIdByCode(service, dto.getCode());
DingUserInfo dingUserInfo = platformDingConfig.topapiV2UserGet(service, userSimple.getUserid()); DingUserInfo dingUserInfo = platformDingConfig.topapiV2UserGet(service, userSimple.getUserid());
TokenBean tokenBean = tieshengLoginConfigurer.doLogin(new DoLoginInfo(dingUserInfo.getAppId(), TokenBean tokenBean = corePlatformUniqueService.login(new DoLoginInfo(dingUserInfo.getAppId(),
dingUserInfo.getUserid(), "ding", JSON.toJSONString(dingUserInfo))); dingUserInfo.getUserid(), "ding", JSON.toJSONString(dingUserInfo)));
tieshengLoginConfigurer.onLoginRedirect(tokenBean, dto.getTo(), dto.getExtra(), response); corePlatformUniqueService.redirect(tokenBean, dto.getTo(), dto.getExtra(), response);
} }
@@ -182,9 +182,9 @@ public class LoginController {
@OperationIgnore @OperationIgnore
public void wxmpOauth2(@PathVariable String service, CodeExtraDTO dto, HttpServletResponse response) { public void wxmpOauth2(@PathVariable String service, CodeExtraDTO dto, HttpServletResponse response) {
WxUserInfo wxUserInfo = platformWxmpConfig.getOAuth2AccessToken(service, dto.getCode()); WxUserInfo wxUserInfo = platformWxmpConfig.getOAuth2AccessToken(service, dto.getCode());
TokenBean tokenBean = tieshengLoginConfigurer.doLogin(new DoLoginInfo(wxUserInfo.getAppId(), TokenBean tokenBean = corePlatformUniqueService.login(new DoLoginInfo(wxUserInfo.getAppId(),
wxUserInfo.getOpenid(), "wxmp", JSON.toJSONString(wxUserInfo))); wxUserInfo.getOpenid(), "wxmp", JSON.toJSONString(wxUserInfo)));
tieshengLoginConfigurer.onLoginRedirect(tokenBean, dto.getTo(), dto.getExtra(), response); corePlatformUniqueService.redirect(tokenBean, dto.getTo(), dto.getExtra(), response);
} }
@@ -214,7 +214,7 @@ public class LoginController {
public ApiResp<WxminiLoginVo> wxminiIndex(@PathVariable String service, String code) { public ApiResp<WxminiLoginVo> wxminiIndex(@PathVariable String service, String code) {
String openid = platformWxminiConfig.jscode2session(service, code); String openid = platformWxminiConfig.jscode2session(service, code);
WxConfigBean configBean = platformWxminiConfig.getConfigBean(service); WxConfigBean configBean = platformWxminiConfig.getConfigBean(service);
TokenBean tokenBean = tieshengLoginConfigurer.doLogin(new DoLoginInfo(configBean.getAppId(), TokenBean tokenBean = corePlatformUniqueService.login(new DoLoginInfo(configBean.getAppId(),
openid, "wxmini", "{}")); openid, "wxmini", "{}"));
WxminiLoginVo loginVo = new WxminiLoginVo(); WxminiLoginVo loginVo = new WxminiLoginVo();

View File

@@ -1,7 +1,7 @@
package com.tiesheng.web.mapper; package com.tiesheng.login.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tiesheng.web.pojos.dao.CoreLogLogin; import com.tiesheng.login.pojos.dao.CoreLogLogin;
public interface CoreLogLoginMapper extends BaseMapper<CoreLogLogin> { public interface CoreLogLoginMapper extends BaseMapper<CoreLogLogin> {
} }

View File

@@ -1,7 +1,7 @@
package com.tiesheng.web.mapper; package com.tiesheng.login.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tiesheng.web.pojos.dao.CorePlatformUnique; import com.tiesheng.login.pojos.dao.CorePlatformUnique;
public interface CorePlatformUniqueMapper extends BaseMapper<CorePlatformUnique> { public interface CorePlatformUniqueMapper extends BaseMapper<CorePlatformUnique> {
} }

View File

@@ -1,4 +1,4 @@
package com.tiesheng.web.pojos; package com.tiesheng.login.pojos;
/** /**
* 当前token的数据 * 当前token的数据

View File

@@ -1,4 +1,4 @@
package com.tiesheng.web.pojos.dao; package com.tiesheng.login.pojos.dao;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;

View File

@@ -1,4 +1,4 @@
package com.tiesheng.web.pojos.dao; package com.tiesheng.login.pojos.dao;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;

View File

@@ -0,0 +1,113 @@
package com.tiesheng.login.service;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.tiesheng.login.mapper.CoreLogLoginMapper;
import com.tiesheng.login.mapper.CorePlatformUniqueMapper;
import com.tiesheng.login.pojos.DoLoginInfo;
import com.tiesheng.login.pojos.RequestUserInfo;
import com.tiesheng.login.pojos.dao.CoreLogLogin;
import com.tiesheng.login.pojos.dao.CorePlatformUnique;
import com.tiesheng.util.ServletKit;
import com.tiesheng.util.config.Ip2regionConfig;
import com.tiesheng.util.pojos.TokenBean;
import com.tiesheng.util.service.TsServiceBase;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;
/**
* @author hao
*/
@Service
public class CorePlatformUniqueService extends TsServiceBase<CorePlatformUniqueMapper, CorePlatformUnique> {
@Resource
CoreLogLoginMapper coreLogLoginMapper;
@Resource
Ip2regionConfig ip2regionConfig;
@Resource
TsLoginConfigurer tsLoginConfigurer;
@Transactional(rollbackFor = Exception.class)
public TokenBean login(DoLoginInfo loginInfo) {
CorePlatformUnique platformUnique = getOneByColumn("unique_id", loginInfo.getUnique());
if (platformUnique == null) {
platformUnique = new CorePlatformUnique();
platformUnique.setAppId(loginInfo.getAppId());
platformUnique.setUniqueId(loginInfo.getUnique());
}
platformUnique.setPlatform(loginInfo.getPlatform());
platformUnique.setInfo(loginInfo.getInfo());
saveOrUpdate(platformUnique);
String oldUserId = platformUnique.getUserId();
TokenBean tokenBean = tsLoginConfigurer.login(platformUnique);
if (tokenBean != null) {
// 添加登录日志
addLoginLog(platformUnique, tokenBean);
// 更新唯一值
if (!StrUtil.isEmpty(tokenBean.getId()) &&
!Objects.equals(oldUserId, tokenBean.getId())) {
platformUnique.setUserId(tokenBean.getId());
saveOrUpdate(platformUnique);
}
}
return tokenBean;
}
/**
* 授权登录回调
*
* @param bean
*/
public void redirect(TokenBean bean, String to, String extra, HttpServletResponse response) {
tsLoginConfigurer.redirect(bean, to, extra, response);
}
/**
* 签名错误的时候
*/
public void onSignError(HttpServletResponse response) {
tsLoginConfigurer.onSignError(response);
}
///////////////////////////////////////////////////////////////////////////
// 登录日志
///////////////////////////////////////////////////////////////////////////
/**
* 添加登录日志
*
* @param platformUnique
* @param tokenBean
*/
public void addLoginLog(CorePlatformUnique platformUnique, TokenBean tokenBean) {
HttpServletRequest request = ServletKit.getRequest();
String ip = ServletUtil.getClientIP(request);
CoreLogLogin login = new CoreLogLogin();
login.setUserId(tokenBean.getId());
login.setPlatform(platformUnique.getPlatform());
RequestUserInfo requestUserInfo = tsLoginConfigurer.getCachedUserInfo(tokenBean);
login.setUserName(requestUserInfo.getName());
login.setIp(ip);
login.setAddress(ip2regionConfig.search(login.getIp()));
coreLogLoginMapper.insert(login);
}
}

View File

@@ -1,36 +0,0 @@
package com.tiesheng.login.service;
import com.tiesheng.util.pojos.TokenBean;
import com.tiesheng.login.pojos.DoLoginInfo;
import org.springframework.context.annotation.Configuration;
import javax.servlet.http.HttpServletResponse;
/**
* @author hao
*/
@Configuration
public interface TieshengLoginConfigurer {
/**
* 执行登录
*
* @return
*/
TokenBean doLogin(DoLoginInfo loginInfo);
/**
* 授权登录回调
*
* @param bean
*/
void onLoginRedirect(TokenBean bean, String to, String extra, HttpServletResponse response);
/**
* 签名错误的时候
*/
void onSignError(HttpServletResponse response);
}

View File

@@ -0,0 +1,69 @@
package com.tiesheng.login.service;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.tiesheng.login.pojos.RequestUserInfo;
import com.tiesheng.login.pojos.dao.CorePlatformUnique;
import com.tiesheng.util.config.TsTokenConfig;
import com.tiesheng.util.pojos.TokenBean;
import com.tiesheng.util.service.TsCacheService;
import org.springframework.context.annotation.Configuration;
import javax.servlet.http.HttpServletResponse;
/**
* @author hao
*/
@Configuration
public interface TsLoginConfigurer {
/**
* 执行登录
*
* @return
*/
TokenBean login(CorePlatformUnique platformUnique);
/**
* 授权登录回调
*
* @param bean
*/
void redirect(TokenBean bean, String to, String extra, HttpServletResponse response);
/**
* 签名错误的时候
*/
default void onSignError(HttpServletResponse response) {
ServletUtil.write(response, "404", "text");
}
/**
* 获取当前用户的信息
*
* @param tokenBean
* @return
*/
default RequestUserInfo getCachedUserInfo(TokenBean tokenBean) {
String key = StrUtil.format(TsTokenConfig.CACHE_REQUEST_LOGIN_KEY, tokenBean.getId());
RequestUserInfo obj = TsCacheService.of().getObj(key, RequestUserInfo.class, -1);
if (obj == null) {
obj = getCurrentUserName(tokenBean);
}
if (obj != null) {
TsCacheService.of().putObj(key, obj, 30 * 60);
}
return obj;
}
/**
* 获取当前用户的姓名
*
* @return
*/
RequestUserInfo getCurrentUserName(TokenBean userId);
}

View File

@@ -1,32 +0,0 @@
package com.tiesheng.login.service.impl;
import com.tiesheng.util.pojos.TokenBean;
import com.tiesheng.login.pojos.DoLoginInfo;
import com.tiesheng.login.service.TieshengLoginConfigurer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Configuration;
import javax.servlet.http.HttpServletResponse;
/**
* @author hao
*/
@Configuration
@ConditionalOnMissingBean(value = TieshengLoginConfigurer.class, ignored = DefaultLoginConfigurer.class)
public class DefaultLoginConfigurer implements TieshengLoginConfigurer {
@Override
public TokenBean doLogin(DoLoginInfo loginInfo) {
return null;
}
@Override
public void onLoginRedirect(TokenBean bean, String to, String extra, HttpServletResponse response) {
}
@Override
public void onSignError(HttpServletResponse response) {
}
}

View File

@@ -1,6 +1,24 @@
SET NAMES utf8mb4; SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0; SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for core_log_login
-- ----------------------------
CREATE TABLE `core_log_login`
(
`id` varchar(50) NOT NULL,
`create_time` datetime NOT NULL,
`update_time` datetime NOT NULL,
`is_deleted` int(6) NOT NULL DEFAULT '0',
`user_id` varchar(50) DEFAULT NULL COMMENT '用户id',
`user_name` varchar(255) DEFAULT NULL COMMENT '用户姓名',
`platform` varchar(50) DEFAULT NULL COMMENT '登录方式',
`ip` varchar(100) DEFAULT NULL COMMENT 'ip',
`address` varchar(255) DEFAULT NULL COMMENT 'ip地址',
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4 COMMENT ='日志-登录';
-- ---------------------------- -- ----------------------------
-- Table structure for core_platform_unique -- Table structure for core_platform_unique
-- ---------------------------- -- ----------------------------

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.tiesheng.web.mapper.CoreLogLoginMapper"> <mapper namespace="com.tiesheng.login.mapper.CoreLogLoginMapper">
<resultMap id="BaseResultMap" type="com.tiesheng.web.pojos.dao.CoreLogLogin"> <resultMap id="BaseResultMap" type="com.tiesheng.login.pojos.dao.CoreLogLogin">
<!--@mbg.generated--> <!--@mbg.generated-->
<!--@Table core_log_login--> <!--@Table core_log_login-->
<id column="id" jdbcType="VARCHAR" property="id" /> <id column="id" jdbcType="VARCHAR" property="id" />

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.tiesheng.web.mapper.CorePlatformUniqueMapper"> <mapper namespace="com.tiesheng.login.mapper.CorePlatformUniqueMapper">
<resultMap id="BaseResultMap" type="com.tiesheng.web.pojos.dao.CorePlatformUnique"> <resultMap id="BaseResultMap" type="com.tiesheng.login.pojos.dao.CorePlatformUnique">
<!--@mbg.generated--> <!--@mbg.generated-->
<!--@Table core_platform_unique--> <!--@Table core_platform_unique-->
<id column="id" jdbcType="VARCHAR" property="id" /> <id column="id" jdbcType="VARCHAR" property="id" />

View File

@@ -6,7 +6,7 @@
<parent> <parent>
<groupId>com.tiesheng.springboot-parent</groupId> <groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId> <artifactId>springboot-parent</artifactId>
<version>2.0.0.rc6</version> <version>2.0.0.rc21</version>
</parent> </parent>
<artifactId>springboot-message</artifactId> <artifactId>springboot-message</artifactId>

View File

@@ -1,7 +1,6 @@
package com.tiesheng.message.config.aliyun; package com.tiesheng.message.config.aliyun;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import com.tiesheng.message.pojos.AliyunTempParam;
public interface AliyunSmsHandler { public interface AliyunSmsHandler {

View File

@@ -5,13 +5,12 @@ import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil; import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import com.tiesheng.message.pojos.AliyunTempParam; import com.tiesheng.message.service.TsMessageSender;
import com.tiesheng.message.pojos.MessageReqResp;
import com.tiesheng.message.service.TieshengMessageSender;
import com.tiesheng.util.exception.ApiException; import com.tiesheng.util.exception.ApiException;
import com.tiesheng.util.pojos.ApiResp;
import com.tiesheng.util.service.http.OkHttpUtil;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@@ -31,7 +30,7 @@ import java.util.stream.Collectors;
*/ */
@Configuration @Configuration
@ConfigurationProperties(prefix = "tiesheng.aliyun") @ConfigurationProperties(prefix = "tiesheng.aliyun")
public class AliyunSmsSender implements TieshengMessageSender { public class AliyunSmsSender implements TsMessageSender {
/** /**
* 请求地址 * 请求地址
@@ -102,7 +101,7 @@ public class AliyunSmsSender implements TieshengMessageSender {
String respBody = ""; String respBody = "";
try { try {
respBody = HttpUtil.get(ENDPOINT + "?Signature=" + signature + sortQueryStringTmp, 10 * 1000); respBody = OkHttpUtil.get(ENDPOINT + "?Signature=" + signature + sortQueryStringTmp);
} catch (Exception e) { } catch (Exception e) {
respBody = JSONUtil.createObj() respBody = JSONUtil.createObj()
.putOpt("Code", "Error") .putOpt("Code", "Error")
@@ -120,17 +119,7 @@ public class AliyunSmsSender implements TieshengMessageSender {
* @param tempParam 短信模板 * @param tempParam 短信模板
* @return * @return
*/ */
public MessageReqResp sendSms(String phoneNumbers, AliyunTempParam tempParam) { public ApiResp<String> sendSms(String phoneNumbers, AliyunTempParam tempParam) {
MessageReqResp reqResp = new MessageReqResp("阿里云短信");
reqResp.setTarget(phoneNumbers);
reqResp.setResult(1);
reqResp.setContent(JSONUtil.createObj()
.putOpt("PhoneNumbers", phoneNumbers)
.putOpt("SignName", tempParam.getSignName())
.putOpt("TemplateCode", tempParam.getTemplateCode())
.putOpt("TemplateParam", tempParam.getTemplateParam())
.toString());
// 业务API参数 // 业务API参数
ConcurrentHashMap<String, String> queryMap = new ConcurrentHashMap<>(); ConcurrentHashMap<String, String> queryMap = new ConcurrentHashMap<>();
@@ -141,18 +130,16 @@ public class AliyunSmsSender implements TieshengMessageSender {
queryMap.put("TemplateParam", tempParam.getTemplateParam().toString()); queryMap.put("TemplateParam", tempParam.getTemplateParam().toString());
} }
reqResp.setRespBody(request("SendSms", queryMap)); JSONObject respObj = JSONUtil.parseObj(request("SendSms", queryMap));
JSONObject respObj = JSONUtil.parseObj(reqResp.getRespBody());
if (!Objects.equals(respObj.getStr("Code"), "OK")) { if (!Objects.equals(respObj.getStr("Code"), "OK")) {
reqResp.setResult(0); return ApiResp.resp130(respObj.getStr("Message"));
reqResp.setToast(respObj.getStr("Message"));
} }
return reqResp; return ApiResp.respOK("");
} }
@Override @Override
public MessageReqResp send(String user, JSONObject body) { public ApiResp<String> send(String user, JSONObject body) {
boolean mobile = Validator.isMobile(user); boolean mobile = Validator.isMobile(user);
if (!mobile) { if (!mobile) {
return null; return null;

View File

@@ -1,4 +1,4 @@
package com.tiesheng.message.pojos; package com.tiesheng.message.config.aliyun;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;

View File

@@ -1,87 +0,0 @@
package com.tiesheng.message.pojos;
public class MessageReqResp {
private String type;
/**
* 发送对象
*/
private String target;
/**
* 发送内容
*/
private String content;
/**
* 返回结果
*/
private String respBody;
/**
* 结果0-否1-是
*/
private Integer result;
/**
* 提示的异常信息
*/
private String toast;
public MessageReqResp(String type) {
this.type = type;
}
///////////////////////////////////////////////////////////////////////////
// setter\getter
///////////////////////////////////////////////////////////////////////////
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getTarget() {
return target;
}
public void setTarget(String target) {
this.target = target;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getRespBody() {
return respBody;
}
public void setRespBody(String respBody) {
this.respBody = respBody;
}
public Integer getResult() {
return result;
}
public void setResult(Integer result) {
this.result = result;
}
public String getToast() {
return toast;
}
public void setToast(String toast) {
this.toast = toast;
}
}

View File

@@ -2,12 +2,12 @@ package com.tiesheng.message.service;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import com.tiesheng.message.pojos.MessageReqResp; import com.tiesheng.util.pojos.ApiResp;
/** /**
* @author hao * @author hao
*/ */
public interface TieshengMessageSender { public interface TsMessageSender {
/** /**
@@ -20,7 +20,7 @@ public interface TieshengMessageSender {
* @param channel 消息通道如果为空表示所有通道 * @param channel 消息通道如果为空表示所有通道
* @return 返回的内容如果为空表示发送成功 * @return 返回的内容如果为空表示发送成功
*/ */
MessageReqResp send(String user, JSONObject body); ApiResp<String> send(String user, JSONObject body);
/** /**

View File

@@ -1,15 +1,11 @@
package com.tiesheng.web.service; package com.tiesheng.message.service;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import com.tiesheng.web.mapper.CoreLogMessageMapper;
import com.tiesheng.web.pojos.dao.CoreLogMessage;
import com.tiesheng.message.pojos.MessageReqResp;
import com.tiesheng.message.pojos.UserChannel; import com.tiesheng.message.pojos.UserChannel;
import com.tiesheng.message.service.TieshengMessageSender; import com.tiesheng.util.pojos.ApiResp;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -20,25 +16,10 @@ import java.util.Objects;
* @author hao * @author hao
*/ */
@Service @Service
public class CoreMessageService { public class TsMessageService {
@Autowired @Autowired
List<TieshengMessageSender> messageSenderList; List<TsMessageSender> messageSenderList;
@Autowired
CoreLogMessageMapper coreLogMessageMapper;
/**
* 插入数据
*
* @param reqResp
*/
private void insertMessageLog(MessageReqResp reqResp) {
if (reqResp == null) {
return;
}
coreLogMessageMapper.insert(BeanUtil.copyProperties(reqResp, CoreLogMessage.class));
}
/** /**
* 发送所有消息 * 发送所有消息
@@ -47,10 +28,10 @@ public class CoreMessageService {
* @param body * @param body
*/ */
public void all(List<String> userIds, JSONObject body) { public void all(List<String> userIds, JSONObject body) {
messageSenderList.stream().filter(TieshengMessageSender::support) messageSenderList.stream().filter(TsMessageSender::support)
.forEach(sender -> { .forEach(sender -> {
for (String user : userIds) { for (String user : userIds) {
insertMessageLog(sender.send(user, body)); sender.send(user, body);
} }
}); });
} }
@@ -68,9 +49,9 @@ public class CoreMessageService {
return; return;
} }
messageSenderList.stream().filter(TieshengMessageSender::support) messageSenderList.stream().filter(TsMessageSender::support)
.forEach(sender -> channels.stream().filter(it -> Objects.equals(it.getChannel(), sender.getChannel())) .forEach(sender -> channels.stream().filter(it -> Objects.equals(it.getChannel(), sender.getChannel()))
.forEach(it -> insertMessageLog(sender.send(it.getUser(), body)))); .forEach(it -> sender.send(it.getUser(), body)));
} }
@@ -80,20 +61,18 @@ public class CoreMessageService {
* @param userChannel * @param userChannel
* @param body * @param body
*/ */
public MessageReqResp send(UserChannel userChannel, JSONObject body) { public ApiResp<String> send(UserChannel userChannel, JSONObject body) {
if (StrUtil.isEmpty(userChannel.getUser()) || StrUtil.isEmpty(userChannel.getChannel())) { if (StrUtil.isEmpty(userChannel.getUser()) || StrUtil.isEmpty(userChannel.getChannel())) {
return null; return ApiResp.resp130("消息对象或消息通道不存在");
} }
TieshengMessageSender messageSender = CollUtil.findOne(messageSenderList, TsMessageSender messageSender = CollUtil.findOne(messageSenderList,
sender -> Objects.equals(sender.getChannel(), userChannel.getChannel()) && sender.support()); sender -> Objects.equals(sender.getChannel(), userChannel.getChannel()) && sender.support());
if (messageSender != null) { if (messageSender != null) {
MessageReqResp reqResp = messageSender.send(userChannel.getUser(), body); return messageSender.send(userChannel.getUser(), body);
insertMessageLog(reqResp);
return reqResp;
} }
return null; return ApiResp.resp130("消息未成功发送");
} }
} }

View File

@@ -6,7 +6,7 @@
<parent> <parent>
<groupId>com.tiesheng.springboot-parent</groupId> <groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId> <artifactId>springboot-parent</artifactId>
<version>2.0.0.rc6</version> <version>2.0.0.rc21</version>
</parent> </parent>
<artifactId>springboot-platform</artifactId> <artifactId>springboot-platform</artifactId>

View File

@@ -4,18 +4,22 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.TypeReference; import cn.hutool.core.lang.TypeReference;
import cn.hutool.core.map.MapUtil; import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import cn.hutool.log.LogFactory; import cn.hutool.log.LogFactory;
import com.tiesheng.platform.config.ding.bean.*; import com.tiesheng.platform.config.ding.bean.*;
import com.tiesheng.util.TimedCacheHelper;
import com.tiesheng.util.exception.ApiException; import com.tiesheng.util.exception.ApiException;
import com.tiesheng.util.service.TsCacheService;
import com.tiesheng.util.service.http.OkHttpUtil;
import okhttp3.Request;
import okhttp3.Response;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import java.util.*; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer; import java.util.function.Consumer;
/** /**
@@ -57,28 +61,36 @@ public class PlatformDingConfig {
* @return * @return
*/ */
public <T> DingResponse<T> doRequest(String service, String url, JSONObject body, TypeReference<DingResponse<T>> typeReference) { public <T> DingResponse<T> doRequest(String service, String url, JSONObject body, TypeReference<DingResponse<T>> typeReference) {
String accessToken = getAccessToken(service);
if (StrUtil.contains(url, "?")) { if (StrUtil.contains(url, "?")) {
url = url + "&access_token=" + getAccessToken(service); url = url + "&access_token=" + accessToken;
} else { } else {
url = url + "?access_token=" + getAccessToken(service); url = url + "?access_token=" + accessToken;
} }
HttpResponse execute; Request request;
if (body == null) { if (body == null) {
execute = HttpUtil.createGet(url).execute(); request = OkHttpUtil.ofGet(url);
} else { } else {
execute = HttpUtil.createPost(url).body(body.toString()).execute(); request = OkHttpUtil.ofPost(url, body);
} }
request = request.newBuilder().header("x-acs-dingtalk-access-token", accessToken).build();
if (execute.isOk()) { try {
DingResponse<T> bean = JSONUtil.toBean(execute.body(), typeReference, true); Response response = OkHttpUtil.ofHttpClient().build().newCall(request).execute();
if (!bean.isOk()) { if (response.isSuccessful() && response.body() != null) {
LogFactory.get().info(bean.getErrmsg()); String rawBody = response.body().string();
DingResponse<T> bean = JSONUtil.toBean(rawBody, typeReference, true);
bean.setRawBody(rawBody);
return bean;
} else {
LogFactory.get().info(response.body().string());
} }
return bean; } catch (Exception e) {
LogFactory.get().error(e);
} }
return null; return DingResponse.ofError();
} }
@@ -92,9 +104,9 @@ public class PlatformDingConfig {
* @return accessToken * @return accessToken
* @see <a href="https://open.dingtalk.com/document/orgapp-server/obtain-orgapp-token" /> * @see <a href="https://open.dingtalk.com/document/orgapp-server/obtain-orgapp-token" />
*/ */
private String getAccessToken(String service) { public synchronized String getAccessToken(String service) {
DingConfigBean dingConfigBean = getConfigBean(service); DingConfigBean dingConfigBean = getConfigBean(service);
String accessToken = TimedCacheHelper.getTimedCache().get(CACHE_ACCESS_TOKEN + dingConfigBean.getAppKey(), false); String accessToken = TsCacheService.of().get(CACHE_ACCESS_TOKEN + dingConfigBean.getAppKey(), -1);
if (!StrUtil.isEmpty(accessToken)) { if (!StrUtil.isEmpty(accessToken)) {
return accessToken; return accessToken;
} }
@@ -103,10 +115,11 @@ public class PlatformDingConfig {
Map<String, Object> query = new HashMap<>(10); Map<String, Object> query = new HashMap<>(10);
query.put("appkey", dingConfigBean.getAppKey()); query.put("appkey", dingConfigBean.getAppKey());
query.put("appsecret", dingConfigBean.getAppSecret()); query.put("appsecret", dingConfigBean.getAppSecret());
String response = HttpUtil.get("https://oapi.dingtalk.com/gettoken", query); String response = OkHttpUtil.get("https://oapi.dingtalk.com/gettoken", query);
JSONObject respJson = JSONUtil.parseObj(response); JSONObject respJson = JSONUtil.parseObj(response);
accessToken = respJson.getStr("access_token"); accessToken = respJson.getStr("access_token");
TimedCacheHelper.getTimedCache().put(CACHE_ACCESS_TOKEN + dingConfigBean.getAppKey(), accessToken, respJson.getLong("expires_in")); TsCacheService.of().put(CACHE_ACCESS_TOKEN + dingConfigBean.getAppKey(),
accessToken, respJson.getLong("expires_in"));
return accessToken; return accessToken;
} }
@@ -120,7 +133,7 @@ public class PlatformDingConfig {
*/ */
private String getJsapiTicket(String service) { private String getJsapiTicket(String service) {
DingConfigBean dingConfigBean = getConfigBean(service); DingConfigBean dingConfigBean = getConfigBean(service);
String jsapiTicket = TimedCacheHelper.getTimedCache().get(CACHE_JSAPI_TICKET + dingConfigBean.getAppKey(), false); String jsapiTicket = TsCacheService.of().get(CACHE_JSAPI_TICKET + dingConfigBean.getAppKey(), -1);
if (StrUtil.isEmpty(jsapiTicket)) { if (StrUtil.isEmpty(jsapiTicket)) {
DingResponse<String> respJson = doRequest(service, "https://oapi.dingtalk.com/get_jsapi_ticket", null, DingResponse<String> respJson = doRequest(service, "https://oapi.dingtalk.com/get_jsapi_ticket", null,
new TypeReference<DingResponse<String>>() { new TypeReference<DingResponse<String>>() {
@@ -128,8 +141,9 @@ public class PlatformDingConfig {
if (!respJson.isOk()) { if (!respJson.isOk()) {
throw new ApiException(respJson.getErrmsg()); throw new ApiException(respJson.getErrmsg());
} }
jsapiTicket = respJson.getTicket();
TimedCacheHelper.getTimedCache().put(CACHE_JSAPI_TICKET + dingConfigBean.getAppKey(), jsapiTicket = respJson.getRawValue("ticket", String.class);
TsCacheService.of().put(CACHE_JSAPI_TICKET + dingConfigBean.getAppKey(),
jsapiTicket, respJson.getExpiresIn()); jsapiTicket, respJson.getExpiresIn());
} }
return jsapiTicket; return jsapiTicket;
@@ -263,10 +277,12 @@ public class PlatformDingConfig {
* 发送工作通知 * 发送工作通知
* *
* @param service * @param service
* @param content * @param title
* @param markdown
* @param actionUrl * @param actionUrl
* @param userIds * @param userIds
* @return * @return
* @see <a href='https://open.dingtalk.com/document/orgapp/asynchronous-sending-of-enterprise-session-messages' </a>
*/ */
public DingResponse<String> messageNotification(String service, String title, String markdown, String actionUrl, List<String> userIds) { public DingResponse<String> messageNotification(String service, String title, String markdown, String actionUrl, List<String> userIds) {
@@ -276,15 +292,20 @@ public class PlatformDingConfig {
DingConfigBean configBean = getConfigBean(service); DingConfigBean configBean = getConfigBean(service);
JSONObject actionCard = new JSONObject();
actionCard.set("title", title);
actionCard.set("markdown", markdown);
actionCard.set("single_title", "点击查看");
actionCard.set("single_url", actionUrl);
JSONObject msg = new JSONObject(); JSONObject msg = new JSONObject();
msg.set("msgtype", "action_card");
msg.set("action_card", actionCard); if (StrUtil.isEmpty(actionUrl)) {
msg.set("msgtype", "markdown");
msg.set("markdown", JSONUtil.createObj()
.set("title", title).set("text", markdown)
);
} else {
msg.set("msgtype", "action_card");
msg.set("action_card", JSONUtil.createObj()
.set("title", title).set("markdown", markdown)
.set("single_title", "点击查看").set("single_url", actionUrl)
);
}
JSONObject body = new JSONObject(); JSONObject body = new JSONObject();
body.putOpt("agent_id", configBean.getAgentId()); body.putOpt("agent_id", configBean.getAgentId());

View File

@@ -1,14 +1,16 @@
package com.tiesheng.platform.config.ding.bean; package com.tiesheng.platform.config.ding.bean;
import cn.hutool.json.JSONUtil;
import java.util.Objects; import java.util.Objects;
public class DingResponse<T> { public class DingResponse<T> {
private String errcode; private String errcode;
private String errmsg; private String errmsg;
private String ticket;
private Long expiresIn; private Long expiresIn;
private T result; private T result;
private String rawBody;
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// 逻辑方法 // 逻辑方法
@@ -18,6 +20,30 @@ public class DingResponse<T> {
return Objects.equals(errcode, "0"); return Objects.equals(errcode, "0");
} }
/**
* 构造一个异常对象
*
* @return
*/
public static <T> DingResponse<T> ofError() {
DingResponse<T> response = new DingResponse<>();
response.setErrcode("-1");
response.setErrmsg("网络访问异常。");
return response;
}
/**
* 从原始数据中获取值
*
* @param path
* @return
*/
public <E> E getRawValue(String path, Class<E> tClass) {
return JSONUtil.parse(getRawBody()).getByPath(path, tClass);
}
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// setter\getter // setter\getter
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
@@ -46,14 +72,6 @@ public class DingResponse<T> {
this.result = result; this.result = result;
} }
public String getTicket() {
return ticket;
}
public void setTicket(String ticket) {
this.ticket = ticket;
}
public Long getExpiresIn() { public Long getExpiresIn() {
return expiresIn; return expiresIn;
} }
@@ -61,4 +79,12 @@ public class DingResponse<T> {
public void setExpiresIn(Long expiresIn) { public void setExpiresIn(Long expiresIn) {
this.expiresIn = expiresIn; this.expiresIn = expiresIn;
} }
public String getRawBody() {
return rawBody;
}
public void setRawBody(String rawBody) {
this.rawBody = rawBody;
}
} }

View File

@@ -2,12 +2,11 @@ package com.tiesheng.platform.config.wxmini;
import cn.hutool.core.map.MapUtil; import cn.hutool.core.map.MapUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import com.tiesheng.platform.config.wxmp.bean.WxConfigBean; import com.tiesheng.platform.config.wxmp.bean.WxConfigBean;
import com.tiesheng.util.exception.ApiException; import com.tiesheng.util.exception.ApiException;
import com.tiesheng.util.service.http.OkHttpUtil;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@@ -51,13 +50,14 @@ public class PlatformWxminiConfig {
*/ */
public String jscode2session(String service, String code) { public String jscode2session(String service, String code) {
WxConfigBean configBean = getConfigBean(service); WxConfigBean configBean = getConfigBean(service);
try (HttpResponse response = HttpRequest.get("https://api.weixin.qq.com/sns/jscode2session"
String body = OkHttpUtil.get("https://api.weixin.qq.com/sns/jscode2session"
+ "?appid=" + configBean.getAppId() + "?appid=" + configBean.getAppId()
+ "&secret=" + configBean.getAppSecret() + "&secret=" + configBean.getAppSecret()
+ "&js_code=" + code + "&grant_type=authorization_code").execute()) { + "&js_code=" + code + "&grant_type=authorization_code");
JSONObject object = JSONUtil.parseObj(response.body());
return object.getStr("openid"); JSONObject object = JSONUtil.parseObj(body);
} return object.getStr("openid");
} }
/** /**
@@ -67,12 +67,13 @@ public class PlatformWxminiConfig {
*/ */
public String getAccessToken(String service) { public String getAccessToken(String service) {
WxConfigBean configBean = getConfigBean(service); WxConfigBean configBean = getConfigBean(service);
try (HttpResponse response = HttpRequest.get("https://api.weixin.qq.com/cgi-bin/token"
String body = OkHttpUtil.get("https://api.weixin.qq.com/cgi-bin/token"
+ "?grant_type=client_credential&appid=" + configBean.getAppId() + "?grant_type=client_credential&appid=" + configBean.getAppId()
+ "&secret=" + configBean.getAppSecret()).execute()) { + "&secret=" + configBean.getAppSecret());
JSONObject object = JSONUtil.parseObj(response.body());
return object.getStr("access_token"); JSONObject object = JSONUtil.parseObj(body);
} return object.getStr("access_token");
} }

View File

@@ -4,7 +4,6 @@ package com.tiesheng.platform.config.wxmp;
import cn.hutool.core.map.MapUtil; import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil; import cn.hutool.core.util.URLUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import cn.hutool.log.LogFactory; import cn.hutool.log.LogFactory;
@@ -12,8 +11,9 @@ import com.tiesheng.platform.config.wxmp.bean.WxConfigBean;
import com.tiesheng.platform.config.wxmp.bean.WxJsapiSignature; import com.tiesheng.platform.config.wxmp.bean.WxJsapiSignature;
import com.tiesheng.platform.config.wxmp.bean.WxOAuth2AccessToken; import com.tiesheng.platform.config.wxmp.bean.WxOAuth2AccessToken;
import com.tiesheng.platform.config.wxmp.bean.WxUserInfo; import com.tiesheng.platform.config.wxmp.bean.WxUserInfo;
import com.tiesheng.util.TimedCacheHelper;
import com.tiesheng.util.exception.ApiException; import com.tiesheng.util.exception.ApiException;
import com.tiesheng.util.service.TsCacheService;
import com.tiesheng.util.service.http.OkHttpUtil;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@@ -63,17 +63,17 @@ public class PlatformWxmpConfig {
*/ */
private String getAccessToken(String service) { private String getAccessToken(String service) {
WxConfigBean configBean = getConfigBean(service); WxConfigBean configBean = getConfigBean(service);
String accessToken = TimedCacheHelper.getTimedCache().get(CACHE_ACCESS_TOKEN + configBean.getAppId(), false); String accessToken = TsCacheService.of().get(CACHE_ACCESS_TOKEN + configBean.getAppId(), -1);
if (StrUtil.isEmpty(accessToken)) { if (StrUtil.isEmpty(accessToken)) {
Map<String, Object> query = new HashMap<>(10); Map<String, Object> query = new HashMap<>(10);
query.put("grant_type", "client_credential"); query.put("grant_type", "client_credential");
query.put("appid", configBean.getAppId()); query.put("appid", configBean.getAppId());
query.put("secret", configBean.getAppSecret()); query.put("secret", configBean.getAppSecret());
String response = HttpUtil.get("https://api.weixin.qq.com/cgi-bin/token", query); String response = OkHttpUtil.get("https://api.weixin.qq.com/cgi-bin/token", query);
LogFactory.get().info("getAccessToken: " + response);
JSONObject respJson = JSONUtil.parseObj(response); JSONObject respJson = JSONUtil.parseObj(response);
accessToken = respJson.getStr("access_token"); accessToken = respJson.getStr("access_token");
TimedCacheHelper.getTimedCache().put(CACHE_ACCESS_TOKEN + configBean.getAppId(), accessToken, respJson.getLong("expires_in")); TsCacheService.of().put(CACHE_ACCESS_TOKEN + configBean.getAppId(), accessToken,
respJson.getLong("expires_in"));
} }
return accessToken; return accessToken;
} }
@@ -86,16 +86,17 @@ public class PlatformWxmpConfig {
*/ */
private String getJsapiTicket(String service) { private String getJsapiTicket(String service) {
WxConfigBean configBean = getConfigBean(service); WxConfigBean configBean = getConfigBean(service);
String jsapiTicket = TimedCacheHelper.getTimedCache().get(CACHE_JSAPI_TICKET + configBean.getAppId(), false); String jsapiTicket = TsCacheService.of().get(CACHE_JSAPI_TICKET + configBean.getAppId(), -1);
if (StrUtil.isEmpty(jsapiTicket)) { if (StrUtil.isEmpty(jsapiTicket)) {
Map<String, Object> query = new HashMap<>(10); Map<String, Object> query = new HashMap<>(10);
query.put("access_token", getAccessToken(service)); query.put("access_token", getAccessToken(service));
query.put("type", "jsapi"); query.put("type", "jsapi");
String response = HttpUtil.get("https://api.weixin.qq.com/cgi-bin/ticket/getticket", query); String response = OkHttpUtil.get("https://api.weixin.qq.com/cgi-bin/ticket/getticket", query);
LogFactory.get().info("getJsapiTicket: " + response); LogFactory.get().info("getJsapiTicket: " + response);
JSONObject respJson = JSONUtil.parseObj(response); JSONObject respJson = JSONUtil.parseObj(response);
jsapiTicket = respJson.getStr("ticket"); jsapiTicket = respJson.getStr("ticket");
TimedCacheHelper.getTimedCache().put(CACHE_JSAPI_TICKET + configBean.getAppId(), jsapiTicket, respJson.getLong("expires_in")); TsCacheService.of().put(CACHE_JSAPI_TICKET + configBean.getAppId(), jsapiTicket,
respJson.getLong("expires_in"));
} }
return jsapiTicket; return jsapiTicket;
} }
@@ -155,7 +156,7 @@ public class PlatformWxmpConfig {
public void mediaPicGet(String service, String mediaId, String filePath) { public void mediaPicGet(String service, String mediaId, String filePath) {
String fileUrl = String.format("https://api.weixin.qq.com/cgi-bin/media/get?access_token=%s&media_id=%s", String fileUrl = String.format("https://api.weixin.qq.com/cgi-bin/media/get?access_token=%s&media_id=%s",
getAccessToken(service), mediaId); getAccessToken(service), mediaId);
HttpUtil.downloadFile(fileUrl, filePath); OkHttpUtil.downloadFile(fileUrl, filePath);
} }

View File

@@ -1,8 +1,8 @@
package com.tiesheng.platform.config.wxmp.bean; package com.tiesheng.platform.config.wxmp.bean;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject; import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import com.tiesheng.util.service.http.OkHttpUtil;
/** /**
* @author hao * @author hao
@@ -13,7 +13,7 @@ public class WxOAuth2AccessToken {
private String openid; private String openid;
public static WxOAuth2AccessToken create(String appId, String secret, String code) { public static WxOAuth2AccessToken create(String appId, String secret, String code) {
String response = HttpUtil.get("https://api.weixin.qq.com/sns/oauth2/access_token" + String response = OkHttpUtil.get("https://api.weixin.qq.com/sns/oauth2/access_token" +
"?appid=" + appId + "&secret=" + secret + "&code=" + code + "&grant_type=authorization_code"); "?appid=" + appId + "&secret=" + secret + "&code=" + code + "&grant_type=authorization_code");
JSONObject respJson = JSONUtil.parseObj(response); JSONObject respJson = JSONUtil.parseObj(response);

View File

@@ -1,7 +1,7 @@
package com.tiesheng.platform.config.wxmp.bean; package com.tiesheng.platform.config.wxmp.bean;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import com.tiesheng.util.service.http.OkHttpUtil;
/** /**
* @author hao * @author hao
@@ -30,7 +30,7 @@ public class WxUserInfo {
* @return * @return
*/ */
public static WxUserInfo create(WxOAuth2AccessToken oAuth2AccessToken) { public static WxUserInfo create(WxOAuth2AccessToken oAuth2AccessToken) {
String s = HttpUtil.get("https://api.weixin.qq.com/sns/userinfo" String s = OkHttpUtil.get("https://api.weixin.qq.com/sns/userinfo"
+ "?access_token=" + oAuth2AccessToken.getAccessToken() + "?access_token=" + oAuth2AccessToken.getAccessToken()
+ "&openid=" + oAuth2AccessToken.getOpenid() + "&lang=zh_CN"); + "&openid=" + oAuth2AccessToken.getOpenid() + "&lang=zh_CN");
return JSONUtil.toBean(s, WxUserInfo.class); return JSONUtil.toBean(s, WxUserInfo.class);

View File

@@ -6,7 +6,7 @@
<parent> <parent>
<groupId>com.tiesheng.springboot-parent</groupId> <groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId> <artifactId>springboot-parent</artifactId>
<version>2.0.0.rc6</version> <version>2.0.0.rc21</version>
</parent> </parent>
<artifactId>springboot-poi</artifactId> <artifactId>springboot-poi</artifactId>

View File

@@ -6,7 +6,7 @@
<parent> <parent>
<groupId>com.tiesheng.springboot-parent</groupId> <groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId> <artifactId>springboot-parent</artifactId>
<version>2.0.0.rc6</version> <version>2.0.0.rc21</version>
</parent> </parent>
<artifactId>springboot-role</artifactId> <artifactId>springboot-role</artifactId>
@@ -22,6 +22,13 @@
<groupId>com.tiesheng.springboot-parent</groupId> <groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-util</artifactId> <artifactId>springboot-util</artifactId>
</dependency> </dependency>
<!-- aspect -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -0,0 +1,104 @@
package com.tiesheng.role.controller;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tiesheng.role.pojos.dao.CoreRoleAuthority;
import com.tiesheng.role.pojos.dao.CoreRoleServer;
import com.tiesheng.role.pojos.dto.OwnerMenuDTO;
import com.tiesheng.role.pojos.dto.OwnerPointDTO;
import com.tiesheng.role.pojos.vo.ServiceMenuVO;
import com.tiesheng.role.service.CoreRoleService;
import com.tiesheng.util.pojos.ApiResp;
import com.tiesheng.util.pojos.TokenBean;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/comm/role")
public class CommRoleController {
@Resource
CoreRoleService coreRoleService;
/**
* 获取自己拥有的服务
*
* @return
*/
@GetMapping("/owner/server")
public ApiResp<List<CoreRoleServer>> ownerServer(TokenBean tokenBean) {
List<CoreRoleAuthority> allOwnerMenus = coreRoleService.getOwnerAuthorityLeafList(tokenBean.getId(), tokenBean.getRoleId());
List<String> list = allOwnerMenus.stream().map(CoreRoleAuthority::getService).collect(Collectors.toList());
List<CoreRoleServer> roleServerList = new ArrayList<>();
if (CollUtil.isNotEmpty(list)) {
roleServerList = coreRoleService.getServerMapper().selectList(new QueryWrapper<CoreRoleServer>()
.in("id", list)
.eq(CoreRoleServer.IS_DELETED, 0)
.eq("is_open", 1)
);
}
return ApiResp.respOK(roleServerList);
}
/**
* 获取自己拥有的菜单
*
* @return
*/
@GetMapping("/owner/menu")
public ApiResp<List<ServiceMenuVO>> ownerMenu(@Valid OwnerMenuDTO dto, TokenBean tokenBean) {
List<ServiceMenuVO> ownerMenus = coreRoleService.getOwnerMenus(tokenBean.getId(), tokenBean.getRoleId(), dto);
return ApiResp.respOK(ownerMenus);
}
/**
* 获取自己拥有的功能点
*
* @return
*/
@GetMapping("/owner/point")
public ApiResp<List<CoreRoleAuthority>> ownerPoint(@Valid OwnerPointDTO dto, TokenBean tokenBean) {
List<CoreRoleAuthority> allOwnerMenus = coreRoleService.getOwnerAuthorityLeafList(tokenBean.getId(), tokenBean.getRoleId());
String parentId;
if (StrUtil.isNotEmpty(dto.getParentNo())) {
CoreRoleAuthority selected = coreRoleService.getAuthorityMapper().selectOne(new QueryWrapper<CoreRoleAuthority>()
.eq("no", dto.getParentNo())
.eq("is_deleted", 0)
.last("limit 1")
);
parentId = selected == null ? "" : selected.getId();
} else {
parentId = "";
}
List<CoreRoleAuthority> collect = allOwnerMenus.stream()
.filter(it -> Objects.equals(it.getType(), "point"))
.filter(it -> it.getService().equals(dto.getService()))
.filter(it -> it.getPlatform().equals(dto.getPlatform()))
.filter(it -> {
if (StrUtil.isNotEmpty(parentId)) {
return parentId.equals(it.getParent());
}
return true;
}).collect(Collectors.toList());
return ApiResp.respOK(collect);
}
}

View File

@@ -1,317 +0,0 @@
package com.tiesheng.role.controller;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tiesheng.role.pojos.dao.*;
import com.tiesheng.role.pojos.dto.GroupRxUpdateDTO;
import com.tiesheng.role.pojos.dto.MenuListDTO;
import com.tiesheng.role.pojos.dto.OwnerMenuDTO;
import com.tiesheng.role.pojos.dto.OwnerPointDTO;
import com.tiesheng.role.pojos.vo.GroupTypeDTO;
import com.tiesheng.role.pojos.vo.RoleUserPageVO;
import com.tiesheng.role.pojos.vo.ServiceMenuVO;
import com.tiesheng.role.service.CoreRoleService;
import com.tiesheng.util.exception.ApiException;
import com.tiesheng.util.pojos.ApiResp;
import com.tiesheng.util.pojos.IdDTO;
import com.tiesheng.util.pojos.PageDTO;
import com.tiesheng.util.pojos.TokenBean;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@RestController
@RequestMapping("/role")
public class RoleController {
@Resource
CoreRoleService coreRoleService;
/**
* 角色列表
*
* @return
*/
@GetMapping("/group/list")
public ApiResp<List<CoreRoleGroup>> groupList(@Valid GroupTypeDTO dto) {
return ApiResp.respOK(coreRoleService.list(
new QueryWrapper<CoreRoleGroup>()
.eq("is_deleted", 0)
.eq("type", dto.getType())
.orderByAsc("sort")
));
}
/**
* 角色编辑
*
* @param roleGroup
* @return
*/
@PostMapping("/group/update")
public ApiResp<String> groupUpdate(@RequestBody CoreRoleGroup roleGroup) {
if (StrUtil.isNotEmpty(roleGroup.getId())) {
roleGroup.setType(null);
roleGroup.setIsSystem(null);
}
coreRoleService.saveOrUpdate(roleGroup);
return ApiResp.respOK("");
}
/**
* 角色-删除
*
* @return
*/
@PostMapping("/group/deleted")
public ApiResp<String> groupDeleted(@RequestBody @Valid IdDTO dto) {
CoreRoleGroup byId = coreRoleService.getById(dto.getId());
if (byId == null || byId.getIsDeleted() != 0) {
throw new ApiException("角色不存在或已删除");
}
if (byId.getIsSystem() == 1) {
throw new ApiException(StrUtil.format("该{}无法删除",
Objects.equals(byId.getType(), "role") ? "角色" : "职位"));
}
CoreRoleGroup coreServiceMenu = new CoreRoleGroup();
coreServiceMenu.setId(dto.getId());
coreServiceMenu.setIsDeleted(1);
coreRoleService.updateById(coreServiceMenu);
return ApiResp.respOK("");
}
/**
* 获取角色的权限
*
* @return
*/
@GetMapping("/group/rx/list")
public ApiResp<List<CoreRoleGroupRx>> groupRxList(@Valid IdDTO dto) {
List<CoreRoleGroupRx> list = coreRoleService.getGroupRxMapper().selectList(new QueryWrapper<CoreRoleGroupRx>()
.eq(CoreRoleGroupRx.IS_DELETED, 0)
.eq("group_id", dto.getId())
);
return ApiResp.respOK(list);
}
/**
* 橘色的权限编辑
*
* @return
*/
@PostMapping("/group/rx/update")
public ApiResp<String> groupRxUpdate(@RequestBody @Valid GroupRxUpdateDTO dto) {
coreRoleService.updateGroupRx(dto);
return ApiResp.respOK("");
}
/**
* 授权列表
*
* @return
*/
@GetMapping("/user/page")
public ApiResp<List<RoleUserPageVO>> userPage(PageDTO dto) {
QueryWrapper<CoreRoleUser> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("cru.is_deleted", 0);
dto.likeColumns(queryWrapper, "cru.ext1", "cru.ext2", "cru.ext3");
queryWrapper.orderByAsc("cru.user_id");
Page<RoleUserPageVO> page = dto.pageObj();
coreRoleService.getUserMapper().page(page, queryWrapper);
return ApiResp.respOK(page.getRecords(), page.getTotal());
}
/**
* 授权调整
*
* @return
*/
@PostMapping("/user/update")
public ApiResp<String> userUpdate(@RequestBody CoreRoleUser roleUser) {
if (StrUtil.isNotEmpty(roleUser.getId())) {
coreRoleService.getUserMapper().updateById(roleUser);
} else {
coreRoleService.getUserMapper().insert(roleUser);
}
return ApiResp.respOK("");
}
/**
* 授权-删除
*
* @return
*/
@PostMapping("/user/deleted")
public ApiResp<String> userDeleted(@RequestBody @Valid IdDTO dto) {
CoreRoleUser coreRoleUser = new CoreRoleUser();
coreRoleUser.setId(dto.getId());
coreRoleUser.setIsDeleted(1);
coreRoleService.getUserMapper().updateById(coreRoleUser);
return ApiResp.respOK("");
}
/**
* 获取服务列表
*
* @return
*/
@GetMapping("/server/list")
public ApiResp<List<CoreRoleServer>> list() {
return ApiResp.respOK(coreRoleService.getServerMapper().selectList(new QueryWrapper<CoreRoleServer>()
.eq(CoreRoleServer.IS_DELETED, 0)
.eq("is_open", 1)
));
}
/**
* 修改服务
*
* @param coreService
* @return
*/
@PostMapping("/server/update")
public ApiResp<String> update(@RequestBody CoreRoleServer coreService) {
if (StrUtil.isNotEmpty(coreService.getId())) {
coreRoleService.getServerMapper().updateById(coreService);
} else {
coreRoleService.getServerMapper().insert(coreService);
}
return ApiResp.respOK("");
}
/**
* 权限-列出
*
* @return
*/
@GetMapping("/authority/list")
public ApiResp<List<ServiceMenuVO>> menuList(@Valid MenuListDTO dto) {
List<CoreRoleAuthority> list = coreRoleService.getAuthorityMapper().selectList(new QueryWrapper<CoreRoleAuthority>()
.eq(CoreRoleAuthority.IS_DELETED, 0)
.eq("service", dto.getService())
.eq(StrUtil.isNotEmpty(dto.getPlatform()), "platform", dto.getPlatform())
.orderByAsc("sort")
);
List<ServiceMenuVO> collect = coreRoleService.menuChildrenWrap(list, null);
return ApiResp.respOK(collect);
}
/**
* 权限-编辑
*
* @return
*/
@PostMapping("/authority/update")
public ApiResp<String> menuUpdate(@RequestBody CoreRoleAuthority serviceMenu) {
serviceMenu.setParent(StrUtil.emptyToDefault(serviceMenu.getParent(), null));
if (StrUtil.isEmpty(serviceMenu.getId())) {
coreRoleService.getAuthorityMapper().insert(serviceMenu);
} else {
serviceMenu.setNo(null);
coreRoleService.getAuthorityMapper().updateById(serviceMenu);
}
return ApiResp.respOK("");
}
/**
* 获取自己拥有的服务
*
* @return
*/
@GetMapping("/owner/server")
public ApiResp<List<CoreRoleServer>> ownerServer(TokenBean tokenBean) {
List<CoreRoleAuthority> allOwnerMenus = coreRoleService.getOwnerAuthorityLeafList(tokenBean.getId(), tokenBean.getRoleId());
List<String> list = allOwnerMenus.stream().map(CoreRoleAuthority::getService).collect(Collectors.toList());
List<CoreRoleServer> roleServerList = new ArrayList<>();
if (CollUtil.isNotEmpty(list)) {
roleServerList = coreRoleService.getServerMapper().selectList(new QueryWrapper<CoreRoleServer>()
.in("id", list)
.eq(CoreRoleServer.IS_DELETED, 0)
.eq("is_open", 1)
);
}
return ApiResp.respOK(roleServerList);
}
/**
* 获取自己拥有的菜单
*
* @return
*/
@GetMapping("/owner/menu")
public ApiResp<List<ServiceMenuVO>> ownerMenu(TokenBean tokenBean, @Valid OwnerMenuDTO dto) {
List<ServiceMenuVO> ownerMenus = coreRoleService.getOwnerMenus(tokenBean.getId(), tokenBean.getRoleId(), dto);
return ApiResp.respOK(ownerMenus);
}
/**
* 获取自己拥有的功能点
*
* @return
*/
@GetMapping("/owner/point")
public ApiResp<List<CoreRoleAuthority>> ownerPoint(TokenBean tokenBean, @Valid OwnerPointDTO dto) {
List<CoreRoleAuthority> allOwnerMenus = coreRoleService.getOwnerAuthorityLeafList(tokenBean.getId(), tokenBean.getRoleId());
String parentId;
if (StrUtil.isNotEmpty(dto.getParentNo())) {
CoreRoleAuthority selected = coreRoleService.getAuthorityMapper().selectOne(new QueryWrapper<CoreRoleAuthority>()
.eq("no", dto.getParentNo())
.eq("is_deleted", 0)
.last("limit 1")
);
parentId = selected == null ? "" : selected.getId();
} else {
parentId = "";
}
List<CoreRoleAuthority> collect = allOwnerMenus.stream()
.filter(it -> Objects.equals(it.getType(), "point"))
.filter(it -> it.getService().equals(dto.getService()))
.filter(it -> it.getPlatform().equals(dto.getPlatform()))
.filter(it -> {
if (StrUtil.isNotEmpty(parentId)) {
return parentId.equals(it.getParent());
}
return true;
}).collect(Collectors.toList());
return ApiResp.respOK(collect);
}
}

View File

@@ -0,0 +1,122 @@
package com.tiesheng.role.controller.role;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tiesheng.annotation.role.RoleAuthority;
import com.tiesheng.role.pojos.dao.CoreRoleGroup;
import com.tiesheng.role.pojos.dao.CoreRoleGroupRx;
import com.tiesheng.role.pojos.dto.GroupRxUpdateDTO;
import com.tiesheng.role.pojos.vo.GroupTypeDTO;
import com.tiesheng.role.service.CoreRoleService;
import com.tiesheng.util.exception.ApiException;
import com.tiesheng.util.pojos.ApiResp;
import com.tiesheng.util.pojos.IdDTO;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
import java.util.Objects;
@RestController
@RequestMapping("/role/group")
@RoleAuthority(value = "group", group = "role")
public class RoleGroupController {
@Resource
CoreRoleService coreRoleService;
/**
* 角色列表
*
* @return
*/
@GetMapping("/page")
public ApiResp<List<CoreRoleGroup>> groupPage(@Valid GroupTypeDTO dto) {
QueryWrapper<CoreRoleGroup> queryWrapper = new QueryWrapper<CoreRoleGroup>()
.eq("is_deleted", 0)
.eq(StrUtil.isNotEmpty(dto.getType()), "type", dto.getType())
.orderByAsc("sort");
dto.likeColumns(queryWrapper, "name");
Page<CoreRoleGroup> page = dto.pageObj();
coreRoleService.page(page, queryWrapper);
return ApiResp.respOK(page.getRecords(), page.getTotal());
}
/**
* 角色编辑
*
* @param roleGroup
* @return
*/
@PostMapping("/update")
public ApiResp<String> groupUpdate(@RequestBody CoreRoleGroup roleGroup) {
if (StrUtil.isNotEmpty(roleGroup.getId())) {
roleGroup.setType(null);
roleGroup.setIsSystem(null);
}
coreRoleService.saveOrUpdate(roleGroup);
return ApiResp.respOK("");
}
/**
* 角色-删除
*
* @return
*/
@PostMapping("/deleted")
public ApiResp<String> groupDeleted(@RequestBody @Valid IdDTO dto) {
CoreRoleGroup byId = coreRoleService.getById(dto.getId());
if (byId == null || byId.getIsDeleted() != 0) {
throw new ApiException("角色不存在或已删除");
}
if (byId.getIsSystem() == 1) {
throw new ApiException(StrUtil.format("该{}无法删除",
Objects.equals(byId.getType(), "role") ? "角色" : "职位"));
}
CoreRoleGroup coreServiceMenu = new CoreRoleGroup();
coreServiceMenu.setId(dto.getId());
coreServiceMenu.setIsDeleted(1);
coreRoleService.updateById(coreServiceMenu);
return ApiResp.respOK("");
}
/**
* 获取角色的权限
*
* @return
*/
@GetMapping("/rx/list")
public ApiResp<List<CoreRoleGroupRx>> groupRxList(@Valid IdDTO dto) {
List<CoreRoleGroupRx> list = coreRoleService.getGroupRxMapper().selectList(new QueryWrapper<CoreRoleGroupRx>()
.eq(CoreRoleGroupRx.IS_DELETED, 0)
.eq("group_id", dto.getId())
);
return ApiResp.respOK(list);
}
/**
* 角色的权限编辑
*
* @return
*/
@PostMapping("/rx/update")
public ApiResp<String> groupRxUpdate(@RequestBody @Valid GroupRxUpdateDTO dto) {
coreRoleService.updateGroupRx(dto);
return ApiResp.respOK("");
}
}

View File

@@ -0,0 +1,95 @@
package com.tiesheng.role.controller.role;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tiesheng.annotation.role.RoleAuthority;
import com.tiesheng.role.pojos.dao.CoreRoleAuthority;
import com.tiesheng.role.pojos.dao.CoreRoleServer;
import com.tiesheng.role.pojos.dto.MenuListDTO;
import com.tiesheng.role.pojos.vo.ServiceMenuVO;
import com.tiesheng.role.service.CoreRoleService;
import com.tiesheng.util.pojos.ApiResp;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
@RestController
@RequestMapping("/role")
@RoleAuthority(value = "server", group = "role")
public class RoleServerController {
@Resource
CoreRoleService coreRoleService;
/**
* 获取服务列表
*
* @return
*/
@GetMapping("/server/list")
public ApiResp<List<CoreRoleServer>> list() {
return ApiResp.respOK(coreRoleService.getServerMapper().selectList(new QueryWrapper<CoreRoleServer>()
.eq(CoreRoleServer.IS_DELETED, 0)
.eq("is_open", 1)
));
}
/**
* 修改服务
*
* @param coreService
* @return
*/
@PostMapping("/server/update")
public ApiResp<String> update(@RequestBody CoreRoleServer coreService) {
if (StrUtil.isNotEmpty(coreService.getId())) {
coreRoleService.getServerMapper().updateById(coreService);
} else {
coreRoleService.getServerMapper().insert(coreService);
}
return ApiResp.respOK("");
}
/**
* 权限-列出
*
* @return
*/
@GetMapping("/authority/list")
public ApiResp<List<ServiceMenuVO>> menuList(@Valid MenuListDTO dto) {
List<CoreRoleAuthority> list = coreRoleService.getAuthorityMapper().selectList(new QueryWrapper<CoreRoleAuthority>()
.eq(CoreRoleAuthority.IS_DELETED, 0)
.eq("service", dto.getService())
.eq(StrUtil.isNotEmpty(dto.getPlatform()), "platform", dto.getPlatform())
.orderByAsc("sort")
);
List<ServiceMenuVO> collect = coreRoleService.menuChildrenWrap(list, null);
return ApiResp.respOK(collect);
}
/**
* 权限-编辑
*
* @return
*/
@PostMapping("/authority/update")
public ApiResp<String> menuUpdate(@RequestBody CoreRoleAuthority serviceMenu) {
serviceMenu.setParent(StrUtil.emptyToDefault(serviceMenu.getParent(), null));
if (StrUtil.isEmpty(serviceMenu.getId())) {
coreRoleService.getAuthorityMapper().insert(serviceMenu);
} else {
serviceMenu.setNo(null);
coreRoleService.getAuthorityMapper().updateById(serviceMenu);
}
return ApiResp.respOK("");
}
}

View File

@@ -0,0 +1,69 @@
package com.tiesheng.role.controller.role;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tiesheng.annotation.role.RoleAuthority;
import com.tiesheng.role.pojos.dao.CoreRoleUser;
import com.tiesheng.role.pojos.vo.RoleUserPageVO;
import com.tiesheng.role.service.CoreRoleService;
import com.tiesheng.util.pojos.ApiResp;
import com.tiesheng.util.pojos.IdDTO;
import com.tiesheng.util.pojos.PageDTO;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
@RestController
@RequestMapping("/role/user")
@RoleAuthority(value = "user", group = "role")
public class RoleUserController {
@Resource
CoreRoleService coreRoleService;
/**
* 授权列表
*
* @return
*/
@GetMapping("/page")
public ApiResp<List<RoleUserPageVO>> userPage(PageDTO dto) {
QueryWrapper<CoreRoleUser> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("cru.is_deleted", 0);
dto.likeColumns(queryWrapper, "cru.ext1", "cru.ext2", "cru.ext3");
queryWrapper.orderByAsc("cru.user_id");
Page<RoleUserPageVO> page = dto.pageObj();
coreRoleService.getUserMapper().page(page, queryWrapper);
return ApiResp.respOK(page.getRecords(), page.getTotal());
}
/**
* 授权调整
*
* @return
*/
@PostMapping("/update")
public ApiResp<String> userUpdate(@RequestBody CoreRoleUser roleUser) {
coreRoleService.roleUserUpdate(roleUser);
return ApiResp.respOK("");
}
/**
* 授权-删除
*
* @return
*/
@PostMapping("/deleted")
public ApiResp<String> userDeleted(@RequestBody @Valid IdDTO dto) {
coreRoleService.roleUserDeleted(dto.getId());
return ApiResp.respOK("");
}
}

View File

@@ -3,5 +3,13 @@ package com.tiesheng.role.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tiesheng.role.pojos.dao.CoreRoleAuthority; import com.tiesheng.role.pojos.dao.CoreRoleAuthority;
import java.util.List;
public interface CoreRoleAuthorityMapper extends BaseMapper<CoreRoleAuthority> { public interface CoreRoleAuthorityMapper extends BaseMapper<CoreRoleAuthority> {
/**
* 批量插入数据
*
* @param coreRoleAuthorities
*/
void batchInsert(List<CoreRoleAuthority> coreRoleAuthorities);
} }

View File

@@ -1,11 +1,8 @@
package com.tiesheng.role.pojos.dao; package com.tiesheng.role.pojos.dao;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import com.tiesheng.util.pojos.DaoBase; import com.tiesheng.util.pojos.DaoBase;
import java.util.Date;
/** /**
* 角色-权限 * 角色-权限
@@ -78,6 +75,12 @@ public class CoreRoleAuthority extends DaoBase {
@TableField(value = "platform") @TableField(value = "platform")
private String platform; private String platform;
/**
* 版本号
*/
@TableField(value = "version")
private String version;
/** /**
* 扩展1 * 扩展1
*/ */
@@ -294,6 +297,24 @@ public class CoreRoleAuthority extends DaoBase {
this.platform = platform; this.platform = platform;
} }
/**
* 获取版本号
*
* @return version - 版本号
*/
public String getVersion() {
return version;
}
/**
* 设置版本号
*
* @param version 版本号
*/
public void setVersion(String version) {
this.version = version;
}
/** /**
* 获取扩展1 * 获取扩展1
* *
@@ -347,4 +368,4 @@ public class CoreRoleAuthority extends DaoBase {
public void setExt3(String ext3) { public void setExt3(String ext3) {
this.ext3 = ext3; this.ext3 = ext3;
} }
} }

View File

@@ -1,10 +1,9 @@
package com.tiesheng.role.pojos.vo; package com.tiesheng.role.pojos.vo;
import javax.validation.constraints.NotEmpty; import com.tiesheng.util.pojos.PageDTO;
public class GroupTypeDTO { public class GroupTypeDTO extends PageDTO {
@NotEmpty(message = "请选择一个类型")
private String type; private String type;
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////

View File

@@ -1,42 +1,51 @@
package com.tiesheng.role.service; package com.tiesheng.role.service;
import cn.hutool.core.annotation.AnnotationUtil;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tiesheng.annotation.role.RoleAuthority;
import com.tiesheng.role.mapper.*; import com.tiesheng.role.mapper.*;
import com.tiesheng.role.pojos.dao.CoreRoleAuthority; import com.tiesheng.role.pojos.dao.CoreRoleAuthority;
import com.tiesheng.role.pojos.dao.CoreRoleGroup; import com.tiesheng.role.pojos.dao.CoreRoleGroup;
import com.tiesheng.role.pojos.dao.CoreRoleGroupRx; import com.tiesheng.role.pojos.dao.CoreRoleGroupRx;
import com.tiesheng.role.pojos.dao.CoreRoleUser;
import com.tiesheng.role.pojos.dto.GroupRxUpdateDTO; import com.tiesheng.role.pojos.dto.GroupRxUpdateDTO;
import com.tiesheng.role.pojos.dto.OwnerMenuDTO; import com.tiesheng.role.pojos.dto.OwnerMenuDTO;
import com.tiesheng.role.pojos.vo.ServiceMenuVO; import com.tiesheng.role.pojos.vo.ServiceMenuVO;
import com.tiesheng.util.exception.ApiException;
import com.tiesheng.util.service.TsCacheService;
import com.tiesheng.util.service.TsServiceBase; import com.tiesheng.util.service.TsServiceBase;
import com.tiesheng.util.service.role.TsAuthorityHandler;
import org.springframework.aop.support.AopUtils;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.ArrayList; import java.lang.reflect.Method;
import java.util.List; import java.util.*;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Service @Service
public class CoreRoleService extends TsServiceBase<CoreRoleGroupMapper, CoreRoleGroup> { public class CoreRoleService extends TsServiceBase<CoreRoleGroupMapper, CoreRoleGroup>
implements ApplicationListener<ContextRefreshedEvent> {
@Resource @Resource
CoreRoleUserMapper coreRoleUserMapper; CoreRoleUserMapper coreRoleUserMapper;
@Resource @Resource
CoreRoleGroupRxMapper coreRoleGroupRxMapper; CoreRoleGroupRxMapper coreRoleGroupRxMapper;
@Resource @Resource
CoreRoleAuthorityMapper coreRoleAuthorityMapper; CoreRoleAuthorityMapper coreRoleAuthorityMapper;
@Resource @Resource
CoreRoleServerMapper coreRoleServerMapper; CoreRoleServerMapper coreRoleServerMapper;
@Resource
TsAuthorityHandler tsAuthorityHandler;
public CoreRoleServerMapper getServerMapper() { public CoreRoleServerMapper getServerMapper() {
return coreRoleServerMapper; return coreRoleServerMapper;
@@ -91,17 +100,70 @@ public class CoreRoleService extends TsServiceBase<CoreRoleGroupMapper, CoreRole
coreRoleGroupRxMapper.delete(new QueryWrapper<CoreRoleGroupRx>() coreRoleGroupRxMapper.delete(new QueryWrapper<CoreRoleGroupRx>()
.eq("group_id", dto.getId()) .eq("group_id", dto.getId())
); );
CoreRoleGroup roleGroup = getById(dto.getId());
Validator.validateNotEmpty(roleGroup, "角色不存在");
List<CoreRoleAuthority> authorities = coreRoleAuthorityMapper.selectList(new QueryWrapper<CoreRoleAuthority>()
.eq(CoreRoleAuthority.IS_DELETED, 0)
.in("id", dto.getMenuIds())
);
List<CoreRoleGroupRx> list = new ArrayList<>(); List<CoreRoleGroupRx> list = new ArrayList<>();
for (String menuId : dto.getMenuIds()) { for (CoreRoleAuthority authority : authorities) {
CoreRoleGroupRx coreRoleGroupRx = new CoreRoleGroupRx(); CoreRoleGroupRx coreRoleGroupRx = new CoreRoleGroupRx();
coreRoleGroupRx.setGroupId(dto.getId()); coreRoleGroupRx.setGroupId(roleGroup.getId());
coreRoleGroupRx.setMenuId(menuId); coreRoleGroupRx.setMenuId(authority.getId());
list.add(coreRoleGroupRx); list.add(coreRoleGroupRx);
} }
if (CollUtil.isNotEmpty(list)) { if (CollUtil.isNotEmpty(list)) {
coreRoleGroupRxMapper.batchInsert(list); coreRoleGroupRxMapper.batchInsert(list);
onRoleChange(dto.getId(), "");
} }
}
/**
* 编辑、更新用户的授权
*
* @param roleUser
*/
public void roleUserUpdate(CoreRoleUser roleUser) {
if (StrUtil.isNotEmpty(roleUser.getId())) {
coreRoleUserMapper.updateById(roleUser);
} else {
coreRoleUserMapper.insert(roleUser);
}
onRoleChange(roleUser.getTypeId(), roleUser.getUserId());
}
/**
* 删除用户授权
*
* @param recordId
*/
public void roleUserDeleted(String recordId) {
CoreRoleUser coreRoleUser = coreRoleUserMapper.selectById(recordId);
if (coreRoleUser == null || coreRoleUser.getIsDeleted() == 1) {
throw new ApiException("该授权已被删除");
}
coreRoleUser.setIsDeleted(1);
coreRoleUserMapper.updateById(coreRoleUser);
onRoleChange(coreRoleUser.getTypeId(), coreRoleUser.getUserId());
}
/**
* 当授权发生变化时
*/
public void onRoleChange(String roleId, String userId) {
TsCacheService.of().keys(StrUtil.format(TsAuthorityHandler.CACHE_HAS_AUTHORITY,
roleId, userId)).forEach(key -> TsCacheService.of().remove(key));
} }
@@ -155,4 +217,35 @@ public class CoreRoleService extends TsServiceBase<CoreRoleGroupMapper, CoreRole
.collect(Collectors.toList()), null); .collect(Collectors.toList()), null);
} }
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
ApplicationContext applicationContext = event.getApplicationContext();
Map<String, Object> beansOfType = applicationContext.getBeansWithAnnotation(RoleAuthority.class);
String version = DateUtil.format(new Date(), "yyyyMMddHHmmss");
for (Map.Entry<String, Object> entry : beansOfType.entrySet()) {
Class<?> targetClass = AopUtils.getTargetClass(entry.getValue());
RoleAuthority menu = targetClass.getAnnotation(RoleAuthority.class);
List<RoleAuthority> points = new ArrayList<>();
Method[] methods = targetClass.getDeclaredMethods();
for (Method method : methods) {
RoleAuthority methodAuthority = AnnotationUtil.getAnnotation(method, RoleAuthority.class);
if (methodAuthority != null) {
points.add(methodAuthority);
}
}
tsAuthorityHandler.addRoleAuthority(version, menu, points);
}
coreRoleAuthorityMapper.delete(new QueryWrapper<CoreRoleAuthority>()
.ne("version", version)
);
}
} }

View File

@@ -0,0 +1,102 @@
package com.tiesheng.role.service;
import cn.hutool.core.util.StrUtil;
import com.tiesheng.annotation.role.RoleAuthority;
import com.tiesheng.role.mapper.CoreRoleAuthorityMapper;
import com.tiesheng.role.mapper.CoreRoleUserMapper;
import com.tiesheng.role.pojos.dao.CoreRoleAuthority;
import com.tiesheng.util.config.GlobalConfig;
import com.tiesheng.util.pojos.TokenBean;
import com.tiesheng.util.service.role.TsAuthorityHandler;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class RoleAuthorityHandler implements TsAuthorityHandler {
@Resource
CoreRoleAuthorityMapper coreRoleAuthorityMapper;
@Resource
GlobalConfig globalConfig;
@Resource
CoreRoleUserMapper coreRoleUserMapper;
@Override
public void addRoleAuthority(String version, RoleAuthority menu, List<RoleAuthority> points) {
if (menu.group().length == 0) {
return;
}
List<CoreRoleAuthority> list = new ArrayList<>();
// 分组
CoreRoleAuthority groupAuthority = new CoreRoleAuthority();
groupAuthority.setLevel(0);
for (String group : menu.group()) {
String parentId = groupAuthority.getId();
int level = groupAuthority.getLevel() + 1;
String no = group;
if (StrUtil.isNotEmpty(groupAuthority.getNo())) {
no = StrUtil.join("_", groupAuthority.getNo(), group);
}
groupAuthority = new CoreRoleAuthority();
groupAuthority.setNo(no);
groupAuthority.setName(group);
groupAuthority.setService(globalConfig.getService());
groupAuthority.setType("group");
groupAuthority.setLevel(level);
groupAuthority.setPlatform(menu.platform());
groupAuthority.setParent(parentId);
groupAuthority.setVersion(version);
groupAuthority.setId(StrUtil.join("_", groupAuthority.getService(), groupAuthority.getNo()));
list.add(groupAuthority);
}
// 菜单
CoreRoleAuthority menuAuthority = new CoreRoleAuthority();
menuAuthority.setNo(StrUtil.join("_", menu.group(), menu.value()));
menuAuthority.setName(menu.value());
menuAuthority.setService(globalConfig.getService());
menuAuthority.setType("menu");
menuAuthority.setLevel(groupAuthority.getLevel() + 1);
menuAuthority.setParent(groupAuthority.getId());
menuAuthority.setPlatform(menu.platform());
menuAuthority.setVersion(version);
menuAuthority.setId(StrUtil.join("_", menuAuthority.getService(), menuAuthority.getNo()));
list.add(menuAuthority);
// 功能点
for (RoleAuthority authority : points) {
CoreRoleAuthority point = new CoreRoleAuthority();
point.setNo(StrUtil.join("_", menuAuthority.getNo(), authority.value()));
point.setName(authority.value());
point.setService(globalConfig.getService());
point.setType("point");
point.setLevel(menuAuthority.getLevel() + 1);
point.setParent(menuAuthority.getId());
point.setVersion(version);
point.setPlatform(StrUtil.emptyToDefault(authority.platform(), menu.platform()));
point.setId(StrUtil.join("_", point.getService(), point.getNo()));
list.add(point);
}
coreRoleAuthorityMapper.batchInsert(list);
}
@Override
public List<String> getAuthorities(TokenBean tokenBean) {
List<CoreRoleAuthority> list = coreRoleUserMapper.getOwnerAuthorityLeafList(tokenBean.getId(),
tokenBean.getRoleId());
return list.stream().map(CoreRoleAuthority::getNo).distinct().collect(Collectors.toList());
}
}

View File

@@ -1,3 +1,6 @@
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
create table core_role_authority create table core_role_authority
( (
id varchar(50) not null id varchar(50) not null
@@ -93,3 +96,7 @@ create table core_role_user
DEFAULT CHARSET = utf8mb4 DEFAULT CHARSET = utf8mb4
comment '角色-用户'; comment '角色-用户';
alter table core_role_authority
add version varchar(50) null comment '版本号' after platform;
SET FOREIGN_KEY_CHECKS = 1;

View File

@@ -19,13 +19,39 @@
<result column="type" jdbcType="VARCHAR" property="type" /> <result column="type" jdbcType="VARCHAR" property="type" />
<result column="link" jdbcType="LONGVARCHAR" property="link" /> <result column="link" jdbcType="LONGVARCHAR" property="link" />
<result column="platform" jdbcType="VARCHAR" property="platform" /> <result column="platform" jdbcType="VARCHAR" property="platform" />
<result column="version" jdbcType="VARCHAR" property="version" />
<result column="ext1" jdbcType="VARCHAR" property="ext1" /> <result column="ext1" jdbcType="VARCHAR" property="ext1" />
<result column="ext2" jdbcType="VARCHAR" property="ext2" /> <result column="ext2" jdbcType="VARCHAR" property="ext2" />
<result column="ext3" jdbcType="VARCHAR" property="ext3" /> <result column="ext3" jdbcType="VARCHAR" property="ext3" />
</resultMap> </resultMap>
<sql id="Base_Column_List"> <sql id="Base_Column_List">
<!--@mbg.generated--> <!--@mbg.generated-->
id, create_time, update_time, is_deleted, service, `no`, `name`, sort, `level`, parent, id, create_time, update_time, is_deleted, service, `no`, `name`, sort, `level`, parent,
remark, is_open, `type`, link, platform, ext1, ext2, ext3 remark, is_open, `type`, link, platform, version, ext1, ext2, ext3
</sql> </sql>
</mapper>
<insert id="batchInsert">
insert into core_role_authority(id, create_time, update_time, is_deleted, service, no, name, level, parent,
type, platform, is_open, version)
values
<foreach collection="list" item="item" separator=",">
(#{item.id}, now(), now(), 0,
#{item.service},
#{item.no},
#{item.name},
#{item.level},
#{item.parent},
#{item.type},
#{item.platform}, 1, #{item.version})
</foreach>
on duplicate key update update_time=now(),
is_deleted=0,
level=values(level),
parent=values(parent),
type=values(type),
platform=values(platform),
version=values(version)
</insert>
</mapper>

View File

@@ -6,7 +6,7 @@
<parent> <parent>
<groupId>com.tiesheng.springboot-parent</groupId> <groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId> <artifactId>springboot-parent</artifactId>
<version>2.0.0.rc6</version> <version>2.0.0.rc21</version>
</parent> </parent>
<artifactId>springboot-util</artifactId> <artifactId>springboot-util</artifactId>
@@ -32,8 +32,21 @@
<dependency> <dependency>
<groupId>cn.hutool</groupId> <groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId> <artifactId>hutool-bom</artifactId>
<version>5.8.16</version> <version>5.8.16</version>
<type>pom</type>
<exclusions>
<exclusion>
<groupId>cn.hutool</groupId>
<artifactId>hutool-http</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version>
</dependency> </dependency>
<!-- MySql驱动 --> <!-- MySql驱动 -->
@@ -68,6 +81,17 @@
<version>1.68</version> <version>1.68</version>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<exclusions>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -1,25 +0,0 @@
package com.tiesheng.util;
import cn.hutool.cache.CacheUtil;
import cn.hutool.cache.impl.TimedCache;
public class TimedCacheHelper {
private static volatile TimedCache<String, String> timedCache;
/**
* 获取一个默认2分钟过期的缓存
*/
public static TimedCache<String, String> getTimedCache() {
if (timedCache == null) {
synchronized (TimedCacheHelper.class) {
if (timedCache == null) {
timedCache = CacheUtil.newTimedCache(2 * 60 * 1000);
timedCache.schedulePrune(1000);
}
}
}
return timedCache;
}
}

View File

@@ -8,8 +8,8 @@ import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.SmUtil; import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.symmetric.SM4; import cn.hutool.crypto.symmetric.SM4;
import com.tiesheng.util.ServletKit; import com.tiesheng.util.ServletKit;
import com.tiesheng.util.TimedCacheHelper;
import com.tiesheng.util.exception.ApiException; import com.tiesheng.util.exception.ApiException;
import com.tiesheng.util.service.TsCacheService;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@@ -104,12 +104,12 @@ public class EncryptConfig {
String salt = decrypt(encrypted).substring(0, saltSize); String salt = decrypt(encrypted).substring(0, saltSize);
String inputEncrypted = passwdCreate(inputPasswd, salt); String inputEncrypted = passwdCreate(inputPasswd, salt);
if (!StrUtil.equals(inputEncrypted, encrypted)) { if (!StrUtil.equals(inputEncrypted, encrypted)) {
String clientIp = ServletKit.getClientIP(); String clientIp = "passwdVerify_" + ServletKit.getClientIP();
int num = NumberUtil.parseInt(TimedCacheHelper.getTimedCache().get(clientIp, false)); int num = NumberUtil.parseInt(TsCacheService.of().get(clientIp, -1));
if (num > 5) { if (num > 5) {
throw new ApiException("登录失败已达6次请10分钟后再试"); throw new ApiException("登录失败已达6次请10分钟后再试");
} }
TimedCacheHelper.getTimedCache().put(clientIp, String.valueOf(num + 1), 10 * 60 * 1000); TsCacheService.of().put(clientIp, String.valueOf(num + 1), 10 * 60);
throw new ApiException("账号或密码错误"); throw new ApiException("账号或密码错误");
} }
} }

View File

@@ -4,9 +4,7 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.comparator.VersionComparator; import cn.hutool.core.comparator.VersionComparator;
import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import cn.hutool.extra.spring.SpringUtil; import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.http.HttpGlobalConfig;
import cn.hutool.log.LogFactory; import cn.hutool.log.LogFactory;
import com.tiesheng.util.exception.ApiException; import com.tiesheng.util.exception.ApiException;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
@@ -14,7 +12,6 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import javax.annotation.PostConstruct;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@@ -40,14 +37,6 @@ public class GlobalConfig {
private HashMap<String, String> ext; private HashMap<String, String> ext;
@PostConstruct
public void init() {
// 默认10s的超时时间
HttpGlobalConfig.setTimeout(10 * 1000);
// 最多重定向3次
HttpGlobalConfig.setMaxRedirectCount(3);
}
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// 逻辑方法 // 逻辑方法
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////

View File

@@ -1,9 +1,9 @@
package com.tiesheng.util.config; package com.tiesheng.util.config;
import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.FileUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.log.LogFactory; import cn.hutool.log.LogFactory;
import com.tiesheng.util.ip2region.Searcher; import com.tiesheng.util.ip2region.Searcher;
import com.tiesheng.util.service.http.OkHttpUtil;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@@ -27,7 +27,7 @@ public class Ip2regionConfig {
public void downloadDbFile() { public void downloadDbFile() {
if (!FileUtil.exist(dbPath)) { if (!FileUtil.exist(dbPath)) {
LogFactory.get().info("download ip2region file start"); LogFactory.get().info("download ip2region file start");
HttpUtil.downloadFile(dbUrl, dbPath); OkHttpUtil.downloadFile(dbUrl, dbPath);
LogFactory.get().info("download ip2region file finish"); LogFactory.get().info("download ip2region file finish");
} }
} }

View File

@@ -23,6 +23,12 @@ import java.util.Map;
@ConfigurationProperties("tiesheng.token") @ConfigurationProperties("tiesheng.token")
public class TsTokenConfig { public class TsTokenConfig {
/**
* 用户登录的KEY
*/
public static String CACHE_REQUEST_LOGIN_KEY = "CACHE:LOGIN:{}";
/** /**
* token常量 * token常量
*/ */
@@ -79,7 +85,7 @@ public class TsTokenConfig {
} catch (Exception ignored) { } catch (Exception ignored) {
} }
if (tokenBean == null && thrExp) { if ((tokenBean == null || StrUtil.isEmpty(tokenBean.getId())) && thrExp) {
throw new ApiException(StrUtil.isEmpty(token) ? 110 : 112, throw new ApiException(StrUtil.isEmpty(token) ? 110 : 112,
StrUtil.isEmpty(token) ? "请先登录" : "登录过期,请重新登陆"); StrUtil.isEmpty(token) ? "请先登录" : "登录过期,请重新登陆");
} }

View File

@@ -129,6 +129,19 @@ public class ApiResp<T> {
} }
/**
* 130错误
*
* @param msg
* @return
*/
public static ApiResp<String> resp130(String msg) {
ApiResp<String> result = new ApiResp<>();
result.code = 130;
result.message = msg;
return result;
}
/** /**
* 是否成功 * 是否成功
* *

View File

@@ -6,8 +6,8 @@ import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil; import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.http.HttpUtil;
import com.tiesheng.util.config.GlobalConfig; import com.tiesheng.util.config.GlobalConfig;
import com.tiesheng.util.service.http.OkHttpUtil;
public class FileUploadPath { public class FileUploadPath {
@@ -71,7 +71,7 @@ public class FileUploadPath {
String newFileName = UPLOAD_FOLDER + StrUtil.subAfter(httpUrl, UPLOAD_FOLDER, true); String newFileName = UPLOAD_FOLDER + StrUtil.subAfter(httpUrl, UPLOAD_FOLDER, true);
FileUploadPath uploadPath = file(newFileName); FileUploadPath uploadPath = file(newFileName);
if (!FileUtil.exist(uploadPath.getAbsolutePath())) { if (!FileUtil.exist(uploadPath.getAbsolutePath())) {
HttpUtil.downloadFile(httpUrl, uploadPath.getAbsolutePath()); OkHttpUtil.downloadFile(httpUrl, uploadPath.getAbsolutePath());
} }
return uploadPath.getHttpPath(); return uploadPath.getHttpPath();

View File

@@ -12,19 +12,15 @@ import com.tiesheng.util.config.TsTokenConfig;
public class TokenBean { public class TokenBean {
private String id; private String id;
private String environmentType;
private String service;
private String roleId; private String roleId;
private String extra; private String extra;
public TokenBean() { public TokenBean() {
} }
public TokenBean(String id, String environmentType, String service) { public TokenBean(String id, String roleId) {
this.id = id; this.id = id;
this.environmentType = environmentType; this.roleId = roleId;
this.service = service;
this.roleId = "";
this.extra = ""; this.extra = "";
} }
@@ -37,8 +33,6 @@ public class TokenBean {
return JWT.create() return JWT.create()
.setExpiresAt(DateUtil.offsetHour(DateUtil.date(), tsTokenConfig.getExpireHours())) .setExpiresAt(DateUtil.offsetHour(DateUtil.date(), tsTokenConfig.getExpireHours()))
.setPayload("id", getId()) .setPayload("id", getId())
.setPayload("environmentType", StrUtil.emptyToDefault(getEnvironmentType(), ""))
.setPayload("service", StrUtil.emptyToDefault(getService(), ""))
.setPayload("roleId", StrUtil.emptyToDefault(getRoleId(), "")) .setPayload("roleId", StrUtil.emptyToDefault(getRoleId(), ""))
.setPayload("extra", StrUtil.emptyToDefault(getExtra(), "")) .setPayload("extra", StrUtil.emptyToDefault(getExtra(), ""))
.setKey(tsTokenConfig.getEncryptKey().getBytes()) .setKey(tsTokenConfig.getEncryptKey().getBytes())
@@ -57,22 +51,6 @@ public class TokenBean {
this.id = id; this.id = id;
} }
public String getEnvironmentType() {
return environmentType;
}
public void setEnvironmentType(String environmentType) {
this.environmentType = environmentType;
}
public String getService() {
return service;
}
public void setService(String service) {
this.service = service;
}
public String getExtra() { public String getExtra() {
return extra; return extra;
} }

View File

@@ -0,0 +1,95 @@
package com.tiesheng.util.service;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.tiesheng.util.ServletKit;
import com.tiesheng.util.exception.ApiException;
import com.tiesheng.util.service.cache.TsCacheHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Set;
@Service
public class TsCacheService {
@Autowired
TsCacheHandler tsCacheHandler;
/**
* 获取一个缓存
*
* @return
*/
public static TsCacheService of() {
return SpringUtil.getBean(TsCacheService.class);
}
public void put(String key, String value) {
tsCacheHandler.put(key, value);
}
public void put(String key, String value, long seconds) {
tsCacheHandler.put(key, value, seconds);
}
public void putObj(String key, Object value, long seconds) {
tsCacheHandler.put(key, JSONUtil.toJsonStr(value), seconds);
}
public String get(String key) {
return tsCacheHandler.get(key);
}
public String get(String key, long seconds) {
return tsCacheHandler.get(key, seconds);
}
/**
* 获取一个缓存对象
*
* @param key
* @param tClass
* @param seconds =0时获取数据后会删除缓存<0时不改变原有缓存时间
* @param <T>
* @return
*/
public <T> T getObj(String key, Class<T> tClass, long seconds) {
return JSONUtil.toBean(get(key, seconds), tClass, true);
}
public void remove(String key) {
tsCacheHandler.remove(key);
}
/**
* 获取key
*
* @param pattern
* @return
*/
public Set<String> keys(String pattern) {
return tsCacheHandler.keys(pattern);
}
///////////////////////////////////////////////////////////////////////////
// 图形验证码
///////////////////////////////////////////////////////////////////////////
/**
* 验证 图片验证码
*/
public void verifyCaptcha(String value) {
String captchaKey = ServletUtil.getHeader(ServletKit.getRequest(), "captcha", "utf-8");
String cache = get(captchaKey);
if (StrUtil.isEmpty(cache) || !StrUtil.equals(cache, value)) {
throw new ApiException("验证码不正确");
}
remove(captchaKey);
}
}

View File

@@ -0,0 +1,21 @@
package com.tiesheng.util.service.cache;
import java.util.Set;
public interface TsCacheHandler {
String name();
void put(String key, String value);
void put(String key, String value, long timeout);
String get(String key);
String get(String key, long timeout);
void remove(String key);
Set<String> keys(String prefix);
}

View File

@@ -0,0 +1,62 @@
package com.tiesheng.util.service.cache;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import javax.annotation.Resource;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@Configuration
@ConditionalOnProperty("spring.redis.url")
public class TsCacheRedisHandler implements TsCacheHandler {
@Resource
RedisTemplate<String, String> redisTemplate;
@Override
public String name() {
return "RedisCache";
}
@Override
public void put(String key, String value) {
redisTemplate.opsForValue().set(key, value, 2 * 60, TimeUnit.SECONDS);
}
@Override
public void put(String key, String value, long seconds) {
redisTemplate.opsForValue().set(key, value, seconds, TimeUnit.SECONDS);
}
@Override
public String get(String key) {
return redisTemplate.opsForValue().get(key);
}
@Override
public String get(String key, long seconds) {
if (seconds > 0) {
return redisTemplate.opsForValue().getAndExpire(key, seconds, TimeUnit.SECONDS);
} else if (seconds == 0) {
return redisTemplate.opsForValue().getAndDelete(key);
}
return redisTemplate.opsForValue().get(key);
}
@Override
public void remove(String key) {
redisTemplate.delete(key);
}
@Override
public Set<String> keys(String prefix) {
return redisTemplate.keys(prefix + "*");
}
}

View File

@@ -0,0 +1,77 @@
package com.tiesheng.util.service.cache;
import cn.hutool.cache.CacheUtil;
import cn.hutool.cache.impl.TimedCache;
import cn.hutool.core.util.StrUtil;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Configuration;
import java.util.Set;
import java.util.stream.Collectors;
@Configuration
@ConditionalOnMissingBean(value = TsCacheHandler.class, ignored = {TsCacheTimedHandler.class, TsCacheTimedHandler.class})
public class TsCacheTimedHandler implements TsCacheHandler {
private static volatile TimedCache<String, String> timedCache;
/**
* 获取一个默认2分钟过期的缓存
*/
private static TimedCache<String, String> getTimedCache() {
if (timedCache == null) {
synchronized (TsCacheTimedHandler.class) {
if (timedCache == null) {
timedCache = CacheUtil.newTimedCache(2 * 60 * 1000);
timedCache.schedulePrune(1000);
}
}
}
return timedCache;
}
@Override
public String name() {
return "TimedCache";
}
@Override
public void put(String key, String value) {
getTimedCache().put(key, value);
}
@Override
public void put(String key, String value, long seconds) {
getTimedCache().put(key, value, seconds * 1000);
}
@Override
public String get(String key) {
return getTimedCache().get(key);
}
@Override
public String get(String key, long seconds) {
String value = getTimedCache().get(key, false);
if (seconds > 0) {
getTimedCache().put(key, value, seconds * 1000);
} else if (seconds == 0) {
getTimedCache().remove(key);
}
return value;
}
@Override
public void remove(String key) {
getTimedCache().remove(key);
}
@Override
public Set<String> keys(String prefix) {
return getTimedCache().keySet().stream().filter(key -> StrUtil.startWith(key, prefix))
.collect(Collectors.toSet());
}
}

View File

@@ -0,0 +1,52 @@
package com.tiesheng.util.service.http;
import okhttp3.Interceptor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Component
public class OkHttpConfig implements ApplicationListener<ContextRefreshedEvent> {
/**
* 全局连接超时
*/
public static int GLOBAL_TIMEOUT = 5 * 1000;
/**
* 全局拦截器
*/
public static final List<Interceptor> INTERCEPTORS = new ArrayList<>();
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
ApplicationContext applicationContext = event.getApplicationContext();
Map<String, Interceptor> beansOfType = applicationContext.getBeansOfType(Interceptor.class);
for (Map.Entry<String, Interceptor> entry : beansOfType.entrySet()) {
INTERCEPTORS.add(entry.getValue());
}
}
///////////////////////////////////////////////////////////////////////////
// setter、getter
///////////////////////////////////////////////////////////////////////////
/**
* 设置全局超时时间
*
* @param timeout
*/
public static void setGlobalTimeout(int timeout) {
GLOBAL_TIMEOUT = timeout;
}
}

View File

@@ -0,0 +1,167 @@
package com.tiesheng.util.service.http;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.net.url.UrlQuery;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONObject;
import okhttp3.*;
import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.TimeUnit;
public class OkHttpUtil {
/**
* 创建客户端
*
* @return
*/
public static OkHttpClient.Builder ofHttpClient() {
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.connectTimeout(OkHttpConfig.GLOBAL_TIMEOUT, TimeUnit.MILLISECONDS)
.readTimeout(OkHttpConfig.GLOBAL_TIMEOUT, TimeUnit.MILLISECONDS);
for (Interceptor interceptor : OkHttpConfig.INTERCEPTORS) {
builder.addInterceptor(interceptor);
}
return builder;
}
public static Request ofRequest(String method, String url, RequestBody body) {
return new Request.Builder()
.url(url).method(method, body).build();
}
public static Request ofGet(String url) {
return ofRequest("GET", url, null);
}
public static Request ofPost(String url, JSONObject body) {
return ofRequest("POST", url, ofJsonBody(body.toString()));
}
public static Request ofPost(String url, RequestBody body) {
return ofRequest("POST", url, body);
}
public static RequestBody ofJsonBody(String json) {
return RequestBody.create(MediaType.parse("application/json; charset=utf-8"), json);
}
public static ResponseBody ofJsonResponse(String json) {
return ResponseBody.create(MediaType.parse("application/json; charset=utf-8"), json);
}
public static MultipartBody.Builder ofMultipartBody(File file) {
return new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("file", file.getName(),
RequestBody.create(MediaType.parse("application/octet-stream"), file));
}
///////////////////////////////////////////////////////////////////////////
// get请求
///////////////////////////////////////////////////////////////////////////
public static String get(String urlString) {
return get(urlString, OkHttpConfig.GLOBAL_TIMEOUT);
}
public static String get(String urlString, Map<String, Object> queryMap) {
String build = UrlQuery.of(queryMap).build(CharsetUtil.CHARSET_UTF_8);
if (StrUtil.contains(urlString, "?")) {
urlString = urlString + "&" + build;
} else {
urlString = urlString + "?" + build;
}
return get(urlString, OkHttpConfig.GLOBAL_TIMEOUT);
}
public static String get(String urlString, int timeout) {
try {
return ofHttpClient().connectTimeout(timeout, TimeUnit.MILLISECONDS)
.build().newCall(ofGet(urlString)).execute().body().string();
} catch (IOException ignored) {
}
return null;
}
///////////////////////////////////////////////////////////////////////////
// Post请求
///////////////////////////////////////////////////////////////////////////
public static String post(String urlString, Map<String, String> paramMap) {
return post(urlString, paramMap, OkHttpConfig.GLOBAL_TIMEOUT);
}
public static String post(String urlString, Map<String, String> paramMap, int timeout) {
FormBody.Builder formBuilder = new FormBody.Builder();
for (String key : paramMap.keySet()) {
formBuilder.add(key, paramMap.get(key));
}
return post(urlString, formBuilder.build(), timeout);
}
public static String post(String urlString, JSONObject body) {
return post(urlString, body, OkHttpConfig.GLOBAL_TIMEOUT);
}
public static String post(String urlString, JSONObject body, int timeout) {
return post(urlString, ofJsonBody(body.toString()), timeout);
}
public static String post(String urlString, RequestBody body, int timeout) {
try {
return ofHttpClient().connectTimeout(timeout, TimeUnit.MILLISECONDS)
.build().newCall(ofPost(urlString, body)).execute().body().string();
} catch (IOException ignored) {
}
return null;
}
///////////////////////////////////////////////////////////////////////////
// Download下载文件
///////////////////////////////////////////////////////////////////////////
public static File downloadFile(String url, String destFile) {
return downloadFile(url, FileUtil.file(destFile));
}
public static File downloadFile(String url, File destFile) {
try {
Response response = ofHttpClient()
.connectTimeout(0, TimeUnit.MILLISECONDS)
.readTimeout(0, TimeUnit.MILLISECONDS)
.build().newCall(ofGet(url)).execute();
if (response.isSuccessful() && response.body() != null) {
FileUtil.writeFromStream(response.body().byteStream(), destFile);
}
return destFile;
} catch (IOException ignored) {
}
return null;
}
public static byte[] downloadBytes(String url) {
try {
Response response = ofHttpClient()
.connectTimeout(0, TimeUnit.MILLISECONDS)
.readTimeout(0, TimeUnit.MILLISECONDS)
.build().newCall(ofGet(url)).execute();
if (response.isSuccessful() && response.body() != null) {
return response.body().bytes();
}
} catch (IOException ignored) {
}
return null;
}
}

View File

@@ -0,0 +1,33 @@
package com.tiesheng.util.service.role;
import com.tiesheng.annotation.role.RoleAuthority;
import com.tiesheng.util.pojos.TokenBean;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public interface TsAuthorityHandler {
String CACHE_HAS_AUTHORITY = "CACHE:HAS_AUTHORITY:{}:{}";
/**
* 添加所有的权限
*
* @param groupAuthority
* @param pointAuthorityList
* @return
*/
void addRoleAuthority(String version, RoleAuthority groupAuthority, List<RoleAuthority> pointAuthorityList);
/**
* 获取权限列表
*
* @param tokenBean
* @return
*/
List<String> getAuthorities(TokenBean tokenBean);
}

View File

@@ -6,7 +6,7 @@
<parent> <parent>
<groupId>com.tiesheng.springboot-parent</groupId> <groupId>com.tiesheng.springboot-parent</groupId>
<artifactId>springboot-parent</artifactId> <artifactId>springboot-parent</artifactId>
<version>2.0.0.rc6</version> <version>2.0.0.rc21</version>
</parent> </parent>
<artifactId>springboot-web</artifactId> <artifactId>springboot-web</artifactId>

View File

@@ -2,8 +2,8 @@ package com.tiesheng.web;
import com.tiesheng.database.DatabaseAutoConfigurer; import com.tiesheng.database.DatabaseAutoConfigurer;
import com.tiesheng.encrypt.EncryptAutoConfigurer; import com.tiesheng.encrypt.EncryptAutoConfigurer;
import com.tiesheng.login.LoginAutoConfigurer;
import com.tiesheng.message.MessageAutoConfigurer; import com.tiesheng.message.MessageAutoConfigurer;
import com.tiesheng.platform.PlatformAutoConfigurer;
import com.tiesheng.util.UtilAutoConfigurer; import com.tiesheng.util.UtilAutoConfigurer;
import com.tiesheng.web.service.TieshengWebConfigurer; import com.tiesheng.web.service.TieshengWebConfigurer;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
@@ -20,9 +20,9 @@ import java.lang.annotation.*;
UtilAutoConfigurer.class, UtilAutoConfigurer.class,
MessageAutoConfigurer.class, MessageAutoConfigurer.class,
WebAutoConfigurer.class, WebAutoConfigurer.class,
LoginAutoConfigurer.class,
DatabaseAutoConfigurer.class, DatabaseAutoConfigurer.class,
EncryptAutoConfigurer.class, EncryptAutoConfigurer.class,
PlatformAutoConfigurer.class,
}) })
public @interface EnableTieshengWeb { public @interface EnableTieshengWeb {

View File

@@ -10,7 +10,8 @@ import org.springframework.context.annotation.ComponentScan;
@ComponentScan({ @ComponentScan({
"com.tiesheng.web.**.*", "com.tiesheng.web.**.*",
"com.tiesheng.role.**.*", "com.tiesheng.role.**.*",
"com.tiesheng.login.**.*",
}) })
@MapperScan(value = {"com.tiesheng.web.mapper", "com.tiesheng.role.mapper"}) @MapperScan(value = {"com.tiesheng.web.mapper", "com.tiesheng.role.mapper", "com.tiesheng.login.mapper"})
public class WebAutoConfigurer { public class WebAutoConfigurer {
} }

View File

@@ -0,0 +1,87 @@
package com.tiesheng.web.config.role;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.tiesheng.annotation.role.RoleAuthority;
import com.tiesheng.annotation.role.RoleIgnore;
import com.tiesheng.annotation.token.TokenIgnore;
import com.tiesheng.util.ServletKit;
import com.tiesheng.util.config.TsTokenConfig;
import com.tiesheng.util.exception.ApiException;
import com.tiesheng.util.pojos.TokenBean;
import com.tiesheng.util.service.TsCacheService;
import com.tiesheng.util.service.role.TsAuthorityHandler;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;
@Aspect
@Component
public class RoleAuthorityAspect {
@Resource
TsTokenConfig tsTokenConfig;
@Resource
TsAuthorityHandler tsAuthorityHandler;
/**
* 获取
*/
@Before("execution(* com..controller..*.*(..))")
public void before(JoinPoint joinPoint) {
RoleAuthority classAnnotation = joinPoint.getTarget().getClass().getAnnotation(RoleAuthority.class);
if (classAnnotation == null) {
return;
}
// 忽略TOKEN时不校验
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
TokenIgnore tokenIgnore = signature.getMethod().getAnnotation(TokenIgnore.class);
if (tokenIgnore != null) {
return;
}
RoleIgnore roleIgnore = signature.getMethod().getAnnotation(RoleIgnore.class);
if (roleIgnore != null) {
return;
}
HttpServletRequest request = ServletKit.getRequest();
TokenBean tokenBean = tsTokenConfig.validToken(request, true);
String cacheKey = StrUtil.format(TsAuthorityHandler.CACHE_HAS_AUTHORITY, tokenBean.getRoleId(), tokenBean.getId());
List<String> authorityList = StrUtil.split(TsCacheService.of().get(cacheKey), ";")
.stream().filter(StrUtil::isNotEmpty).collect(Collectors.toList());
if (CollUtil.isEmpty(authorityList)) {
authorityList = tsAuthorityHandler.getAuthorities(tokenBean);
if (CollUtil.isNotEmpty(authorityList)) {
TsCacheService.of().put(cacheKey, StrUtil.join(";", authorityList));
}
}
boolean isAuthorized;
String authority = StrUtil.join("_", classAnnotation.group(), classAnnotation.value());
RoleAuthority annotation = signature.getMethod().getAnnotation(RoleAuthority.class);
if (annotation != null) {
// 检查是否是功能点的权限
isAuthorized = CollUtil.contains(authorityList, StrUtil.join("_", authority, annotation.value()));
} else {
// 检查是否有menu的权限
isAuthorized = !authorityList.stream().filter(it -> StrUtil.startWith(it, authority))
.collect(Collectors.toList()).isEmpty();
}
if (isAuthorized) {
return;
}
throw new ApiException(403, "您无权访问");
}
}

View File

@@ -1,125 +0,0 @@
package com.tiesheng.web.controller;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tiesheng.web.pojos.dao.CoreLogLogin;
import com.tiesheng.web.pojos.dao.CoreLogMessage;
import com.tiesheng.web.pojos.dao.CoreLogOperation;
import com.tiesheng.web.pojos.dao.CoreLogProcess;
import com.tiesheng.util.pojos.PageDTO;
import com.tiesheng.web.pojos.vo.ProcessDetailVo;
import com.tiesheng.web.service.CoreLogService;
import com.tiesheng.util.pojos.ApiResp;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.util.List;
/**
* @author hao
*/
@RestController
@RequestMapping("/manager/log")
public class LogController {
@Autowired
CoreLogService coreLogService;
/**
* 操作日志列表
*
* @return
*/
@GetMapping("/operation/page")
public ApiResp<List<CoreLogOperation>> operationPage(@Valid PageDTO dto) {
QueryWrapper<CoreLogOperation> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("is_deleted", 0);
dto.likeColumns(queryWrapper, "user_name", "title", "subject");
queryWrapper.orderByDesc("create_time");
Page<CoreLogOperation> page = dto.pageObj();
coreLogService.getBaseMapper().page(page, queryWrapper);
return ApiResp.respOK(page.getRecords(), page.getTotal());
}
/**
* 登录日志列表
*
* @return
*/
@GetMapping("/login/page")
public ApiResp<List<CoreLogLogin>> loginPage(@Valid PageDTO dto) {
QueryWrapper<CoreLogLogin> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("is_deleted", 0);
dto.likeColumns(queryWrapper, "user_name", "ip", "address");
queryWrapper.orderByDesc("create_time");
Page<CoreLogLogin> page = dto.pageObj();
coreLogService.getLogLoginMapper().selectPage(page, queryWrapper);
return ApiResp.respOK(page.getRecords(), page.getTotal());
}
/**
* 登录日志列表
*
* @return
*/
@GetMapping("/message/page")
public ApiResp<List<CoreLogMessage>> messagePage(String result, @Valid PageDTO dto) {
QueryWrapper<CoreLogMessage> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("is_deleted", 0);
if (!StrUtil.isEmpty(result)) {
queryWrapper.eq("result", result);
}
dto.likeColumns(queryWrapper, "type", "target", "content", "resp_body");
queryWrapper.orderByDesc("create_time");
Page<CoreLogMessage> page = dto.pageObj();
coreLogService.getLogMessageMapper().selectPage(page, queryWrapper);
return ApiResp.respOK(page.getRecords(), page.getTotal());
}
/**
* 过程日志列表
*
* @return
*/
@GetMapping("/process/page")
public ApiResp<List<CoreLogProcess>> processPage(String type, @Valid PageDTO dto) {
QueryWrapper<CoreLogProcess> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("is_deleted", 0);
if (!StrUtil.isEmpty(type)) {
queryWrapper.eq("type", type);
}
dto.likeColumns(queryWrapper, "title");
queryWrapper.orderByDesc("create_time");
Page<CoreLogProcess> page = dto.pageObj();
coreLogService.getCoreLogProcessMapper().selectPage(page, queryWrapper);
return ApiResp.respOK(page.getRecords(), page.getTotal());
}
/**
* 过程日志详情
*
* @return
*/
@GetMapping("/process/detail")
public ApiResp<ProcessDetailVo> processPage(String id) {
ProcessDetailVo processDetail = coreLogService.getProcessDetail(id);
return ApiResp.respOK(processDetail);
}
}

View File

@@ -0,0 +1,83 @@
package com.tiesheng.web.controller.comm;
import cn.hutool.core.lang.Validator;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tiesheng.annotation.token.TokenIgnore;
import com.tiesheng.util.pojos.ApiResp;
import com.tiesheng.util.pojos.IdDTO;
import com.tiesheng.web.pojos.dao.CoreConfigEnum;
import com.tiesheng.web.pojos.dao.CoreConfigSystem;
import com.tiesheng.web.pojos.dto.config.EnumTypeDTO;
import com.tiesheng.web.pojos.vo.ProcessDetailVo;
import com.tiesheng.web.service.CoreConfigService;
import com.tiesheng.web.service.CoreLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.util.List;
@RestController
@RequestMapping("/comm/web")
public class CommWebController {
@Autowired
CoreLogService coreLogService;
@Autowired
CoreConfigService coreConfigService;
/**
* 系统配置列表
*
* @return
*/
@GetMapping("/system/page")
@TokenIgnore
public ApiResp<List<CoreConfigSystem>> systemPage(String keyword) {
Validator.validateNotEmpty(keyword, "请上传关键字");
QueryWrapper<CoreConfigSystem> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("is_deleted", 0);
queryWrapper.likeRight("config_key", keyword);
queryWrapper.orderByAsc("config_key");
List<CoreConfigSystem> list = coreConfigService.list(queryWrapper);
return ApiResp.respOK(list);
}
/**
* 获取枚举列表
*
* @param dto
* @return
*/
@GetMapping("/enum/list")
@TokenIgnore
public ApiResp<List<CoreConfigEnum>> enumList(EnumTypeDTO dto) {
QueryWrapper<CoreConfigEnum> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("is_deleted", 0);
queryWrapper.eq("type", dto.getType());
List<CoreConfigEnum> selectList = coreConfigService.getEnumMapper().selectList(queryWrapper);
return ApiResp.respOK(selectList);
}
/**
* 过程日志详情
*
* @return
*/
@GetMapping("/process/detail")
@TokenIgnore
public ApiResp<ProcessDetailVo> processPage(@Valid IdDTO dto) {
ProcessDetailVo processDetail = coreLogService.getProcessDetail(dto.getId());
return ApiResp.respOK(processDetail);
}
}

View File

@@ -1,16 +1,16 @@
package com.tiesheng.web.controller; package com.tiesheng.web.controller.comm;
import cn.hutool.captcha.LineCaptcha; import cn.hutool.captcha.LineCaptcha;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import com.tiesheng.annotation.token.TokenIgnore; import com.tiesheng.annotation.token.TokenIgnore;
import com.tiesheng.util.service.TsCacheService;
import com.tiesheng.web.config.template.ToolTemplateHandler; import com.tiesheng.web.config.template.ToolTemplateHandler;
import com.tiesheng.web.pojos.dto.*; import com.tiesheng.web.pojos.dto.*;
import com.tiesheng.web.pojos.vo.TemplateInfoVO; import com.tiesheng.web.pojos.vo.TemplateInfoVO;
import com.tiesheng.web.pojos.vo.PicVerifyVo; import com.tiesheng.web.pojos.vo.PicVerifyVo;
import com.tiesheng.web.service.FileUploadService; import com.tiesheng.web.service.FileUploadService;
import com.tiesheng.web.service.TimedCacheService;
import com.tiesheng.util.exception.ApiException; import com.tiesheng.util.exception.ApiException;
import com.tiesheng.util.pojos.ApiResp; import com.tiesheng.util.pojos.ApiResp;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -31,7 +31,7 @@ import java.util.stream.Collectors;
public class ToolController { public class ToolController {
@Autowired @Autowired
TimedCacheService timedCacheService; TsCacheService tsCacheService;
@Autowired @Autowired
FileUploadService fileUploadService; FileUploadService fileUploadService;
@Autowired @Autowired
@@ -51,7 +51,7 @@ public class ToolController {
PicVerifyVo vo = new PicVerifyVo(); PicVerifyVo vo = new PicVerifyVo();
vo.setBase64(lineCaptcha.getImageBase64Data()); vo.setBase64(lineCaptcha.getImageBase64Data());
vo.setKey(IdUtil.simpleUUID()); vo.setKey(IdUtil.simpleUUID());
timedCacheService.setImageCode(vo.getKey(), lineCaptcha.getCode()); tsCacheService.put(vo.getKey(), lineCaptcha.getCode());
return ApiResp.respOK(vo); return ApiResp.respOK(vo);
} }
@@ -113,7 +113,7 @@ public class ToolController {
/** /**
* 合并文件 * 合并文件
* *
* @param fileMd5 * @param dto
* @return * @return
*/ */
@TokenIgnore @TokenIgnore

View File

@@ -0,0 +1,49 @@
package com.tiesheng.web.controller.system;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tiesheng.annotation.role.RoleAuthority;
import com.tiesheng.util.pojos.ApiResp;
import com.tiesheng.web.pojos.dao.CoreConfigEnum;
import com.tiesheng.web.pojos.dto.config.EnumTypeDTO;
import com.tiesheng.web.service.CoreConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @author hao
*/
@RestController
@RequestMapping("/config")
@RoleAuthority(value = "enum", group = "system")
public class ConfigEnumController {
@Autowired
CoreConfigService coreConfigService;
/**
* 获取枚举列表
*
* @param dto
* @return
*/
@GetMapping("/enum/list")
public ApiResp<List<CoreConfigEnum>> enumList(EnumTypeDTO dto) {
QueryWrapper<CoreConfigEnum> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("is_deleted", 0);
if (!StrUtil.isEmpty(dto.getType())) {
queryWrapper.eq("type", dto.getType());
}
List<CoreConfigEnum> selectList = coreConfigService.getEnumMapper().selectList(queryWrapper);
return ApiResp.respOK(selectList);
}
}

View File

@@ -1,19 +1,16 @@
package com.tiesheng.web.controller; package com.tiesheng.web.controller.system;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tiesheng.annotation.token.TokenIgnore; import com.tiesheng.annotation.role.RoleAuthority;
import com.tiesheng.web.pojos.dao.CoreConfigEnum;
import com.tiesheng.web.pojos.dao.CoreConfigSystem;
import com.tiesheng.web.pojos.dto.config.ConfigSystemDTO;
import com.tiesheng.web.pojos.dto.config.EnumTypeDTO;
import com.tiesheng.web.service.CoreConfigService;
import com.tiesheng.web.service.TieshengWebConfigurer;
import com.tiesheng.util.exception.ApiException; import com.tiesheng.util.exception.ApiException;
import com.tiesheng.util.pojos.ApiResp; import com.tiesheng.util.pojos.ApiResp;
import com.tiesheng.util.pojos.PageDTO; import com.tiesheng.util.pojos.PageDTO;
import com.tiesheng.web.pojos.dao.CoreConfigSystem;
import com.tiesheng.web.pojos.dto.config.ConfigSystemDTO;
import com.tiesheng.web.service.CoreConfigService;
import com.tiesheng.web.service.TieshengWebConfigurer;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@@ -24,7 +21,8 @@ import java.util.List;
*/ */
@RestController @RestController
@RequestMapping("/config") @RequestMapping("/config")
public class ConfigController { @RoleAuthority(value = "config", group = "system")
public class ConfigSystemController {
@Autowired @Autowired
CoreConfigService coreConfigService; CoreConfigService coreConfigService;
@@ -38,7 +36,6 @@ public class ConfigController {
* @return * @return
*/ */
@GetMapping("/system/page") @GetMapping("/system/page")
@TokenIgnore
public ApiResp<List<CoreConfigSystem>> systemPage(PageDTO dto) { public ApiResp<List<CoreConfigSystem>> systemPage(PageDTO dto) {
QueryWrapper<CoreConfigSystem> queryWrapper = new QueryWrapper<>(); QueryWrapper<CoreConfigSystem> queryWrapper = new QueryWrapper<>();
@@ -78,25 +75,4 @@ public class ConfigController {
return ApiResp.respOK(""); return ApiResp.respOK("");
} }
/**
* 获取枚举列表
*
* @param dto
* @return
*/
@GetMapping("/enum/list")
@TokenIgnore
public ApiResp<List<CoreConfigEnum>> enumList(EnumTypeDTO dto) {
QueryWrapper<CoreConfigEnum> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("is_deleted", 0);
if (!StrUtil.isEmpty(dto.getType())) {
queryWrapper.eq("type", dto.getType());
}
List<CoreConfigEnum> selectList = coreConfigService.getEnumMapper().selectList(queryWrapper);
return ApiResp.respOK(selectList);
}
} }

View File

@@ -0,0 +1,52 @@
package com.tiesheng.web.controller.system;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tiesheng.annotation.role.RoleAuthority;
import com.tiesheng.util.pojos.ApiResp;
import com.tiesheng.util.pojos.PageDTO;
import com.tiesheng.web.pojos.dao.CoreLogApi;
import com.tiesheng.web.service.CoreLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.util.List;
/**
* @author hao
*/
@RestController
@RequestMapping("/manager/log")
@RoleAuthority(value = "api", group = "system")
public class LogApiController {
@Autowired
CoreLogService coreLogService;
/**
* 调用日志
*
* @return
*/
@GetMapping("/api/page")
public ApiResp<List<CoreLogApi>> apiPage(String result, @Valid PageDTO dto) {
QueryWrapper<CoreLogApi> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("is_deleted", 0);
if (!StrUtil.isEmpty(result)) {
queryWrapper.eq("result", result);
}
dto.likeColumns(queryWrapper, "type", "content");
queryWrapper.orderByDesc("create_time");
Page<CoreLogApi> page = dto.pageObj();
coreLogService.getLogApiMapper().selectPage(page, queryWrapper);
return ApiResp.respOK(page.getRecords(), page.getTotal());
}
}

View File

@@ -0,0 +1,48 @@
package com.tiesheng.web.controller.system;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tiesheng.annotation.role.RoleAuthority;
import com.tiesheng.login.pojos.dao.CoreLogLogin;
import com.tiesheng.util.pojos.ApiResp;
import com.tiesheng.util.pojos.PageDTO;
import com.tiesheng.web.service.CoreLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.util.List;
/**
* @author hao
*/
@RestController
@RequestMapping("/manager/log")
@RoleAuthority(value = "login", group = "system")
public class LogLoginController {
@Autowired
CoreLogService coreLogService;
/**
* 登录日志列表
*
* @return
*/
@GetMapping("/login/page")
public ApiResp<List<CoreLogLogin>> loginPage(@Valid PageDTO dto) {
QueryWrapper<CoreLogLogin> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("is_deleted", 0);
dto.likeColumns(queryWrapper, "user_name", "ip", "address");
queryWrapper.orderByDesc("create_time");
Page<CoreLogLogin> page = dto.pageObj();
coreLogService.getLogLoginMapper().selectPage(page, queryWrapper);
return ApiResp.respOK(page.getRecords(), page.getTotal());
}
}

View File

@@ -0,0 +1,50 @@
package com.tiesheng.web.controller.system;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tiesheng.annotation.role.RoleAuthority;
import com.tiesheng.util.pojos.ApiResp;
import com.tiesheng.util.pojos.PageDTO;
import com.tiesheng.web.pojos.dao.CoreLogOperation;
import com.tiesheng.web.service.CoreLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.util.List;
/**
* @author hao
*/
@RestController
@RequestMapping("/manager/log")
@RoleAuthority(value = "operation", group = "system")
public class LogOperationController {
@Autowired
CoreLogService coreLogService;
/**
* 操作日志列表
*
* @return
*/
@GetMapping("/operation/page")
public ApiResp<List<CoreLogOperation>> operationPage(@Valid PageDTO dto) {
QueryWrapper<CoreLogOperation> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("is_deleted", 0);
dto.likeColumns(queryWrapper, "user_name", "title", "subject");
queryWrapper.orderByDesc("create_time");
Page<CoreLogOperation> page = dto.pageObj();
coreLogService.getBaseMapper().page(page, queryWrapper);
return ApiResp.respOK(page.getRecords(), page.getTotal());
}
}

View File

@@ -0,0 +1,51 @@
package com.tiesheng.web.controller.system;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tiesheng.annotation.role.RoleAuthority;
import com.tiesheng.util.pojos.ApiResp;
import com.tiesheng.util.pojos.PageDTO;
import com.tiesheng.web.pojos.dao.CoreLogProcess;
import com.tiesheng.web.service.CoreLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
import java.util.List;
/**
* @author hao
*/
@RestController
@RequestMapping("/manager/log")
@RoleAuthority(value = "process", group = "system")
public class LogProcessController {
@Autowired
CoreLogService coreLogService;
/**
* 过程日志列表
*
* @return
*/
@GetMapping("/process/page")
public ApiResp<List<CoreLogProcess>> processPage(String type, @Valid PageDTO dto) {
QueryWrapper<CoreLogProcess> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("is_deleted", 0);
if (!StrUtil.isEmpty(type)) {
queryWrapper.eq("type", type);
}
dto.likeColumns(queryWrapper, "title");
queryWrapper.orderByDesc("create_time");
Page<CoreLogProcess> page = dto.pageObj();
coreLogService.getCoreLogProcessMapper().selectPage(page, queryWrapper);
return ApiResp.respOK(page.getRecords(), page.getTotal());
}
}

View File

@@ -0,0 +1,7 @@
package com.tiesheng.web.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tiesheng.web.pojos.dao.CoreLogApi;
public interface CoreLogApiMapper extends BaseMapper<CoreLogApi> {
}

View File

@@ -1,7 +0,0 @@
package com.tiesheng.web.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.tiesheng.web.pojos.dao.CoreLogMessage;
public interface CoreLogMessageMapper extends BaseMapper<CoreLogMessage> {
}

View File

@@ -1,14 +1,17 @@
package com.tiesheng.web.pojos.dao; package com.tiesheng.web.pojos.dao;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import com.tiesheng.util.pojos.DaoBase; import com.tiesheng.util.pojos.DaoBase;
import java.util.Date;
/** /**
* 日志-消息 * 日志-调用
*/ */
@TableName(value = "core_log_message") @TableName(value = "core_log_api")
public class CoreLogMessage extends DaoBase { public class CoreLogApi extends DaoBase {
/** /**
* 类型 * 类型
*/ */
@@ -16,10 +19,10 @@ public class CoreLogMessage extends DaoBase {
private String type; private String type;
/** /**
* 发送对象 * 请求地址
*/ */
@TableField(value = "target") @TableField(value = "url")
private String target; private String url;
/** /**
* 发送内容 * 发送内容
@@ -58,21 +61,21 @@ public class CoreLogMessage extends DaoBase {
} }
/** /**
* 获取发送对象 * 获取请求地址
* *
* @return target - 发送对象 * @return url - 请求地址
*/ */
public String getTarget() { public String getUrl() {
return target; return url;
} }
/** /**
* 设置发送对象 * 设置请求地址
* *
* @param target 发送对象 * @param url 请求地址
*/ */
public void setTarget(String target) { public void setUrl(String url) {
this.target = target; this.url = url;
} }
/** /**
@@ -128,4 +131,4 @@ public class CoreLogMessage extends DaoBase {
public void setResult(Integer result) { public void setResult(Integer result) {
this.result = result; this.result = result;
} }
} }

View File

@@ -5,30 +5,24 @@ import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.tiesheng.util.ServletKit; import com.tiesheng.login.mapper.CoreLogLoginMapper;
import com.tiesheng.util.config.Ip2regionConfig; import com.tiesheng.login.pojos.RequestUserInfo;
import com.tiesheng.util.exception.ApiException; import com.tiesheng.util.exception.ApiException;
import com.tiesheng.util.pojos.TokenBean; import com.tiesheng.util.pojos.TokenBean;
import com.tiesheng.util.service.TsServiceBase; import com.tiesheng.util.service.TsServiceBase;
import com.tiesheng.web.mapper.CoreLogLoginMapper; import com.tiesheng.web.mapper.CoreLogApiMapper;
import com.tiesheng.web.mapper.CoreLogMessageMapper;
import com.tiesheng.web.mapper.CoreLogOperationMapper; import com.tiesheng.web.mapper.CoreLogOperationMapper;
import com.tiesheng.web.mapper.CoreLogProcessMapper; import com.tiesheng.web.mapper.CoreLogProcessMapper;
import com.tiesheng.web.pojos.RequestUserInfo;
import com.tiesheng.web.pojos.dao.CoreLogLogin;
import com.tiesheng.web.pojos.dao.CoreLogOperation; import com.tiesheng.web.pojos.dao.CoreLogOperation;
import com.tiesheng.web.pojos.dao.CoreLogProcess; import com.tiesheng.web.pojos.dao.CoreLogProcess;
import com.tiesheng.web.pojos.dao.CorePlatformUnique;
import com.tiesheng.web.pojos.vo.ProcessDetailVo; import com.tiesheng.web.pojos.vo.ProcessDetailVo;
import com.tiesheng.web.util.ProcessImportConsumer; import com.tiesheng.web.util.ProcessImportConsumer;
import com.tiesheng.web.util.ProcessSyncConsumer; import com.tiesheng.web.util.ProcessSyncConsumer;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -48,9 +42,7 @@ public class CoreLogService extends TsServiceBase<CoreLogOperationMapper, CoreLo
@Autowired @Autowired
CoreLogLoginMapper coreLogLoginMapper; CoreLogLoginMapper coreLogLoginMapper;
@Autowired @Autowired
CoreLogMessageMapper coreLogMessageMapper; CoreLogApiMapper coreLogApiMapper;
@Autowired
Ip2regionConfig ip2regionConfig;
@Autowired @Autowired
CoreLogProcessMapper coreLogProcessMapper; CoreLogProcessMapper coreLogProcessMapper;
@@ -58,8 +50,8 @@ public class CoreLogService extends TsServiceBase<CoreLogOperationMapper, CoreLo
return coreLogLoginMapper; return coreLogLoginMapper;
} }
public CoreLogMessageMapper getLogMessageMapper() { public CoreLogApiMapper getLogApiMapper() {
return coreLogMessageMapper; return coreLogApiMapper;
} }
public CoreLogProcessMapper getCoreLogProcessMapper() { public CoreLogProcessMapper getCoreLogProcessMapper() {
@@ -184,12 +176,12 @@ public class CoreLogService extends TsServiceBase<CoreLogOperationMapper, CoreLo
*/ */
public void addOperationLog(TokenBean tokenBean, String title, String subject, Object params) { public void addOperationLog(TokenBean tokenBean, String title, String subject, Object params) {
RequestUserInfo requestUserInfo = null; if (tokenBean == null || StrUtil.isEmpty(tokenBean.getId())) {
if (tokenBean != null && !StrUtil.isEmpty(tokenBean.getId())) { return;
requestUserInfo = tieshengWebConfigurer.getCurrentUserName(tokenBean);
} }
RequestUserInfo requestUserInfo = tieshengWebConfigurer.configureLogin().getCachedUserInfo(tokenBean);
if (requestUserInfo == null) { if (requestUserInfo == null) {
requestUserInfo = new RequestUserInfo(); return;
} }
CoreLogOperation operation = new CoreLogOperation(); CoreLogOperation operation = new CoreLogOperation();
@@ -210,34 +202,7 @@ public class CoreLogService extends TsServiceBase<CoreLogOperationMapper, CoreLo
cacheOperations.clear(); cacheOperations.clear();
} }
} }
} }
///////////////////////////////////////////////////////////////////////////
// 登录日志
///////////////////////////////////////////////////////////////////////////
/**
* 添加登录日志
*
* @param platformUnique
* @param tokenBean
*/
public void addLoginLog(CorePlatformUnique platformUnique, TokenBean tokenBean) {
HttpServletRequest request = ServletKit.getRequest();
String ip = ServletUtil.getClientIP(request);
CoreLogLogin login = new CoreLogLogin();
login.setUserId(tokenBean.getId());
login.setPlatform(platformUnique.getPlatform());
RequestUserInfo requestUserInfo = tieshengWebConfigurer.getCurrentUserName(tokenBean);
login.setUserName(requestUserInfo.getName());
login.setIp(ip);
login.setAddress(ip2regionConfig.search(login.getIp()));
coreLogLoginMapper.insert(login);
}
} }

View File

@@ -1,72 +0,0 @@
package com.tiesheng.web.service;
import cn.hutool.core.util.StrUtil;
import com.tiesheng.web.mapper.CorePlatformUniqueMapper;
import com.tiesheng.web.pojos.dao.CorePlatformUnique;
import com.tiesheng.util.pojos.TokenBean;
import com.tiesheng.login.pojos.DoLoginInfo;
import com.tiesheng.login.service.TieshengLoginConfigurer;
import com.tiesheng.util.service.TsServiceBase;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;
/**
* @author hao
*/
@Service
public class CorePlatformUniqueService extends TsServiceBase<CorePlatformUniqueMapper, CorePlatformUnique> implements TieshengLoginConfigurer {
@Autowired
TieshengWebConfigurer tieshengWebConfigurer;
@Autowired
CoreLogService coreLogService;
@Override
@Transactional(rollbackFor = Exception.class)
public TokenBean doLogin(DoLoginInfo loginInfo) {
CorePlatformUnique platformUnique = getOneByColumn("unique_id", loginInfo.getUnique());
if (platformUnique == null) {
platformUnique = new CorePlatformUnique();
platformUnique.setAppId(loginInfo.getAppId());
platformUnique.setUniqueId(loginInfo.getUnique());
}
platformUnique.setPlatform(loginInfo.getPlatform());
platformUnique.setInfo(loginInfo.getInfo());
saveOrUpdate(platformUnique);
String oldUserId = platformUnique.getUserId();
TokenBean tokenBean = tieshengWebConfigurer.login(platformUnique);
if (tokenBean != null) {
// 添加登录日志
coreLogService.addLoginLog(platformUnique, tokenBean);
// 更新唯一值
if (!StrUtil.isEmpty(tokenBean.getId()) &&
!Objects.equals(oldUserId, tokenBean.getId())) {
platformUnique.setUserId(tokenBean.getId());
saveOrUpdate(platformUnique);
}
}
return tokenBean;
}
@Override
public void onLoginRedirect(TokenBean bean, String to, String extra, HttpServletResponse response) {
tieshengWebConfigurer.redirect(bean, to, extra, response);
}
@Override
public void onSignError(HttpServletResponse response) {
tieshengWebConfigurer.onSignError(response);
}
}

View File

@@ -0,0 +1,88 @@
package com.tiesheng.web.service;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.tiesheng.util.service.http.OkHttpUtil;
import com.tiesheng.web.mapper.CoreLogApiMapper;
import com.tiesheng.web.pojos.dao.CoreLogApi;
import okhttp3.*;
import okio.Buffer;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
@Component
public class LogApiOkHttpInterceptor implements Interceptor {
@Resource
CoreLogApiMapper coreLogApiMapper;
@NotNull
@Override
public Response intercept(@NotNull Chain chain) {
CoreLogApi logApi = new CoreLogApi();
Request request = chain.request();
logApi.setUrl(request.url().toString());
logApi.setContent(requestBody2String(request));
Response response;
try {
response = chain.proceed(request);
ResponseBody peekBody = response.peekBody(Long.MAX_VALUE);
logApi.setRespBody(peekBody.string());
logApi.setResult(response.code());
peekBody.close();
} catch (Exception e) {
logApi.setRespBody(JSONUtil.createObj()
.putOpt("code", -1)
.putOpt("message", e.getMessage())
.putOpt("exception", e)
.toString());
response = new Response.Builder()
.request(request)
.body(OkHttpUtil.ofJsonResponse(logApi.getRespBody()))
.build();
}
ThreadUtil.execute(() -> coreLogApiMapper.insert(logApi));
return response;
}
private String requestBody2String(@NotNull Request request) {
final Request copy = request.newBuilder().build();
RequestBody requestBody = copy.body();
if (requestBody == null) {
return null;
}
if (requestBody instanceof MultipartBody) {
return null;
}
if (requestBody instanceof FormBody) {
JSONObject jsonObject = JSONUtil.createObj();
FormBody formBody = (FormBody) requestBody;
for (int i = 0; i < formBody.size(); i++) {
jsonObject.putOpt(formBody.encodedName(i), formBody.encodedValue(i));
}
return jsonObject.toString();
}
final Buffer buffer = new Buffer();
try {
if (copy.body() != null) {
copy.body().writeTo(buffer);
}
} catch (Exception e) {
return "occurs error when show requestBody";
}
return buffer.readUtf8();
}
}

View File

@@ -1,33 +1,19 @@
package com.tiesheng.web.service; package com.tiesheng.web.service;
import cn.hutool.log.LogFactory; import cn.hutool.log.LogFactory;
import com.tiesheng.web.pojos.RequestUserInfo; import com.tiesheng.login.service.TsLoginConfigurer;
import com.tiesheng.web.pojos.dao.CoreConfigSystem;
import com.tiesheng.web.pojos.dao.CorePlatformUnique;
import com.tiesheng.util.pojos.TokenBean;
import com.tiesheng.util.ServletKit;
import com.tiesheng.util.exception.ApiRespEnum; import com.tiesheng.util.exception.ApiRespEnum;
import com.tiesheng.util.pojos.ApiResp; import com.tiesheng.util.pojos.ApiResp;
import com.tiesheng.web.pojos.dao.CoreConfigSystem;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
/** /**
* WEB配置 * 核心配置
* *
* @author hao * @author hao
*/ */
public interface TieshengWebConfigurer { public interface TieshengWebConfigurer {
/**
* 获取当前用户的姓名
*
* @return
*/
RequestUserInfo getCurrentUserName(TokenBean userId);
/** /**
* 添加其他异常处理 * 添加其他异常处理
* *
@@ -75,28 +61,16 @@ public interface TieshengWebConfigurer {
default void configSystemCheck(CoreConfigSystem configSystem) { default void configSystemCheck(CoreConfigSystem configSystem) {
} }
///////////////////////////////////////////////////////////////////////////
// 登录配置
///////////////////////////////////////////////////////////////////////////
/** /**
* 登录逻辑 * 登录配置
* *
* @param platformUnique
* @return * @return
*/ */
TokenBean login(CorePlatformUnique platformUnique); TsLoginConfigurer configureLogin();
/**
* 登录重定向
*
* @param bean
* @param extra
* @param response
*/
void redirect(TokenBean bean, String to, String extra, HttpServletResponse response);
/**
* 签名错误的时候
*/
default void onSignError(HttpServletResponse response) {
ServletKit.write(response, "404", "text");
}
} }

View File

@@ -1,82 +0,0 @@
package com.tiesheng.web.service;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.tiesheng.util.ServletKit;
import com.tiesheng.util.TimedCacheHelper;
import com.tiesheng.util.exception.ApiException;
import org.springframework.stereotype.Service;
/**
* @author hao
* @ProjectName cmcc
* @Copyright Hangzhou ShuoChuang Technology Co.,Ltd All Right Reserved
* @Description 这里是对文件的描述
* @data 2019-06-19
* @note 这里写文件的详细功能和改动
* @note
*/
@Service
public class TimedCacheService {
/**
* 清空数据
*
* @param key
*/
public void clearByKey(String key) {
TimedCacheHelper.getTimedCache().remove(key);
}
/**
* 放入缓存
*
* @param key
* @param val
*/
public void putCache(String key, String val) {
TimedCacheHelper.getTimedCache().put(key, val);
}
/**
* 获取缓存
*
* @param key
* @return
*/
public String getCache(String key) {
return TimedCacheHelper.getTimedCache().get(key);
}
///////////////////////////////////////////////////////////////////////////
// 图片验证码缓存
///////////////////////////////////////////////////////////////////////////
/**
* 缓存 图片验证码
*
* @param session
* @param value
*/
public void setImageCode(String captcha, String value) {
putCache(captcha, value);
}
/**
* 验证 图片验证码
*/
public void verifyImage(String value) {
String captchaKey = ServletUtil.getHeader(ServletKit.getRequest(), "captcha", "utf-8");
String cache = getCache(captchaKey);
if (StrUtil.isEmpty(cache) || !StrUtil.equals(cache, value)) {
throw new ApiException("验证码不正确");
}
clearByKey(captchaKey);
}
}

View File

@@ -2,41 +2,23 @@ SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0; SET FOREIGN_KEY_CHECKS = 0;
-- ---------------------------- -- ----------------------------
-- Table structure for core_log_login -- Table structure for core_log_api
-- ---------------------------- -- ----------------------------
CREATE TABLE `core_log_login` CREATE TABLE `core_log_api`
(
`id` varchar(50) NOT NULL,
`create_time` datetime NOT NULL,
`update_time` datetime NOT NULL,
`is_deleted` int(6) NOT NULL DEFAULT '0',
`user_id` varchar(50) DEFAULT NULL COMMENT '用户id',
`user_name` varchar(255) DEFAULT NULL COMMENT '用户姓名',
`platform` varchar(50) DEFAULT NULL COMMENT '登录方式',
`ip` varchar(100) DEFAULT NULL COMMENT 'ip',
`address` varchar(255) DEFAULT NULL COMMENT 'ip地址',
PRIMARY KEY (`id`)
) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4 COMMENT ='日志-登录';
-- ----------------------------
-- Table structure for core_log_message
-- ----------------------------
CREATE TABLE `core_log_message`
( (
`id` varchar(50) NOT NULL, `id` varchar(50) NOT NULL,
`create_time` datetime NOT NULL, `create_time` datetime NOT NULL,
`update_time` datetime NOT NULL, `update_time` datetime NOT NULL,
`is_deleted` int(6) NOT NULL DEFAULT '0', `is_deleted` int(6) NOT NULL DEFAULT '0',
`type` varchar(50) DEFAULT NULL COMMENT '类型', `type` varchar(50) DEFAULT NULL COMMENT '类型',
`target` varchar(255) DEFAULT NULL COMMENT '发送对象', `url` text DEFAULT NULL COMMENT '请求地址',
`content` text COMMENT '发送内容', `content` text COMMENT '发送内容',
`resp_body` text COMMENT '返回结果', `resp_body` text COMMENT '返回结果',
`result` int(6) NOT NULL DEFAULT '0' COMMENT '结果', `result` int(6) NOT NULL DEFAULT '0' COMMENT '结果',
PRIMARY KEY (`id`) PRIMARY KEY (`id`)
) ENGINE = InnoDB ) ENGINE = InnoDB
DEFAULT CHARSET = utf8mb4 DEFAULT CHARSET = utf8mb4
ROW_FORMAT = DYNAMIC COMMENT ='日志-消息'; ROW_FORMAT = DYNAMIC COMMENT ='日志-调用';
-- ---------------------------- -- ----------------------------
-- Table structure for core_log_process -- Table structure for core_log_process

View File

@@ -1,21 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.tiesheng.web.mapper.CoreLogMessageMapper"> <mapper namespace="com.tiesheng.web.mapper.CoreLogApiMapper">
<resultMap id="BaseResultMap" type="com.tiesheng.web.pojos.dao.CoreLogMessage"> <resultMap id="BaseResultMap" type="com.tiesheng.web.pojos.dao.CoreLogApi">
<!--@mbg.generated--> <!--@mbg.generated-->
<!--@Table core_log_message--> <!--@Table core_log_api-->
<id column="id" jdbcType="VARCHAR" property="id" /> <id column="id" jdbcType="VARCHAR" property="id" />
<result column="create_time" jdbcType="TIMESTAMP" property="createTime" /> <result column="create_time" jdbcType="TIMESTAMP" property="createTime" />
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime" /> <result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
<result column="is_deleted" jdbcType="INTEGER" property="isDeleted" /> <result column="is_deleted" jdbcType="INTEGER" property="isDeleted" />
<result column="type" jdbcType="VARCHAR" property="type" /> <result column="type" jdbcType="VARCHAR" property="type" />
<result column="target" jdbcType="VARCHAR" property="target" /> <result column="url" jdbcType="LONGVARCHAR" property="url" />
<result column="content" jdbcType="LONGVARCHAR" property="content" /> <result column="content" jdbcType="LONGVARCHAR" property="content" />
<result column="resp_body" jdbcType="LONGVARCHAR" property="respBody" /> <result column="resp_body" jdbcType="LONGVARCHAR" property="respBody" />
<result column="result" jdbcType="INTEGER" property="result" /> <result column="result" jdbcType="INTEGER" property="result" />
</resultMap> </resultMap>
<sql id="Base_Column_List"> <sql id="Base_Column_List">
<!--@mbg.generated--> <!--@mbg.generated-->
id, create_time, update_time, is_deleted, `type`, target, content, resp_body, `result` id, create_time, update_time, is_deleted, `type`, url, content, resp_body, `result`
</sql> </sql>
</mapper> </mapper>