Compare commits
28 Commits
2.0.5
...
2.0.17-tes
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ffc7220944 | ||
|
|
411969192f | ||
|
|
2cf88cefa7 | ||
|
|
9a56994342 | ||
|
|
a987689bd6 | ||
|
|
690dffa779 | ||
|
|
3ccbd6cd8e | ||
|
|
89e0c5d1d5 | ||
|
|
b15dbc6d4c | ||
|
|
2f6b5b0b05 | ||
|
|
832d615273 | ||
|
|
383a82e530 | ||
|
|
6531709c69 | ||
|
|
6aaf91a755 | ||
|
|
f1ac7d6886 | ||
|
|
2f07f9eb66 | ||
|
|
919cd47623 | ||
|
|
eb1c20b033 | ||
|
|
c1559e96be | ||
|
|
9ef7d2d4a2 | ||
|
|
b90e92f4cb | ||
|
|
cb816d0ff0 | ||
|
|
0470ca0b9a | ||
|
|
d38077b0f8 | ||
|
|
2621c6dedc | ||
|
|
456a95778c | ||
|
|
fd0976a30c | ||
|
|
e519781207 |
25
.gitea/workflows/mvn-deploy.yaml
Normal file
25
.gitea/workflows/mvn-deploy.yaml
Normal file
@@ -0,0 +1,25 @@
|
||||
## 工作流触发时机
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '*'
|
||||
|
||||
jobs:
|
||||
|
||||
## 任务名称
|
||||
local-deploy:
|
||||
|
||||
## 任务执行的服务器
|
||||
runs-on: tiesheng-local
|
||||
|
||||
## 任务步骤
|
||||
steps:
|
||||
|
||||
## 检出代码(固定配置)
|
||||
- name: Check out repository code
|
||||
uses: https://git.tieshengkeji.com/actions/checkout@v4
|
||||
|
||||
## maven打包
|
||||
- name: Maven deploy
|
||||
run: |
|
||||
mvn deploy
|
||||
@@ -1,17 +0,0 @@
|
||||
stages:
|
||||
- deploy
|
||||
|
||||
deploy-jar:
|
||||
stage: deploy
|
||||
tags:
|
||||
- zengos
|
||||
rules:
|
||||
- if: $CI_COMMIT_TAG
|
||||
script:
|
||||
- mvn clean deploy -Dmaven.test.skip -DaltDeploymentRepository=master::default::file:$TAG_REPO_FOLDER
|
||||
- cd $TAG_REPO_FOLDER
|
||||
- git checkout master
|
||||
- git pull
|
||||
- git add .
|
||||
- git commit -m "deploy $CI_PROJECT_NAME $CI_COMMIT_TAG"
|
||||
- git push origin master
|
||||
@@ -1,3 +1,8 @@
|
||||
## 2.0.12
|
||||
|
||||
- 调整OkHttp日志
|
||||
|
||||
|
||||
## 2.0.0.rc46
|
||||
|
||||
现在导入导出都接入底层流程,无需新增接口,只需要实现接口即可。
|
||||
|
||||
25
pom.xml
25
pom.xml
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>com.tiesheng.springboot-parent</groupId>
|
||||
<artifactId>springboot-parent</artifactId>
|
||||
<version>2.0.5</version>
|
||||
<version>2.0.17-test2</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>springboot-parent</name>
|
||||
<description>杭州铁晟科技有限公司基础依赖</description>
|
||||
@@ -58,49 +58,49 @@
|
||||
<dependency>
|
||||
<groupId>com.tiesheng.springboot-parent</groupId>
|
||||
<artifactId>springboot-database</artifactId>
|
||||
<version>2.0.5</version>
|
||||
<version>2.0.17-test2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.tiesheng.springboot-parent</groupId>
|
||||
<artifactId>springboot-login</artifactId>
|
||||
<version>2.0.5</version>
|
||||
<version>2.0.17-test2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.tiesheng.springboot-parent</groupId>
|
||||
<artifactId>springboot-web</artifactId>
|
||||
<version>2.0.5</version>
|
||||
<version>2.0.17-test2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.tiesheng.springboot-parent</groupId>
|
||||
<artifactId>springboot-util</artifactId>
|
||||
<version>2.0.5</version>
|
||||
<version>2.0.17-test2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.tiesheng.springboot-parent</groupId>
|
||||
<artifactId>springboot-platform</artifactId>
|
||||
<version>2.0.5</version>
|
||||
<version>2.0.17-test2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.tiesheng.springboot-parent</groupId>
|
||||
<artifactId>springboot-message</artifactId>
|
||||
<version>2.0.5</version>
|
||||
<version>2.0.17-test2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.tiesheng.springboot-parent</groupId>
|
||||
<artifactId>springboot-role</artifactId>
|
||||
<version>2.0.5</version>
|
||||
<version>2.0.17-test2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.tiesheng.springboot-parent</groupId>
|
||||
<artifactId>springboot-annotation</artifactId>
|
||||
<version>2.0.5</version>
|
||||
<version>2.0.17-test2</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -125,6 +125,13 @@
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>gitea</id>
|
||||
<url>https://git.tieshengkeji.com/api/packages/tieshengkeji/maven</url>
|
||||
</repository>
|
||||
</distributionManagement>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
|
||||
31
qodana.yaml
Normal file
31
qodana.yaml
Normal file
@@ -0,0 +1,31 @@
|
||||
#-------------------------------------------------------------------------------#
|
||||
# Qodana analysis is configured by qodana.yaml file #
|
||||
# https://www.jetbrains.com/help/qodana/qodana-yaml.html #
|
||||
#-------------------------------------------------------------------------------#
|
||||
version: "1.0"
|
||||
|
||||
#Specify inspection profile for code analysis
|
||||
profile:
|
||||
name: qodana.starter
|
||||
|
||||
#Enable inspections
|
||||
#include:
|
||||
# - name: <SomeEnabledInspectionId>
|
||||
|
||||
#Disable inspections
|
||||
#exclude:
|
||||
# - name: <SomeDisabledInspectionId>
|
||||
# paths:
|
||||
# - <path/where/not/run/inspection>
|
||||
|
||||
projectJDK: 17 #(Applied in CI/CD pipeline)
|
||||
|
||||
#Execute shell command before Qodana execution (Applied in CI/CD pipeline)
|
||||
#bootstrap: sh ./prepare-qodana.sh
|
||||
|
||||
#Install IDE plugins before Qodana execution (Applied in CI/CD pipeline)
|
||||
#plugins:
|
||||
# - id: <plugin.id> #(plugin id can be found at https://plugins.jetbrains.com)
|
||||
|
||||
#Specify Qodana linter for analysis (Applied in CI/CD pipeline)
|
||||
linter: jetbrains/qodana-jvm:latest
|
||||
@@ -6,11 +6,11 @@
|
||||
<parent>
|
||||
<groupId>com.tiesheng.springboot-parent</groupId>
|
||||
<artifactId>springboot-parent</artifactId>
|
||||
<version>2.0.5</version>
|
||||
<version>2.0.17-test2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>springboot-ademo</artifactId>
|
||||
<version>2.0.5</version>
|
||||
<version>2.0.17-test2</version>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
|
||||
@@ -16,10 +16,6 @@ import java.util.Objects;
|
||||
@Component
|
||||
public class DemoWebConfigurer implements TieshengWebConfigurer, TsLoginConfigurer {
|
||||
|
||||
@Autowired
|
||||
GlobalConfig globalConfig;
|
||||
|
||||
|
||||
@Override
|
||||
public RequestUserInfo getCurrentUserName(TokenBean tokenBean) {
|
||||
RequestUserInfo info = new RequestUserInfo();
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package com.tiesheng.demo.config;
|
||||
|
||||
|
||||
import com.tiesheng.web.service.CoreConfigService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
@@ -13,9 +11,6 @@ import javax.annotation.PostConstruct;
|
||||
@Component
|
||||
public class TestJobConfig {
|
||||
|
||||
@Autowired
|
||||
CoreConfigService coreConfigService;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ public class TestController {
|
||||
@RequestMapping("/index")
|
||||
@TokenIgnore
|
||||
public void index(HttpServletResponse response) {
|
||||
globalConfig.redirect("mobile", "/test", response);
|
||||
globalConfig.redirectWithVer("mobile", "/test", response);
|
||||
}
|
||||
|
||||
@RequestMapping("/redirect")
|
||||
@@ -75,7 +75,8 @@ public class TestController {
|
||||
@RoleAuthority("redirect")
|
||||
public ApiResp<JsonTest> redirect(HttpServletResponse response) {
|
||||
|
||||
encryptConfig.passwdCreate("111111@Zz", "");
|
||||
String s1 = encryptConfig.passwdCreate("qU3?wE3{bX", "");
|
||||
LogFactory.get().info(s1);
|
||||
|
||||
JsonTest jsonTest = new JsonTest();
|
||||
jsonTest.setNow(DateUtil.date());
|
||||
@@ -219,8 +220,10 @@ public class TestController {
|
||||
"83_7xqG36kdgwuf8zzWLY3jtz7bg4ucziN-0oxbE0X9zBzwbjZ4S4Ss2RM9uHeSIcRp2K-wEp6MLzWhqo2AXj0Jpzd6IiJdUsRxqdHPvEWqAdOgt83vzZwdDf7tZBkGNGeAFASZS",
|
||||
paramJson);
|
||||
Response execute1 = OkHttpUtil.ofHttpClient().build().newCall(request).execute();
|
||||
FileUtil.writeFromStream(execute1.body().byteStream(), file.getAbsolutePath());
|
||||
execute1.close();
|
||||
if (execute1.body() != null) {
|
||||
FileUtil.writeFromStream(execute1.body().byteStream(), file.getAbsolutePath());
|
||||
execute1.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ApiException("每分钟最多生成5000个二维码,请稍后再试!");
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.tiesheng.springboot-parent</groupId>
|
||||
<artifactId>springboot-parent</artifactId>
|
||||
<version>2.0.5</version>
|
||||
<version>2.0.17-test2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>springboot-annotation</artifactId>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.tiesheng.springboot-parent</groupId>
|
||||
<artifactId>springboot-parent</artifactId>
|
||||
<version>2.0.5</version>
|
||||
<version>2.0.17-test2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>springboot-database</artifactId>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.tiesheng.springboot-parent</groupId>
|
||||
<artifactId>springboot-parent</artifactId>
|
||||
<version>2.0.5</version>
|
||||
<version>2.0.17-test2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>springboot-login</artifactId>
|
||||
|
||||
@@ -170,7 +170,7 @@ public class LoginController {
|
||||
extra = "";
|
||||
}
|
||||
String configUrl = globalConfig.buildPath("/login/wxmp/oauth2/" + service + "?extra=" + extra);
|
||||
String authorizationUrl = platformWxmpConfig.buildAuthorizationUrl(service, configUrl, "snsapi_userinfo");
|
||||
String authorizationUrl = platformWxmpConfig.buildAuthorizationUrl(service, configUrl);
|
||||
response.sendRedirect(authorizationUrl);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,8 +20,7 @@ public class DoLoginInfo {
|
||||
this.info = info;
|
||||
|
||||
// 设置IP
|
||||
HttpServletRequest request = ServletKit.getRequest();
|
||||
this.loginIp = ServletKit.getClientIP(request);
|
||||
this.loginIp = ServletKit.getClientIP();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -43,9 +43,12 @@ public class CorePlatformUniqueService extends TsServiceBase<CorePlatformUniqueM
|
||||
*/
|
||||
public TokenBean login(DoLoginInfo loginInfo) {
|
||||
|
||||
int loginErrorTimes = coreLogLoginMapper.getLoginErrorTimes(loginInfo.getLoginIp());
|
||||
if (loginErrorTimes > 4) {
|
||||
throw new ApiException("登录失败已达5次,请10分钟后再试");
|
||||
int loginErrorTimes = tsLoginConfigurer.getLoginErrorTimes();
|
||||
if (loginErrorTimes > 0) {
|
||||
int currentErrorTimes = coreLogLoginMapper.getLoginErrorTimes(loginInfo.getLoginIp());
|
||||
if (currentErrorTimes >= loginErrorTimes) {
|
||||
throw new ApiException("登录失败已达" + loginErrorTimes + "次,请10分钟后再试");
|
||||
}
|
||||
}
|
||||
|
||||
CorePlatformUnique platformUnique = getOneByColumn("unique_id", loginInfo.getUnique());
|
||||
|
||||
@@ -36,7 +36,7 @@ public interface TsLoginConfigurer {
|
||||
/**
|
||||
* 登录失败的时候
|
||||
*/
|
||||
default void onLoginError(String to,HttpServletResponse response) {
|
||||
default void onLoginError(String to, HttpServletResponse response) {
|
||||
ServletKit.write(response, "404", "text");
|
||||
}
|
||||
|
||||
@@ -66,4 +66,14 @@ public interface TsLoginConfigurer {
|
||||
*/
|
||||
RequestUserInfo getCurrentUserName(TokenBean userId);
|
||||
|
||||
|
||||
/**
|
||||
* 获取登录失败的次数,默认5次
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
default int getLoginErrorTimes() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,7 +17,8 @@ CREATE TABLE `core_log_login`
|
||||
`address` varchar(255) DEFAULT NULL COMMENT 'ip地址',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4 COMMENT ='日志-登录';
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci COMMENT ='日志-登录';
|
||||
|
||||
-- ----------------------------
|
||||
-- Table structure for core_platform_unique
|
||||
@@ -35,6 +36,7 @@ CREATE TABLE `core_platform_unique`
|
||||
`info` text COMMENT '其他参数',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4 COMMENT ='平台-唯一值';
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci COMMENT ='平台-唯一值';
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.tiesheng.springboot-parent</groupId>
|
||||
<artifactId>springboot-parent</artifactId>
|
||||
<version>2.0.5</version>
|
||||
<version>2.0.17-test2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>springboot-message</artifactId>
|
||||
|
||||
@@ -99,7 +99,7 @@ public class AliyunSmsSender implements TsMessageSender {
|
||||
String signature = specialUrlEncode(digest);
|
||||
queryMap.put("Signature", signature);
|
||||
|
||||
String respBody = "";
|
||||
String respBody;
|
||||
try {
|
||||
respBody = OkHttpUtil.get(ENDPOINT + "?Signature=" + signature + sortQueryStringTmp);
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.tiesheng.springboot-parent</groupId>
|
||||
<artifactId>springboot-parent</artifactId>
|
||||
<version>2.0.5</version>
|
||||
<version>2.0.17-test2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>springboot-platform</artifactId>
|
||||
|
||||
@@ -76,15 +76,16 @@ public class PlatformDingConfig {
|
||||
request = OkHttpUtil.ofPost(url, body);
|
||||
}
|
||||
request = request.newBuilder().header("x-acs-dingtalk-access-token", accessToken).build();
|
||||
try {
|
||||
Response response = OkHttpUtil.ofHttpClient().build().newCall(request).execute();
|
||||
try (Response response = OkHttpUtil.ofHttpClient().build().newCall(request).execute()) {
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
String rawBody = response.body().string();
|
||||
DingResponse<T> bean = JSON.parseObject(rawBody, typeReference);
|
||||
bean.setRawBody(rawBody);
|
||||
return bean;
|
||||
} else {
|
||||
LogFactory.get().info(response.body().string());
|
||||
if (response.body() != null) {
|
||||
LogFactory.get().info(response.body().string());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
LogFactory.get().error(e);
|
||||
@@ -246,7 +247,7 @@ public class PlatformDingConfig {
|
||||
JSONObject object = new JSONObject();
|
||||
object.put("dept_id", deptId);
|
||||
object.put("cursor", cursor);
|
||||
object.put("size", 200);
|
||||
object.put("size", 100);
|
||||
|
||||
return doRequest(service, "https://oapi.dingtalk.com/topapi/v2/user/list",
|
||||
object, new TypeReference<DingResponse<DingUserListVo>>() {
|
||||
|
||||
@@ -19,6 +19,7 @@ import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author hao
|
||||
@@ -122,12 +123,12 @@ public class PlatformWxmpConfig {
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String buildAuthorizationUrl(String service, String redirectUrl, String scope) {
|
||||
public String buildAuthorizationUrl(String service, String redirectUrl) {
|
||||
WxConfigBean configBean = getConfigBean(service);
|
||||
return "https://open.weixin.qq.com/connect/oauth2/authorize"
|
||||
+ "?appid=" + configBean.getAppId()
|
||||
+ "&redirect_uri=" + URLUtil.encodeAll(redirectUrl)
|
||||
+ "&response_type=code&scope=" + scope
|
||||
+ "&response_type=code&scope=" + configBean.getScope()
|
||||
+ "&state=STATE#wechat_redirect";
|
||||
}
|
||||
|
||||
@@ -141,7 +142,15 @@ public class PlatformWxmpConfig {
|
||||
public WxUserInfo getOAuth2AccessToken(String service, String code) {
|
||||
WxConfigBean configBean = getConfigBean(service);
|
||||
WxOAuth2AccessToken wxOAuth2AccessToken = WxOAuth2AccessToken.create(configBean.getAppId(), configBean.getAppSecret(), code);
|
||||
WxUserInfo wxUserInfo = WxUserInfo.create(wxOAuth2AccessToken);
|
||||
|
||||
WxUserInfo wxUserInfo = null;
|
||||
if (Objects.equals(configBean.getScope(), "snsapi_userinfo")) {
|
||||
wxUserInfo = WxUserInfo.create(wxOAuth2AccessToken);
|
||||
} else {
|
||||
wxUserInfo = new WxUserInfo();
|
||||
wxUserInfo.setOpenid(wxOAuth2AccessToken.getOpenid());
|
||||
wxUserInfo.setRealUser(wxOAuth2AccessToken.isRealUser());
|
||||
}
|
||||
wxUserInfo.setAppId(configBean.getAppId());
|
||||
return wxUserInfo;
|
||||
}
|
||||
@@ -162,7 +171,8 @@ public class PlatformWxmpConfig {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// setter\getter
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// ////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public Map<String, WxConfigBean> getConfigs() {
|
||||
return configs;
|
||||
|
||||
@@ -7,10 +7,12 @@ public class WxConfigBean {
|
||||
|
||||
private String appId;
|
||||
private String appSecret;
|
||||
private String scope = "snsapi_userinfo";
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// setter\getter
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// ////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public String getAppId() {
|
||||
return appId;
|
||||
@@ -27,4 +29,12 @@ public class WxConfigBean {
|
||||
public void setAppSecret(String appSecret) {
|
||||
this.appSecret = appSecret;
|
||||
}
|
||||
|
||||
public String getScope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
public void setScope(String scope) {
|
||||
this.scope = scope;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ public class WxOAuth2AccessToken {
|
||||
|
||||
private String accessToken;
|
||||
private String openid;
|
||||
private String isSnapshotuser;
|
||||
|
||||
public static WxOAuth2AccessToken create(String appId, String secret, String code) {
|
||||
String response = OkHttpUtil.get("https://api.weixin.qq.com/sns/oauth2/access_token" +
|
||||
@@ -23,10 +24,20 @@ public class WxOAuth2AccessToken {
|
||||
return oAuth2AccessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否是真实用户
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isRealUser() {
|
||||
return !"1".equals(isSnapshotuser);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// setter\getter
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// ////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public String getAccessToken() {
|
||||
return accessToken;
|
||||
@@ -43,4 +54,12 @@ public class WxOAuth2AccessToken {
|
||||
public void setOpenid(String openid) {
|
||||
this.openid = openid;
|
||||
}
|
||||
|
||||
public String getIsSnapshotuser() {
|
||||
return isSnapshotuser;
|
||||
}
|
||||
|
||||
public void setIsSnapshotuser(String isSnapshotuser) {
|
||||
this.isSnapshotuser = isSnapshotuser;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ public class WxUserInfo {
|
||||
private String headimgurl;
|
||||
private String openid;
|
||||
private String appId;
|
||||
private boolean isRealUser;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// 逻辑方法
|
||||
@@ -33,13 +34,16 @@ public class WxUserInfo {
|
||||
String s = OkHttpUtil.get("https://api.weixin.qq.com/sns/userinfo"
|
||||
+ "?access_token=" + oAuth2AccessToken.getAccessToken()
|
||||
+ "&openid=" + oAuth2AccessToken.getOpenid() + "&lang=zh_CN");
|
||||
return JSON.parseObject(s, WxUserInfo.class);
|
||||
WxUserInfo wxUserInfo = JSON.parseObject(s, WxUserInfo.class);
|
||||
wxUserInfo.setRealUser(oAuth2AccessToken.isRealUser());
|
||||
return wxUserInfo;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// setter\getter
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// ////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public String getAccessToken() {
|
||||
return accessToken;
|
||||
@@ -112,4 +116,12 @@ public class WxUserInfo {
|
||||
public void setAppId(String appId) {
|
||||
this.appId = appId;
|
||||
}
|
||||
|
||||
public boolean isRealUser() {
|
||||
return isRealUser;
|
||||
}
|
||||
|
||||
public void setRealUser(boolean realUser) {
|
||||
isRealUser = realUser;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.tiesheng.springboot-parent</groupId>
|
||||
<artifactId>springboot-parent</artifactId>
|
||||
<version>2.0.5</version>
|
||||
<version>2.0.17-test2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>springboot-role</artifactId>
|
||||
|
||||
@@ -49,6 +49,7 @@ public class CommRoleController {
|
||||
.in("id", list)
|
||||
.eq(CoreRoleServer.IS_DELETED, 0)
|
||||
.eq("is_open", 1)
|
||||
.orderByAsc("sort")
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ 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.dto.ServerListDTO;
|
||||
import com.tiesheng.role.pojos.vo.ServiceMenuVO;
|
||||
import com.tiesheng.role.service.CoreRoleService;
|
||||
import com.tiesheng.util.pojos.ApiResp;
|
||||
@@ -29,10 +30,11 @@ public class RoleServerController {
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/server/list")
|
||||
public ApiResp<List<CoreRoleServer>> list() {
|
||||
public ApiResp<List<CoreRoleServer>> list(ServerListDTO dto) {
|
||||
return ApiResp.respOK(coreRoleService.getServerMapper().selectList(new QueryWrapper<CoreRoleServer>()
|
||||
.eq(CoreRoleServer.IS_DELETED, 0)
|
||||
.eq("is_open", 1)
|
||||
.eq(StrUtil.isNotEmpty(dto.getIsOpen()), "is_open", dto.getIsOpen())
|
||||
.orderByAsc("sort")
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -30,6 +30,12 @@ public class CoreRoleUser extends DaoBase {
|
||||
@TableField(value = "type_id")
|
||||
private String typeId;
|
||||
|
||||
/**
|
||||
* 说明
|
||||
*/
|
||||
@TableField(value = "remark")
|
||||
private String remark;
|
||||
|
||||
/**
|
||||
* 过期时间,无则不过期
|
||||
*/
|
||||
@@ -108,6 +114,14 @@ public class CoreRoleUser extends DaoBase {
|
||||
this.typeId = typeId;
|
||||
}
|
||||
|
||||
public String getRemark() {
|
||||
return remark;
|
||||
}
|
||||
|
||||
public void setRemark(String remark) {
|
||||
this.remark = remark;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取过期时间,无则不过期
|
||||
*
|
||||
@@ -179,4 +193,4 @@ public class CoreRoleUser extends DaoBase {
|
||||
public void setExt3(String ext3) {
|
||||
this.ext3 = ext3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.tiesheng.role.pojos.dto;
|
||||
|
||||
public class ServerListDTO {
|
||||
|
||||
private String isOpen;
|
||||
|
||||
|
||||
public String getIsOpen() {
|
||||
return isOpen;
|
||||
}
|
||||
|
||||
public void setIsOpen(String isOpen) {
|
||||
this.isOpen = isOpen;
|
||||
}
|
||||
}
|
||||
@@ -138,7 +138,6 @@ public class CoreRoleService extends TsServiceBase<CoreRoleGroupMapper, CoreRole
|
||||
coreRoleGroupRxMapper.batchInsert(list);
|
||||
onRoleChange(dto.getId(), "");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -148,6 +147,9 @@ public class CoreRoleService extends TsServiceBase<CoreRoleGroupMapper, CoreRole
|
||||
* @param roleUser
|
||||
*/
|
||||
public void roleUserUpdate(CoreRoleUser roleUser) {
|
||||
Validator.validateNotEmpty(roleUser.getType(), "请选择授权方式");
|
||||
Validator.validateNotEmpty(roleUser.getTypeId(), "请选择授权" + (Objects.equals(roleUser.getType(), "menu") ? "菜单" : "职位"));
|
||||
|
||||
if (StrUtil.isNotEmpty(roleUser.getId())) {
|
||||
coreRoleUserMapper.updateById(roleUser);
|
||||
} else {
|
||||
|
||||
@@ -24,6 +24,7 @@ create table core_role_authority
|
||||
ext3 varchar(500) null comment '扩展3'
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci
|
||||
comment '角色-权限';
|
||||
|
||||
create table core_role_group
|
||||
@@ -43,6 +44,7 @@ create table core_role_group
|
||||
ext3 varchar(500) null comment '扩展3'
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci
|
||||
comment '角色-分组';
|
||||
|
||||
create table core_role_group_rx
|
||||
@@ -56,6 +58,7 @@ create table core_role_group_rx
|
||||
menu_id varchar(50) not null comment '菜单id'
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci
|
||||
comment '角色-分组-关系';
|
||||
|
||||
create table core_role_server
|
||||
@@ -76,6 +79,7 @@ create table core_role_server
|
||||
ext3 varchar(500) null comment '扩展3'
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci
|
||||
comment '角色-服务';
|
||||
|
||||
create table core_role_user
|
||||
@@ -94,6 +98,7 @@ create table core_role_user
|
||||
ext3 varchar(500) null comment '扩展3'
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci
|
||||
comment '角色-用户';
|
||||
|
||||
alter table core_role_authority
|
||||
@@ -108,4 +113,7 @@ alter table core_role_authority
|
||||
alter table core_role_group_rx
|
||||
add type varchar(10) null comment '关联类型:dep-依赖,bind-绑定';
|
||||
|
||||
alter table core_role_user
|
||||
add remark varchar(500) null comment '说明' after type_id;
|
||||
|
||||
SET FOREIGN_KEY_CHECKS = 1;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
<result column="user_id" jdbcType="VARCHAR" property="userId" />
|
||||
<result column="type" jdbcType="VARCHAR" property="type" />
|
||||
<result column="type_id" jdbcType="VARCHAR" property="typeId" />
|
||||
<result column="remark" jdbcType="VARCHAR" property="remark" />
|
||||
<result column="expire_time" jdbcType="TIMESTAMP" property="expireTime" />
|
||||
<result column="ext1" jdbcType="VARCHAR" property="ext1" />
|
||||
<result column="ext2" jdbcType="VARCHAR" property="ext2" />
|
||||
@@ -18,7 +19,7 @@
|
||||
</resultMap>
|
||||
<sql id="Base_Column_List">
|
||||
<!--@mbg.generated-->
|
||||
id, create_time, update_time, is_deleted, user_id, `type`, type_id, expire_time,
|
||||
id, create_time, update_time, is_deleted, user_id, `type`, type_id, remark, expire_time,
|
||||
ext1, ext2, ext3
|
||||
</sql>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.tiesheng.springboot-parent</groupId>
|
||||
<artifactId>springboot-parent</artifactId>
|
||||
<version>2.0.5</version>
|
||||
<version>2.0.17-test2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>springboot-util</artifactId>
|
||||
|
||||
@@ -17,7 +17,25 @@ public class ServletKit extends ServletUtil {
|
||||
public static HttpServletRequest getRequest() {
|
||||
ServletRequestAttributes attributes = (ServletRequestAttributes)
|
||||
RequestContextHolder.getRequestAttributes();
|
||||
return attributes.getRequest();
|
||||
if (attributes != null) {
|
||||
return attributes.getRequest();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取请求头
|
||||
*
|
||||
* @param name 请求头
|
||||
* @return 请求头
|
||||
*/
|
||||
public static String getHeader(String name) {
|
||||
HttpServletRequest request = getRequest();
|
||||
if (request == null) {
|
||||
return "";
|
||||
}
|
||||
return getHeader(request, name, "utf-8");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -27,6 +45,9 @@ public class ServletKit extends ServletUtil {
|
||||
*/
|
||||
public static String getClientIP() {
|
||||
HttpServletRequest request = getRequest();
|
||||
if (request == null) {
|
||||
return "";
|
||||
}
|
||||
return getClientIP(request);
|
||||
}
|
||||
|
||||
|
||||
@@ -95,12 +95,13 @@ public class GlobalConfig {
|
||||
|
||||
|
||||
/**
|
||||
* 重定向
|
||||
* 构建待版本号的路径
|
||||
*
|
||||
* @param htmlDir 资源目录
|
||||
* @param htmlDir
|
||||
* @param route
|
||||
* @return
|
||||
*/
|
||||
public void redirect(String htmlDir, String route, HttpServletResponse response) {
|
||||
public String buildByVersion(String htmlDir, String route) {
|
||||
if (!StrUtil.endWith(htmlDir, "/")) {
|
||||
htmlDir = htmlDir + "/";
|
||||
}
|
||||
@@ -129,16 +130,32 @@ public class GlobalConfig {
|
||||
throw new ApiException("无法重定向,请检查资源");
|
||||
}
|
||||
CollUtil.sort(versions, (o1, o2) -> -VersionComparator.INSTANCE.compare(o1, o2));
|
||||
String path = buildPath(String.format("/%s%s/index.html#%s", htmlDir, versions.get(0), route));
|
||||
response.sendRedirect(path);
|
||||
return buildPath(String.format("/%s%s/index.html#%s", htmlDir, versions.get(0), route));
|
||||
} catch (IOException e) {
|
||||
LogFactory.get().info(e);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 重定向
|
||||
*
|
||||
* @param htmlDir 资源目录
|
||||
* @param route
|
||||
*/
|
||||
public void redirectWithVer(String htmlDir, String route, HttpServletResponse response) {
|
||||
try {
|
||||
response.sendRedirect(buildByVersion(htmlDir, route));
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// setter\getter
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// ////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
public String getUploadDir() {
|
||||
|
||||
@@ -384,7 +384,7 @@ public class JWT implements RegisteredPayload<JWT> {
|
||||
* @since 5.7.4
|
||||
*/
|
||||
public boolean validate(long leeway) {
|
||||
if (false == verify()) {
|
||||
if (!verify()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.tiesheng.util.jwt;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.exceptions.ValidateException;
|
||||
import cn.hutool.core.util.NumberUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.tiesheng.util.jwt.signers.JWTSigner;
|
||||
import com.tiesheng.util.jwt.signers.NoneJWTSigner;
|
||||
@@ -160,13 +161,13 @@ public class JWTValidator {
|
||||
}
|
||||
|
||||
final String algorithmIdInSigner = signer.getAlgorithmId();
|
||||
if (false == StrUtil.equals(algorithmId, algorithmIdInSigner)) {
|
||||
if (!StrUtil.equals(algorithmId, algorithmIdInSigner)) {
|
||||
throw new ValidateException("Algorithm [{}] defined in header doesn't match to [{}]!"
|
||||
, algorithmId, algorithmIdInSigner);
|
||||
}
|
||||
|
||||
// 通过算法验证签名是否正确
|
||||
if (false == jwt.verify(signer)) {
|
||||
if (!jwt.verify(signer)) {
|
||||
throw new ValidateException("Signature verification failed!");
|
||||
}
|
||||
}
|
||||
@@ -200,7 +201,10 @@ public class JWTValidator {
|
||||
validateNotAfter(JWTPayload.NOT_BEFORE, notBefore, now, leeway);
|
||||
|
||||
// 检查失效时间(失效时间不能早于当前时间)
|
||||
final Date expiresAt = payload.getClaimsJson().getDate(JWTPayload.EXPIRES_AT);
|
||||
// 这里兼容一下旧版本,旧版本使用的是10位数的秒作为数据
|
||||
String string = payload.getClaimsJson().getString(JWTPayload.EXPIRES_AT);
|
||||
Date expiresAt = StrUtil.length(string) == 10 ? DateUtil.date(NumberUtil.parseLong(string) * 1000L)
|
||||
: DateUtil.parse(string);
|
||||
validateNotBefore(JWTPayload.EXPIRES_AT, expiresAt, now, leeway);
|
||||
|
||||
// 检查签发时间(签发时间不能晚于当前时间)
|
||||
|
||||
@@ -84,7 +84,7 @@ public class TsCacheService {
|
||||
* 验证 图片验证码
|
||||
*/
|
||||
public void verifyCaptcha(String value) {
|
||||
String captchaKey = ServletUtil.getHeader(ServletKit.getRequest(), "captcha", "utf-8");
|
||||
String captchaKey = ServletKit.getHeader("captcha");
|
||||
String cache = get(captchaKey);
|
||||
if (StrUtil.isEmpty(cache) || !StrUtil.equals(cache, value)) {
|
||||
throw new ApiException("验证码不正确");
|
||||
|
||||
@@ -10,7 +10,7 @@ import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnMissingBean(value = TsCacheHandler.class, ignored = {TsCacheTimedHandler.class, TsCacheTimedHandler.class})
|
||||
@ConditionalOnMissingBean(value = TsCacheHandler.class, ignored = {TsCacheTimedHandler.class})
|
||||
public class TsCacheTimedHandler implements TsCacheHandler {
|
||||
|
||||
private static volatile TimedCache<String, String> timedCache;
|
||||
|
||||
@@ -57,6 +57,14 @@ public class OkHttpUtil {
|
||||
return ResponseBody.create(MediaType.parse("application/json; charset=utf-8"), json);
|
||||
}
|
||||
|
||||
public static FormBody ofFormResponse(Map<String, String> form) {
|
||||
FormBody.Builder formBuilder = new FormBody.Builder();
|
||||
for (String key : form.keySet()) {
|
||||
formBuilder.add(key, form.get(key));
|
||||
}
|
||||
return formBuilder.build();
|
||||
}
|
||||
|
||||
public static MultipartBody.Builder ofMultipartBody(File file) {
|
||||
return new MultipartBody.Builder()
|
||||
.setType(MultipartBody.FORM)
|
||||
@@ -83,9 +91,11 @@ public class OkHttpUtil {
|
||||
}
|
||||
|
||||
public static String get(String urlString, int timeout) {
|
||||
try {
|
||||
return ofHttpClient().connectTimeout(timeout, TimeUnit.MILLISECONDS)
|
||||
.build().newCall(ofGet(urlString)).execute().body().string();
|
||||
try (Response execute = ofHttpClient().connectTimeout(timeout, TimeUnit.MILLISECONDS)
|
||||
.build().newCall(ofGet(urlString)).execute()) {
|
||||
if (execute.body() != null) {
|
||||
return execute.body().string();
|
||||
}
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
return null;
|
||||
@@ -96,16 +106,12 @@ public class OkHttpUtil {
|
||||
// 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> formMap) {
|
||||
return post(urlString, formMap, 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, Map<String, String> formMap, int timeout) {
|
||||
return post(urlString, ofFormResponse(formMap), timeout);
|
||||
}
|
||||
|
||||
public static String post(String urlString, JSONObject body) {
|
||||
@@ -117,9 +123,11 @@ public class OkHttpUtil {
|
||||
}
|
||||
|
||||
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();
|
||||
try (Response response = ofHttpClient().connectTimeout(timeout, TimeUnit.MILLISECONDS)
|
||||
.build().newCall(ofPost(urlString, body)).execute()) {
|
||||
if (response.body() != null) {
|
||||
return response.body().string();
|
||||
}
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
return null;
|
||||
@@ -135,11 +143,10 @@ public class OkHttpUtil {
|
||||
}
|
||||
|
||||
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();
|
||||
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);
|
||||
}
|
||||
@@ -150,11 +157,10 @@ public class OkHttpUtil {
|
||||
}
|
||||
|
||||
public static byte[] downloadBytes(String url) {
|
||||
try {
|
||||
Response response = ofHttpClient()
|
||||
.connectTimeout(0, TimeUnit.MILLISECONDS)
|
||||
.readTimeout(0, TimeUnit.MILLISECONDS)
|
||||
.build().newCall(ofGet(url)).execute();
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
package com.tiesheng.util.useragent;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ReUtil;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 浏览器对象
|
||||
*
|
||||
* @author looly
|
||||
* @since 4.2.1
|
||||
*/
|
||||
public class Browser extends UserAgentInfo {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 未知
|
||||
*/
|
||||
public static final Browser Unknown = new Browser(NameUnknown, null, null);
|
||||
/**
|
||||
* 其它版本
|
||||
*/
|
||||
public static final String Other_Version = "[\\/ ]([\\d\\w\\.\\-]+)";
|
||||
|
||||
/**
|
||||
* 支持的浏览器类型
|
||||
*/
|
||||
public static final List<Browser> browers = CollUtil.newArrayList(
|
||||
// 部分特殊浏览器是基于安卓、Iphone等的,需要优先判断
|
||||
// 企业微信 企业微信使用微信浏览器内核,会包含 MicroMessenger 所以要放在前面
|
||||
new Browser("wxwork", "wxwork", "wxwork\\/([\\d\\w\\.\\-]+)"),
|
||||
// 微信
|
||||
new Browser("MicroMessenger", "MicroMessenger", Other_Version),
|
||||
// 微信小程序
|
||||
new Browser("miniProgram", "miniProgram", Other_Version),
|
||||
// QQ浏览器
|
||||
new Browser("QQBrowser", "MQQBrowser", "MQQBrowser\\/([\\d\\w\\.\\-]+)"),
|
||||
// 钉钉PC端浏览器
|
||||
new Browser("DingTalk-win", "dingtalk-win", "DingTalk\\(([\\d\\w\\.\\-]+)\\)"),
|
||||
// 钉钉内置浏览器
|
||||
new Browser("DingTalk", "DingTalk", "AliApp\\(DingTalk\\/([\\d\\w\\.\\-]+)\\)"),
|
||||
// 支付宝内置浏览器
|
||||
new Browser("Alipay", "AlipayClient", "AliApp\\(AP\\/([\\d\\w\\.\\-]+)\\)"),
|
||||
// 淘宝内置浏览器
|
||||
new Browser("Taobao", "taobao", "AliApp\\(TB\\/([\\d\\w\\.\\-]+)\\)"),
|
||||
// UC浏览器
|
||||
new Browser("UCBrowser", "UC?Browser", "UC?Browser\\/([\\d\\w\\.\\-]+)"),
|
||||
// XiaoMi 浏览器
|
||||
new Browser("MiuiBrowser", "MiuiBrowser|mibrowser", "MiuiBrowser\\/([\\d\\w\\.\\-]+)"),
|
||||
// 夸克浏览器
|
||||
new Browser("Quark", "Quark", Other_Version),
|
||||
// 联想浏览器
|
||||
new Browser("Lenovo", "SLBrowser", "SLBrowser/([\\d\\w\\.\\-]+)"),
|
||||
new Browser("MSEdge", "Edge|Edg", "(?:edge|Edg|EdgA)\\/([\\d\\w\\.\\-]+)"),
|
||||
new Browser("Chrome", "chrome", Other_Version),
|
||||
new Browser("Firefox", "firefox", Other_Version),
|
||||
new Browser("IEMobile", "iemobile", Other_Version),
|
||||
new Browser("Android Browser", "android", "version\\/([\\d\\w\\.\\-]+)"),
|
||||
new Browser("Safari", "safari", "version\\/([\\d\\w\\.\\-]+)"),
|
||||
new Browser("Opera", "opera", Other_Version),
|
||||
new Browser("Konqueror", "konqueror", Other_Version),
|
||||
new Browser("PS3", "playstation 3", "([\\d\\w\\.\\-]+)\\)\\s*$"),
|
||||
new Browser("PSP", "playstation portable", "([\\d\\w\\.\\-]+)\\)?\\s*$"),
|
||||
new Browser("Lotus", "lotus.notes", "Lotus-Notes\\/([\\w.]+)"),
|
||||
new Browser("Thunderbird", "thunderbird", Other_Version),
|
||||
new Browser("Netscape", "netscape", Other_Version),
|
||||
new Browser("Seamonkey", "seamonkey", Other_Version),
|
||||
new Browser("Outlook", "microsoft.outlook", Other_Version),
|
||||
new Browser("Evolution", "evolution", Other_Version),
|
||||
new Browser("MSIE", "msie", "msie ([\\d\\w\\.\\-]+)"),
|
||||
new Browser("MSIE11", "rv:11", "rv:([\\d\\w\\.\\-]+)"),
|
||||
new Browser("Gabble", "Gabble", Other_Version),
|
||||
new Browser("Yammer Desktop", "AdobeAir", "([\\d\\w\\.\\-]+)\\/Yammer"),
|
||||
new Browser("Yammer Mobile", "Yammer[\\s]+([\\d\\w\\.\\-]+)", "Yammer[\\s]+([\\d\\w\\.\\-]+)"),
|
||||
new Browser("Apache HTTP Client", "Apache\\\\-HttpClient", "Apache\\-HttpClient\\/([\\d\\w\\.\\-]+)"),
|
||||
new Browser("BlackBerry", "BlackBerry", "BlackBerry[\\d]+\\/([\\d\\w\\.\\-]+)")
|
||||
);
|
||||
|
||||
/**
|
||||
* 添加自定义的浏览器类型
|
||||
*
|
||||
* @param name 浏览器名称
|
||||
* @param regex 关键字或表达式
|
||||
* @param versionRegex 匹配版本的正则
|
||||
* @since 5.7.4
|
||||
*/
|
||||
synchronized public static void addCustomBrowser(String name, String regex, String versionRegex) {
|
||||
browers.add(new Browser(name, regex, versionRegex));
|
||||
}
|
||||
|
||||
private Pattern versionPattern;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param name 浏览器名称
|
||||
* @param regex 关键字或表达式
|
||||
* @param versionRegex 匹配版本的正则
|
||||
*/
|
||||
public Browser(String name, String regex, String versionRegex) {
|
||||
super(name, regex);
|
||||
if (Other_Version.equals(versionRegex)) {
|
||||
versionRegex = name + versionRegex;
|
||||
}
|
||||
if (null != versionRegex) {
|
||||
this.versionPattern = Pattern.compile(versionRegex, Pattern.CASE_INSENSITIVE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取浏览器版本
|
||||
*
|
||||
* @param userAgentString User-Agent字符串
|
||||
* @return 版本
|
||||
*/
|
||||
public String getVersion(String userAgentString) {
|
||||
if(isUnknown()){
|
||||
return null;
|
||||
}
|
||||
return ReUtil.getGroup1(this.versionPattern, userAgentString);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否移动浏览器
|
||||
*
|
||||
* @return 是否移动浏览器
|
||||
*/
|
||||
public boolean isMobile() {
|
||||
final String name = this.getName();
|
||||
return "PSP".equals(name) ||
|
||||
"Yammer Mobile".equals(name) ||
|
||||
"Android Browser".equals(name) ||
|
||||
"IEMobile".equals(name) ||
|
||||
"MicroMessenger".equals(name) ||
|
||||
"miniProgram".equals(name) ||
|
||||
"DingTalk".equals(name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.tiesheng.util.useragent;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ReUtil;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 引擎对象
|
||||
*
|
||||
* @author looly
|
||||
* @since 4.2.1
|
||||
*/
|
||||
public class Engine extends UserAgentInfo {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/** 未知 */
|
||||
public static final Engine Unknown = new Engine(NameUnknown, null);
|
||||
|
||||
/**
|
||||
* 支持的引擎类型
|
||||
*/
|
||||
public static final List<Engine> engines = CollUtil.newArrayList(
|
||||
new Engine("Trident", "trident"),
|
||||
new Engine("Webkit", "webkit"),
|
||||
new Engine("Chrome", "chrome"),
|
||||
new Engine("Opera", "opera"),
|
||||
new Engine("Presto", "presto"),
|
||||
new Engine("Gecko", "gecko"),
|
||||
new Engine("KHTML", "khtml"),
|
||||
new Engine("Konqueror", "konqueror"),
|
||||
new Engine("MIDP", "MIDP")
|
||||
);
|
||||
|
||||
private final Pattern versionPattern;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param name 引擎名称
|
||||
* @param regex 关键字或表达式
|
||||
*/
|
||||
public Engine(String name, String regex) {
|
||||
super(name, regex);
|
||||
this.versionPattern = Pattern.compile(name + "[/\\- ]([\\d\\w.\\-]+)", Pattern.CASE_INSENSITIVE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取引擎版本
|
||||
*
|
||||
* @param userAgentString User-Agent字符串
|
||||
* @return 版本
|
||||
* @since 5.7.4
|
||||
*/
|
||||
public String getVersion(String userAgentString) {
|
||||
if(isUnknown()){
|
||||
return null;
|
||||
}
|
||||
return ReUtil.getGroup1(this.versionPattern, userAgentString);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package com.tiesheng.util.useragent;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ReUtil;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 系统对象
|
||||
*
|
||||
* @author looly
|
||||
* @since 4.2.1
|
||||
*/
|
||||
public class OS extends UserAgentInfo {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 未知
|
||||
*/
|
||||
public static final OS Unknown = new OS(NameUnknown, null);
|
||||
|
||||
/**
|
||||
* 支持的引擎类型
|
||||
*/
|
||||
public static final List<OS> oses = CollUtil.newArrayList(//
|
||||
new OS("Windows 10 or Windows Server 2016", "windows nt 10\\.0", "windows nt (10\\.0)"),//
|
||||
new OS("Windows 8.1 or Windows Server 2012R2", "windows nt 6\\.3", "windows nt (6\\.3)"),//
|
||||
new OS("Windows 8 or Windows Server 2012", "windows nt 6\\.2", "windows nt (6\\.2)"),//
|
||||
new OS("Windows Vista", "windows nt 6\\.0", "windows nt (6\\.0)"), //
|
||||
new OS("Windows 7 or Windows Server 2008R2", "windows nt 6\\.1", "windows nt (6\\.1)"), //
|
||||
new OS("Windows 2003", "windows nt 5\\.2", "windows nt (5\\.2)"), //
|
||||
new OS("Windows XP", "windows nt 5\\.1", "windows nt (5\\.1)"), //
|
||||
new OS("Windows 2000", "windows nt 5\\.0", "windows nt (5\\.0)"), //
|
||||
new OS("Windows Phone", "windows (ce|phone|mobile)( os)?", "windows (?:ce|phone|mobile) (\\d+([._]\\d+)*)"), //
|
||||
new OS("Windows", "windows"), //
|
||||
new OS("OSX", "os x (\\d+)[._](\\d+)", "os x (\\d+([._]\\d+)*)"), //
|
||||
new OS("Android", "Android", "Android (\\d+([._]\\d+)*)"),//
|
||||
new OS("Android", "XiaoMi|MI\\s+", "\\(X(\\d+([._]\\d+)*)"),//
|
||||
new OS("Linux", "linux"), //
|
||||
new OS("Wii", "wii", "wii libnup/(\\d+([._]\\d+)*)"), //
|
||||
new OS("PS3", "playstation 3", "playstation 3; (\\d+([._]\\d+)*)"), //
|
||||
new OS("PSP", "playstation portable", "Portable\\); (\\d+([._]\\d+)*)"), //
|
||||
new OS("iPad", "\\(iPad.*os (\\d+)[._](\\d+)", "\\(iPad.*os (\\d+([._]\\d+)*)"), //
|
||||
new OS("iPhone", "\\(iPhone.*os (\\d+)[._](\\d+)", "\\(iPhone.*os (\\d+([._]\\d+)*)"), //
|
||||
new OS("YPod", "iPod touch[\\s\\;]+iPhone.*os (\\d+)[._](\\d+)", "iPod touch[\\s\\;]+iPhone.*os (\\d+([._]\\d+)*)"), //
|
||||
new OS("YPad", "iPad[\\s\\;]+iPhone.*os (\\d+)[._](\\d+)", "iPad[\\s\\;]+iPhone.*os (\\d+([._]\\d+)*)"), //
|
||||
new OS("YPhone", "iPhone[\\s\\;]+iPhone.*os (\\d+)[._](\\d+)", "iPhone[\\s\\;]+iPhone.*os (\\d+([._]\\d+)*)"), //
|
||||
new OS("Symbian", "symbian(os)?"), //
|
||||
new OS("Darwin", "Darwin\\/([\\d\\w\\.\\-]+)", "Darwin\\/([\\d\\w\\.\\-]+)"), //
|
||||
new OS("Adobe Air", "AdobeAir\\/([\\d\\w\\.\\-]+)", "AdobeAir\\/([\\d\\w\\.\\-]+)"), //
|
||||
new OS("Java", "Java[\\s]+([\\d\\w\\.\\-]+)", "Java[\\s]+([\\d\\w\\.\\-]+)")//
|
||||
);
|
||||
|
||||
/**
|
||||
* 添加自定义的系统类型
|
||||
*
|
||||
* @param name 浏览器名称
|
||||
* @param regex 关键字或表达式
|
||||
* @param versionRegex 匹配版本的正则
|
||||
* @since 5.7.4
|
||||
*/
|
||||
synchronized public static void addCustomOs(String name, String regex, String versionRegex) {
|
||||
oses.add(new OS(name, regex, versionRegex));
|
||||
}
|
||||
|
||||
private Pattern versionPattern;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param name 系统名称
|
||||
* @param regex 关键字或表达式
|
||||
*/
|
||||
public OS(String name, String regex) {
|
||||
this(name, regex, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param name 系统名称
|
||||
* @param regex 关键字或表达式
|
||||
* @param versionRegex 版本正则表达式
|
||||
* @since 5.7.4
|
||||
*/
|
||||
public OS(String name, String regex, String versionRegex) {
|
||||
super(name, regex);
|
||||
if (null != versionRegex) {
|
||||
this.versionPattern = Pattern.compile(versionRegex, Pattern.CASE_INSENSITIVE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取浏览器版本
|
||||
*
|
||||
* @param userAgentString User-Agent字符串
|
||||
* @return 版本
|
||||
*/
|
||||
public String getVersion(String userAgentString) {
|
||||
if(isUnknown() || null == this.versionPattern){
|
||||
// 无版本信息
|
||||
return null;
|
||||
}
|
||||
return ReUtil.getGroup1(this.versionPattern, userAgentString);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
package com.tiesheng.util.useragent;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 平台对象
|
||||
*
|
||||
* @author looly
|
||||
* @since 4.2.1
|
||||
*/
|
||||
public class Platform extends UserAgentInfo {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 未知
|
||||
*/
|
||||
public static final Platform Unknown = new Platform(NameUnknown, null);
|
||||
|
||||
/**
|
||||
* Iphone
|
||||
*/
|
||||
public static final Platform IPHONE = new Platform("iPhone", "iphone");
|
||||
/**
|
||||
* ipod
|
||||
*/
|
||||
public static final Platform IPOD = new Platform("iPod", "ipod");
|
||||
/**
|
||||
* ipad
|
||||
*/
|
||||
public static final Platform IPAD = new Platform("iPad", "ipad");
|
||||
|
||||
/**
|
||||
* android
|
||||
*/
|
||||
public static final Platform ANDROID = new Platform("Android", "android");
|
||||
/**
|
||||
* android
|
||||
*/
|
||||
public static final Platform GOOGLE_TV = new Platform("GoogleTV", "googletv");
|
||||
|
||||
/**
|
||||
* Windows Phone
|
||||
*/
|
||||
public static final Platform WINDOWS_PHONE = new Platform("Windows Phone", "windows (ce|phone|mobile)( os)?");
|
||||
|
||||
/**
|
||||
* 支持的移动平台类型
|
||||
*/
|
||||
public static final List<Platform> mobilePlatforms = CollUtil.newArrayList(//
|
||||
WINDOWS_PHONE, //
|
||||
IPAD, //
|
||||
IPOD, //
|
||||
IPHONE, //
|
||||
new Platform("Android", "XiaoMi|MI\\s+"), //
|
||||
ANDROID, //
|
||||
GOOGLE_TV, //
|
||||
new Platform("htcFlyer", "htc_flyer"), //
|
||||
new Platform("Symbian", "symbian(os)?"), //
|
||||
new Platform("Blackberry", "blackberry") //
|
||||
);
|
||||
|
||||
/**
|
||||
* 支持的桌面平台类型
|
||||
*/
|
||||
public static final List<Platform> desktopPlatforms = CollUtil.newArrayList(//
|
||||
new Platform("Windows", "windows"), //
|
||||
new Platform("Mac", "(macintosh|darwin)"), //
|
||||
new Platform("Linux", "linux"), //
|
||||
new Platform("Wii", "wii"), //
|
||||
new Platform("Playstation", "playstation"), //
|
||||
new Platform("Java", "java") //
|
||||
);
|
||||
|
||||
/**
|
||||
* 支持的平台类型
|
||||
*/
|
||||
public static final List<Platform> platforms;
|
||||
|
||||
static {
|
||||
platforms = new ArrayList<>(13);
|
||||
platforms.addAll(mobilePlatforms);
|
||||
platforms.addAll(desktopPlatforms);
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param name 平台名称
|
||||
* @param regex 关键字或表达式
|
||||
*/
|
||||
public Platform(String name, String regex) {
|
||||
super(name, regex);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为移动平台
|
||||
*
|
||||
* @return 是否为移动平台
|
||||
*/
|
||||
public boolean isMobile() {
|
||||
return mobilePlatforms.contains(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为Iphone或者iPod设备
|
||||
*
|
||||
* @return 是否为Iphone或者iPod设备
|
||||
* @since 5.2.3
|
||||
*/
|
||||
public boolean isIPhoneOrIPod() {
|
||||
return this.equals(IPHONE) || this.equals(IPOD);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为Iphone或者iPod设备
|
||||
*
|
||||
* @return 是否为Iphone或者iPod设备
|
||||
* @since 5.2.3
|
||||
*/
|
||||
public boolean isIPad() {
|
||||
return this.equals(IPAD);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为IOS平台,包括IPhone、IPod、IPad
|
||||
*
|
||||
* @return 是否为IOS平台,包括IPhone、IPod、IPad
|
||||
* @since 5.2.3
|
||||
*/
|
||||
public boolean isIos() {
|
||||
return isIPhoneOrIPod() || isIPad();
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为Android平台,包括Android和Google TV
|
||||
*
|
||||
* @return 是否为Android平台,包括Android和Google TV
|
||||
* @since 5.2.3
|
||||
*/
|
||||
public boolean isAndroid() {
|
||||
return this.equals(ANDROID) || this.equals(GOOGLE_TV);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
package com.tiesheng.util.useragent;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* User-Agent信息对象
|
||||
*
|
||||
* @author looly
|
||||
* @since 4.2.1
|
||||
*/
|
||||
public class UserAgent implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 是否为移动平台
|
||||
*/
|
||||
private boolean mobile;
|
||||
/**
|
||||
* 浏览器类型
|
||||
*/
|
||||
private Browser browser;
|
||||
/**
|
||||
* 浏览器版本
|
||||
*/
|
||||
private String version;
|
||||
|
||||
/**
|
||||
* 平台类型
|
||||
*/
|
||||
private Platform platform;
|
||||
|
||||
/**
|
||||
* 系统类型
|
||||
*/
|
||||
private OS os;
|
||||
/**
|
||||
* 系统版本
|
||||
*/
|
||||
private String osVersion;
|
||||
|
||||
/**
|
||||
* 引擎类型
|
||||
*/
|
||||
private Engine engine;
|
||||
/**
|
||||
* 引擎版本
|
||||
*/
|
||||
private String engineVersion;
|
||||
|
||||
/**
|
||||
* 是否为移动平台
|
||||
*
|
||||
* @return 是否为移动平台
|
||||
*/
|
||||
public boolean isMobile() {
|
||||
return mobile;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置是否为移动平台
|
||||
*
|
||||
* @param mobile 是否为移动平台
|
||||
*/
|
||||
public void setMobile(boolean mobile) {
|
||||
this.mobile = mobile;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取浏览器类型
|
||||
*
|
||||
* @return 浏览器类型
|
||||
*/
|
||||
public Browser getBrowser() {
|
||||
return browser;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置浏览器类型
|
||||
*
|
||||
* @param browser 浏览器类型
|
||||
*/
|
||||
public void setBrowser(Browser browser) {
|
||||
this.browser = browser;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取平台类型
|
||||
*
|
||||
* @return 平台类型
|
||||
*/
|
||||
public Platform getPlatform() {
|
||||
return platform;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置平台类型
|
||||
*
|
||||
* @param platform 平台类型
|
||||
*/
|
||||
public void setPlatform(Platform platform) {
|
||||
this.platform = platform;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取系统类型
|
||||
*
|
||||
* @return 系统类型
|
||||
*/
|
||||
public OS getOs() {
|
||||
return os;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置系统类型
|
||||
*
|
||||
* @param os 系统类型
|
||||
*/
|
||||
public void setOs(OS os) {
|
||||
this.os = os;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取系统版本
|
||||
*
|
||||
* @return 系统版本
|
||||
* @since 5.7.4
|
||||
*/
|
||||
public String getOsVersion() {
|
||||
return this.osVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置系统版本
|
||||
*
|
||||
* @param osVersion 系统版本
|
||||
* @since 5.7.4
|
||||
*/
|
||||
public void setOsVersion(String osVersion) {
|
||||
this.osVersion = osVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取引擎类型
|
||||
*
|
||||
* @return 引擎类型
|
||||
*/
|
||||
public Engine getEngine() {
|
||||
return engine;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置引擎类型
|
||||
*
|
||||
* @param engine 引擎类型
|
||||
*/
|
||||
public void setEngine(Engine engine) {
|
||||
this.engine = engine;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取浏览器版本
|
||||
*
|
||||
* @return 浏览器版本
|
||||
*/
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置浏览器版本
|
||||
*
|
||||
* @param version 浏览器版本
|
||||
*/
|
||||
public void setVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取引擎版本
|
||||
*
|
||||
* @return 引擎版本
|
||||
*/
|
||||
public String getEngineVersion() {
|
||||
return engineVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置引擎版本
|
||||
*
|
||||
* @param engineVersion 引擎版本
|
||||
*/
|
||||
public void setEngineVersion(String engineVersion) {
|
||||
this.engineVersion = engineVersion;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
package com.tiesheng.util.useragent;
|
||||
|
||||
import cn.hutool.core.util.ReUtil;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* User-agent信息
|
||||
*
|
||||
* @author looly
|
||||
* @since 4.2.1
|
||||
*/
|
||||
public class UserAgentInfo implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 未知类型
|
||||
*/
|
||||
public static final String NameUnknown = "Unknown";
|
||||
|
||||
/** 信息名称 */
|
||||
private final String name;
|
||||
/** 信息匹配模式 */
|
||||
private final Pattern pattern;
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param name 名字
|
||||
* @param regex 表达式
|
||||
*/
|
||||
public UserAgentInfo(String name, String regex) {
|
||||
this(name, (null == regex) ? null : Pattern.compile(regex, Pattern.CASE_INSENSITIVE));
|
||||
}
|
||||
|
||||
/**
|
||||
* 构造
|
||||
*
|
||||
* @param name 名字
|
||||
* @param pattern 匹配模式
|
||||
*/
|
||||
public UserAgentInfo(String name, Pattern pattern) {
|
||||
this.name = name;
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取信息名称
|
||||
*
|
||||
* @return 信息名称
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取匹配模式
|
||||
*
|
||||
* @return 匹配模式
|
||||
*/
|
||||
public Pattern getPattern() {
|
||||
return pattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* 指定内容中是否包含匹配此信息的内容
|
||||
*
|
||||
* @param content User-Agent字符串
|
||||
* @return 是否包含匹配此信息的内容
|
||||
*/
|
||||
public boolean isMatch(String content) {
|
||||
return ReUtil.contains(this.pattern, content);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为Unknown
|
||||
*
|
||||
* @return 是否为Unknown
|
||||
*/
|
||||
public boolean isUnknown() {
|
||||
return NameUnknown.equals(this.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final UserAgentInfo other = (UserAgentInfo) obj;
|
||||
if (name == null) {
|
||||
return other.name == null;
|
||||
} else return name.equals(other.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package com.tiesheng.util.useragent;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
|
||||
/**
|
||||
* User-Agent解析器
|
||||
*
|
||||
* @author looly
|
||||
* @since 4.2.1
|
||||
*/
|
||||
public class UserAgentParser {
|
||||
|
||||
/**
|
||||
* 解析User-Agent
|
||||
*
|
||||
* @param userAgentString User-Agent字符串
|
||||
* @return {@link UserAgent}
|
||||
*/
|
||||
public static UserAgent parse(String userAgentString) {
|
||||
if(StrUtil.isBlank(userAgentString)){
|
||||
return null;
|
||||
}
|
||||
final UserAgent userAgent = new UserAgent();
|
||||
|
||||
// 浏览器
|
||||
final Browser browser = parseBrowser(userAgentString);
|
||||
userAgent.setBrowser(browser);
|
||||
userAgent.setVersion(browser.getVersion(userAgentString));
|
||||
|
||||
// 浏览器引擎
|
||||
final Engine engine = parseEngine(userAgentString);
|
||||
userAgent.setEngine(engine);
|
||||
userAgent.setEngineVersion(engine.getVersion(userAgentString));
|
||||
|
||||
// 操作系统
|
||||
final OS os = parseOS(userAgentString);
|
||||
userAgent.setOs(os);
|
||||
userAgent.setOsVersion(os.getVersion(userAgentString));
|
||||
|
||||
// 平台
|
||||
final Platform platform = parsePlatform(userAgentString);
|
||||
userAgent.setPlatform(platform);
|
||||
userAgent.setMobile(platform.isMobile() || browser.isMobile());
|
||||
|
||||
|
||||
return userAgent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析浏览器类型
|
||||
*
|
||||
* @param userAgentString User-Agent字符串
|
||||
* @return 浏览器类型
|
||||
*/
|
||||
private static Browser parseBrowser(String userAgentString) {
|
||||
for (Browser browser : Browser.browers) {
|
||||
if (browser.isMatch(userAgentString)) {
|
||||
return browser;
|
||||
}
|
||||
}
|
||||
return Browser.Unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析引擎类型
|
||||
*
|
||||
* @param userAgentString User-Agent字符串
|
||||
* @return 引擎类型
|
||||
*/
|
||||
private static Engine parseEngine(String userAgentString) {
|
||||
for (Engine engine : Engine.engines) {
|
||||
if (engine.isMatch(userAgentString)) {
|
||||
return engine;
|
||||
}
|
||||
}
|
||||
return Engine.Unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析系统类型
|
||||
*
|
||||
* @param userAgentString User-Agent字符串
|
||||
* @return 系统类型
|
||||
*/
|
||||
private static OS parseOS(String userAgentString) {
|
||||
for (OS os : OS.oses) {
|
||||
if (os.isMatch(userAgentString)) {
|
||||
return os;
|
||||
}
|
||||
}
|
||||
return OS.Unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析平台类型
|
||||
*
|
||||
* @param userAgentString User-Agent字符串
|
||||
* @return 平台类型
|
||||
*/
|
||||
private static Platform parsePlatform(String userAgentString) {
|
||||
for (Platform platform : Platform.platforms) {
|
||||
if (platform.isMatch(userAgentString)) {
|
||||
return platform;
|
||||
}
|
||||
}
|
||||
return Platform.Unknown;
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.tiesheng.springboot-parent</groupId>
|
||||
<artifactId>springboot-parent</artifactId>
|
||||
<version>2.0.5</version>
|
||||
<version>2.0.17-test2</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>springboot-web</artifactId>
|
||||
|
||||
@@ -56,8 +56,12 @@ public class OperationAspect {
|
||||
@Around("methodArgs()")
|
||||
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
|
||||
// GET请求不处理
|
||||
HttpServletRequest request = ServletKit.getRequest();
|
||||
if (request == null) {
|
||||
return joinPoint.proceed();
|
||||
}
|
||||
|
||||
// GET请求不处理
|
||||
if (StrUtil.equalsIgnoreCase(request.getMethod(), "GET")) {
|
||||
return joinPoint.proceed(joinPoint.getArgs());
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ 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.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
@@ -24,6 +25,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
@Aspect
|
||||
@Component
|
||||
@ConditionalOnBean(value = TsAuthorityHandler.class)
|
||||
public class RoleAuthorityAspect {
|
||||
|
||||
@Resource
|
||||
|
||||
@@ -5,12 +5,13 @@ import cn.hutool.core.date.DateUtil;
|
||||
import com.tiesheng.annotation.role.RoleAuthority;
|
||||
import com.tiesheng.util.service.role.TsAuthorityHandler;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.context.event.ContextRefreshedEvent;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
@@ -18,19 +19,15 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
@ConditionalOnBean(value = TsAuthorityHandler.class)
|
||||
public class RoleAuthorityCreator implements ApplicationListener<ContextRefreshedEvent> {
|
||||
|
||||
@Autowired(required = false)
|
||||
@Resource
|
||||
TsAuthorityHandler tsAuthorityHandler;
|
||||
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||
|
||||
if (tsAuthorityHandler == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ApplicationContext applicationContext = event.getApplicationContext();
|
||||
Map<String, Object> beansOfType = applicationContext.getBeansWithAnnotation(RoleAuthority.class);
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ 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.exception.ApiException;
|
||||
import com.tiesheng.util.pojos.ApiResp;
|
||||
import com.tiesheng.util.pojos.PageDTO;
|
||||
import com.tiesheng.web.pojos.dao.CoreConfigSystem;
|
||||
@@ -57,21 +56,8 @@ public class ConfigSystemController {
|
||||
*/
|
||||
@PostMapping("/system/update")
|
||||
public ApiResp<String> systemUpdate(@RequestBody ConfigSystemDTO dto) {
|
||||
|
||||
CoreConfigSystem configKey = coreConfigService.getOneByColumn("config_key", dto.getConfigKey());
|
||||
if (configKey == null) {
|
||||
throw new ApiException("该配置不存在,请检查");
|
||||
}
|
||||
if (configKey.getReadOnly() == 1) {
|
||||
throw new ApiException("该配置只读,不可修改");
|
||||
}
|
||||
configKey.setConfigVal(dto.getConfigVal());
|
||||
configKey.setRemark(dto.getRemark());
|
||||
configKey.setExtra(dto.getExtra());
|
||||
|
||||
tieshengWebConfigurer.configSystemCheck(configKey);
|
||||
coreConfigService.updateById(configKey);
|
||||
|
||||
tieshengWebConfigurer.configSystemCheck(dto);
|
||||
coreConfigService.updateConfigSystem(dto);
|
||||
return ApiResp.respOK("");
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
package com.tiesheng.web.service;
|
||||
|
||||
import com.tiesheng.util.exception.ApiException;
|
||||
import com.tiesheng.util.service.TsCacheService;
|
||||
import com.tiesheng.util.service.TsServiceBase;
|
||||
import com.tiesheng.web.mapper.CoreConfigEnumMapper;
|
||||
import com.tiesheng.web.mapper.CoreConfigSystemMapper;
|
||||
import com.tiesheng.web.pojos.dao.CoreConfigSystem;
|
||||
import com.tiesheng.util.service.TsServiceBase;
|
||||
import com.tiesheng.web.pojos.dto.config.ConfigSystemDTO;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
/**
|
||||
* @author hao
|
||||
*/
|
||||
@@ -15,6 +20,11 @@ public class CoreConfigService extends TsServiceBase<CoreConfigSystemMapper, Cor
|
||||
|
||||
@Autowired
|
||||
CoreConfigEnumMapper coreConfigEnumMapper;
|
||||
@Resource
|
||||
TsCacheService tsCacheService;
|
||||
|
||||
|
||||
private static final String CONFIG_SYSTEM_PREFIX = "CONFIG:SYSTEM:";
|
||||
|
||||
public CoreConfigEnumMapper getEnumMapper() {
|
||||
return coreConfigEnumMapper;
|
||||
@@ -28,7 +38,14 @@ public class CoreConfigService extends TsServiceBase<CoreConfigSystemMapper, Cor
|
||||
* @return
|
||||
*/
|
||||
public CoreConfigSystem getTextOrCreate(String configKey, String defaultValue) {
|
||||
CoreConfigSystem oneByColumn = getOneByColumn("config_key", configKey);
|
||||
CoreConfigSystem oneByColumn = tsCacheService.getObj(CONFIG_SYSTEM_PREFIX + configKey,
|
||||
CoreConfigSystem.class, -1);
|
||||
|
||||
if (oneByColumn != null) {
|
||||
return oneByColumn;
|
||||
}
|
||||
|
||||
oneByColumn = getOneByColumn("config_key", configKey);
|
||||
if (oneByColumn == null) {
|
||||
oneByColumn = new CoreConfigSystem();
|
||||
oneByColumn.setId(configKey);
|
||||
@@ -38,7 +55,33 @@ public class CoreConfigService extends TsServiceBase<CoreConfigSystemMapper, Cor
|
||||
oneByColumn.setConfigType(0);
|
||||
save(oneByColumn);
|
||||
}
|
||||
|
||||
tsCacheService.putObj(CONFIG_SYSTEM_PREFIX + configKey, oneByColumn, 10 * 60);
|
||||
|
||||
return oneByColumn;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 更新数据
|
||||
*
|
||||
* @param dto
|
||||
*/
|
||||
public void updateConfigSystem(ConfigSystemDTO dto) {
|
||||
CoreConfigSystem configKey = getOneByColumn("config_key", dto.getConfigKey());
|
||||
if (configKey == null) {
|
||||
throw new ApiException("该配置不存在,请检查");
|
||||
}
|
||||
if (configKey.getReadOnly() == 1) {
|
||||
throw new ApiException("该配置只读,不可修改");
|
||||
}
|
||||
configKey.setConfigVal(dto.getConfigVal());
|
||||
configKey.setRemark(dto.getRemark());
|
||||
configKey.setExtra(dto.getExtra());
|
||||
updateById(configKey);
|
||||
|
||||
tsCacheService.putObj(CONFIG_SYSTEM_PREFIX + configKey, configKey, 10 * 60);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ package com.tiesheng.web.service;
|
||||
|
||||
import cn.hutool.core.thread.ThreadUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.tiesheng.util.service.http.OkHttpUtil;
|
||||
import com.tiesheng.web.mapper.CoreLogApiMapper;
|
||||
import com.tiesheng.web.pojos.dao.CoreLogApi;
|
||||
import okhttp3.*;
|
||||
@@ -30,33 +30,27 @@ public class OkHttpLogInterceptor implements Interceptor {
|
||||
logApi.setUrl(request.url().toString());
|
||||
logApi.setContent(requestBody2String(request));
|
||||
|
||||
Response response;
|
||||
Response response = null;
|
||||
try {
|
||||
response = chain.proceed(request);
|
||||
logApi.setResult(response.code());
|
||||
|
||||
// 如果是json,xml,text,则保存记录
|
||||
if (response.body() != null && StrUtil.containsAll(response.body().contentType().toString(),
|
||||
"json", "xml", "text")) {
|
||||
ResponseBody peekBody = response.peekBody(Long.MAX_VALUE);
|
||||
logApi.setRespBody(peekBody.string());
|
||||
peekBody.close();
|
||||
if (response.body() != null) {
|
||||
MediaType mediaType = response.body().contentType();
|
||||
String contentType = mediaType == null ? "" : mediaType.toString();
|
||||
if (StrUtil.containsAny(contentType, "json", "xml", "text")) {
|
||||
ResponseBody peekBody = response.peekBody(Long.MAX_VALUE);
|
||||
logApi.setRespBody(peekBody.string());
|
||||
peekBody.close();
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
JSONObject object = new JSONObject();
|
||||
object.put("code", -1);
|
||||
object.put("message", e.getMessage());
|
||||
object.put("message", JSON.toJSONString(e));
|
||||
object.put("exception", e);
|
||||
logApi.setRespBody(object.toJSONString());
|
||||
|
||||
response = new Response.Builder()
|
||||
.request(request)
|
||||
.protocol(Protocol.HTTP_1_1)
|
||||
.code(logApi.getResult())
|
||||
.message(e.getMessage())
|
||||
.body(OkHttpUtil.ofJsonResponse(logApi.getRespBody()))
|
||||
.build();
|
||||
}
|
||||
|
||||
ThreadUtil.execute(() -> coreLogApiMapper.insert(logApi));
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.tiesheng.login.service.TsLoginConfigurer;
|
||||
import com.tiesheng.util.exception.ApiRespEnum;
|
||||
import com.tiesheng.util.pojos.ApiResp;
|
||||
import com.tiesheng.web.pojos.dao.CoreConfigSystem;
|
||||
import com.tiesheng.web.pojos.dto.config.ConfigSystemDTO;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
/**
|
||||
@@ -58,7 +59,7 @@ public interface TieshengWebConfigurer {
|
||||
* 系统配置验证
|
||||
* 如果不符合规则,可以抛出异常
|
||||
*/
|
||||
default void configSystemCheck(CoreConfigSystem configSystem) {
|
||||
default void configSystemCheck(ConfigSystemDTO dto) {
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -13,7 +13,8 @@ CREATE TABLE `core_config_enum`
|
||||
`ext` varchar(255) DEFAULT NULL COMMENT '扩展字段',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4 COMMENT ='配置-枚举';
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci COMMENT ='配置-枚举';
|
||||
|
||||
|
||||
CREATE TABLE `core_config_system`
|
||||
@@ -31,7 +32,8 @@ CREATE TABLE `core_config_system`
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uni_key` (`config_key`(50)) USING BTREE
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4 COMMENT ='配置-系统';
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci COMMENT ='配置-系统';
|
||||
|
||||
alter table core_config_enum
|
||||
add sort int(10) not null default 0 comment '排序' after name;
|
||||
|
||||
@@ -18,6 +18,7 @@ CREATE TABLE `core_log_api`
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci
|
||||
ROW_FORMAT = DYNAMIC COMMENT ='日志-调用';
|
||||
|
||||
-- ----------------------------
|
||||
@@ -69,7 +70,8 @@ CREATE TABLE `core_log_operation`
|
||||
`params` longtext COMMENT '其他参数',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE = InnoDB
|
||||
DEFAULT CHARSET = utf8mb4 COMMENT ='日志-操作';
|
||||
DEFAULT CHARSET = utf8mb4
|
||||
COLLATE = utf8mb4_general_ci COMMENT ='日志-操作';
|
||||
|
||||
|
||||
alter table core_log_process
|
||||
|
||||
Reference in New Issue
Block a user