未验证 提交 f4dc2739 编写于 作者: zlt2000's avatar zlt2000 提交者: Gitee

!32 合并dev

Merge pull request !32 from zlt2000/dev
......@@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.zlt</groupId>
<artifactId>central-platform</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
<packaging>pom</packaging>
<properties>
......@@ -62,6 +62,7 @@
<docker.image.prefix>hub.zlt.com:8080/microservices-platform</docker.image.prefix>
<docker.java.security.egd>-Djava.security.egd=file:/dev/./urandom</docker.java.security.egd>
<docker.java.opts>-Xms128m -Xmx128m</docker.java.opts>
<guava.version>20.0</guava.version>
</properties>
<dependencies>
......@@ -430,6 +431,11 @@
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
......@@ -483,7 +489,7 @@
<!-- 业务 -->
<module>zlt-business</module>
<!-- 前端 -->
<!--<module>zlt-web</module>-->
<module>zlt-web</module>
<!-- 任务 -->
<module>zlt-job</module>
<!-- 监控 -->
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-business</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>code-generator</artifactId>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-business</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>file-center</artifactId>
<description>文件中心</description>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>central-platform</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>zlt-business</artifactId>
<description>业务中心</description>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-business</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>search-center</artifactId>
<description>搜索中心</description>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>search-center</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>search-client</artifactId>
<description>搜索中心客户端</description>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>search-center</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>search-server</artifactId>
<description>搜索中心服务端</description>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-business</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>user-center</artifactId>
<description>用户中心</description>
......
......@@ -8,6 +8,7 @@ import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.central.common.annotation.LoginUser;
import com.central.common.constant.CommonConstant;
import com.central.common.context.LoginUserContextHolder;
import com.central.common.model.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
......@@ -147,6 +148,9 @@ public class SysMenuController {
@PostMapping("saveOrUpdate")
public Result saveOrUpdate(@RequestBody SysMenu menu) {
try {
if (menu.getId() == null) {
menu.setCreatorId(LoginUserContextHolder.getUser().getId());
}
menuService.saveOrUpdate(menu);
return Result.succeed("操作成功");
} catch (Exception ex) {
......
......@@ -7,6 +7,7 @@ import java.util.Map;
import java.util.Set;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.central.common.annotation.LoginUser;
import com.central.common.constant.CommonConstant;
import com.central.common.model.*;
......@@ -286,6 +287,23 @@ public class SysUserController {
return queryService.strQuery("sys_user", searchDto, SEARCH_LOGIC_DEL_DTO);
}
/**
* 获取用户并返回角色列表
* @param username
* @return
*/
@GetMapping(value = "/users/roleUser/{username}")
@ApiOperation(value = "查询用户-带角色信息")
@Cacheable(value = "userRoles", key = "#username")
public SysUser selectRoleUser(@PathVariable("username") String username){
SysUser sysUser = selectByUsername(username);
if(ObjectUtil.isNotNull(sysUser)){
List<SysRole> roleList = findRolesByUserId(sysUser.getId());
sysUser.setRoles(roleList);
}
return sysUser;
}
/**
* 是否超级管理员
*/
......
......@@ -6,6 +6,7 @@ import java.util.Map;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.central.common.constant.CommonConstant;
import com.central.common.context.LoginUserContextHolder;
import com.central.common.lock.DistributedLock;
import com.central.common.model.*;
import com.central.common.service.impl.SuperServiceImpl;
......@@ -69,6 +70,7 @@ public class SysRoleServiceImpl extends SuperServiceImpl<SysRoleMapper, SysRole>
@Transactional
public Result saveOrUpdateRole(SysRole sysRole) throws Exception {
if (sysRole.getId() == null) {
sysRole.setCreatorId(LoginUserContextHolder.getUser().getId());
this.saveRole(sysRole);
} else {
baseMapper.updateById(sysRole);
......
......@@ -7,6 +7,7 @@ import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.central.common.constant.CommonConstant;
import com.central.common.context.LoginUserContextHolder;
import com.central.common.lock.DistributedLock;
import com.central.common.model.*;
import com.central.common.service.impl.SuperServiceImpl;
......@@ -226,6 +227,7 @@ public class SysUserServiceImpl extends SuperServiceImpl<SysUserMapper, SysUser>
}
sysUser.setPassword(passwordEncoder.encode(CommonConstant.DEF_USER_PASSWORD));
sysUser.setEnabled(Boolean.TRUE);
sysUser.setCreatorId(LoginUserContextHolder.getUser().getId());
}
String username = sysUser.getUsername();
boolean result = super.saveOrUpdateIdempotency(sysUser, lock
......
......@@ -38,6 +38,19 @@ zlt:
- com.central.user.mapper.SysRoleMapper.findAll
# 用户列表显示用户所关联的所有角色
- com.central.user.mapper.SysUserRoleMapper.findRolesByUserIds
# 数据权限
datascope:
enabled: false
ignoreTables:
- sys_role_user
- sys_role_menu
includeSqls:
# 用户列表
- com.central.user.mapper.SysUserMapper.findList
# 角色列表
- com.central.user.mapper.SysRoleMapper.findList
# 菜单列表
- com.central.user.mapper.SysMenuMapper.selectList
#审计日志
# audit-log:
# enabled: true
......
......@@ -8,7 +8,8 @@
name,
create_time,
update_time,
tenant_id
tenant_id,
data_scope
</sql>
<sql id="where">
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>central-platform</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>zlt-commons</artifactId>
<description>通用组件</description>
......
......@@ -5,7 +5,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-commons</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
......
......@@ -7,6 +7,11 @@ import lombok.Setter;
* 认证配置
*
* @author zlt
* @version 1.0
* @date 2019/1/19
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
@Setter
@Getter
......@@ -47,4 +52,10 @@ public class AuthProperties {
* false: 就算使用同一账号登录时都会新建一个token
*/
private Boolean isShareToken = true;
/**
* 参数加密(rsa),对应的私钥(用于解密)
* 默认私钥对应的公钥为:MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6u4sP969hZP7BUEeAXJlq5wEmZ2CIZU4+5JADY8Ium55qGaE5qXEwMaV+M2HFWU4PZbHfH+RGEIMwjkARRok93krFnJuuwTjLwgyUSsKm5M7v3Ek8zdqs474v1qOxqE6BmHz9QJfgnAtFYxwEyVRoQ12+IAhpOzDU3rz02VR05kGCrgGU6szxDtp6cQ+u9ACGPy/uKdIQ6H7aM/oxMyPlwK9H38ni6Lxai7q56qp6F1p7drxh8CWJZ3j0NicB5ZPnOMtrGL5lfnifHBjB+CDJXv8kffY0zwL3J+LrnyFbpKeNeMJZpykoYW85Pdz+8WnE9KGMM3EeOeD/QX/OfMdFQIDAQAB
*/
private String decryptParamPrivateKey = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDq7iw/3r2Fk/sFQR4BcmWrnASZnYIhlTj7kkANjwi6bnmoZoTmpcTAxpX4zYcVZTg9lsd8f5EYQgzCOQBFGiT3eSsWcm67BOMvCDJRKwqbkzu/cSTzN2qzjvi/Wo7GoToGYfP1Al+CcC0VjHATJVGhDXb4gCGk7MNTevPTZVHTmQYKuAZTqzPEO2npxD670AIY/L+4p0hDoftoz+jEzI+XAr0ffyeLovFqLurnqqnoXWnt2vGHwJYlnePQ2JwHlk+c4y2sYvmV+eJ8cGMH4IMle/yR99jTPAvcn4uufIVukp414wlmnKShhbzk93P7xacT0oYwzcR454P9Bf858x0VAgMBAAECggEBAJxK94VGWi+T01wbhirQQHN6yFSqRPiyncY/9f0PO29MMAOosKIBhnP5qaxsj4HcZR4UQYLCG3VX+8T6xwMx8YXyRogYeTJSfhG8Ej2NtPDrcsRaMYrdQ09RvosPZA0hFclJQVOu0HumxVegpq8WFMhgfNW16KwgF5JiKfRpY5aw4NDWZFmdNExdymrWPheI8pWBq/U+l8oqrekhbiEKXM2UXmLlKTS9Nk46LRYwaaiDW8JEFuPdx0cnakb+ecCXGd/8Cc8Hxn/mLyvqS1cWHT3J+lXRkfcnNnrJTR9qhf9l077XBMJqVckFEpK4kKbXHZd957ISAxq48Tm+xMX9KAECgYEA995szPToU0BxTTtOD4Z4c5JvbURQEcDQl/dB+qCQnu/orW5ZWv4++lHq2SZPjzbt7M8OaoRN8A5zYcNrYe4kBhLOLqHdaS1yUGIIjAejEAJplR5GqI3T5qzaLjpyiUZpO0mOcwAazCevnSXH6uO5jP0sjwxwaXz4OsTcpHIXHqECgYEA8qMXhh+G88+vTELL/2dHhtTIf7IAJLQ37c1Xrm6uwOHPfiDr256Lc4EzF8QAQqlHoYm1jRK7xDfFymY/SJKJVhYehWlNilnMuDuDOqseC/Zn2KgjMSjLLVkbp25DcpAu6SSiWlBvemrV3jivX/MU0BFp8HjbrlUcl12lRtYgrfUCgYB+iN2iA6RWW597fbrr0gnLdgXMEgOODJBwA5l7CFzLxk1Ru/OBsCkWQJtTH2ueALyVF16UodXnpnjgf5Jh++AH+bGnvJn7B2hEAMe8NGnZ0mFz7nDDuyNhrvvyfYPa8EboLTS7IGKNtfTAlHjqQDaI8vW8UO1R7KoL1lOM33FOAQKBgQDt/Z6jReU+3CUbbiFeANWdoLSQ2+1cExEQxWsNgy8Rreux0WTG4/nwb3fIBc4jlJrYDZTwLMHTssjkv+muq1zd/ZAuV51g6LfutSEAuLseDLDLSBBMtbCkaFTBo1uw0U/SCsbcQy01K/leoMcUG//8HjiFUGZZ1s3WgloM4xbmyQKBgAipgnoEyzvUfe2OMOc5ARGNSGZG4JGTGCyfnrYvYfffWpAokklHOkZMumeSWJXkx5F+MgJd9fxBK9S57PZ09gWkoeSVg0xcz5QMjh8BswfCdyet/CXQtwIfK0Wf1gWdAxC6vvv3DQ7zXbTlvqMdVOFzCKlocCYkzWMvIsejWXnW";
}
......@@ -10,6 +10,11 @@ import java.util.List;
* 配置需要放权的url白名单
*
* @author zlt
* @version 1.0
* @date 2019/1/19
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
@Setter
@Getter
......
......@@ -10,7 +10,11 @@ import java.util.List;
* 续签配置
*
* @author zlt
* @version 1.0
* @date 2019/7/9
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
@Setter
@Getter
......
......@@ -7,7 +7,11 @@ import org.springframework.cloud.context.config.annotation.RefreshScope;
/**
* @author zlt
* @version 1.0
* @date 2019/1/4
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
@Setter
@Getter
......
......@@ -10,7 +10,11 @@ import java.util.List;
* url权限配置
*
* @author zlt
* @version 1.0
* @date 2019/8/2
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
@Setter
@Getter
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-commons</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>zlt-common-core</artifactId>
<description>公共通用组件</description>
......@@ -89,5 +89,9 @@
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
</dependencies>
</project>
\ No newline at end of file
......@@ -10,7 +10,7 @@ public interface CommonConstant {
/**
* 项目版本号(banner使用)
*/
String PROJECT_VERSION = "5.5.0";
String PROJECT_VERSION = "5.6.0";
/**
* token请求头名称
......
package com.central.common.datascope.mp.interceptor;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import com.central.common.datascope.mp.sql.handler.SqlHandler;
import com.central.common.properties.DataScopeProperties;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Alias;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.ExpressionVisitorAdapter;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.parser.CCJSqlParserManager;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.select.*;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.http.server.PathContainer;
import org.springframework.web.util.pattern.PathPatternParser;
import java.io.StringReader;
import java.sql.SQLException;
import java.util.*;
import static com.central.common.datascope.mp.sql.handler.SqlHandler.ALIAS_SYNBOL;
/**
* 数据权限拦截器
*
* @author jarvis create by 2023/1/7
*/
@Slf4j
@Data
@NoArgsConstructor
public class DataScopeInnerInterceptor implements InnerInterceptor {
private DataScopeProperties dataScopeProperties;
/**
* 权限的where条件
*/
private SqlHandler sqlHandler;
/**
* 对表配置进行缓存,优先读取缓存,在进行匹配
*/
private Map<String, TableConfig> tableInfoMap = new HashMap<>();
/**
* 通配符
*/
private PathPatternParser pathPatternParser = new PathPatternParser();
public DataScopeInnerInterceptor(DataScopeProperties dataScopeProperties, SqlHandler sqlHandler) {
this.dataScopeProperties = dataScopeProperties;
this.sqlHandler = sqlHandler;
}
@Override
public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
//为空时:所有sql都添加权限控制
if (CollUtil.isEmpty(dataScopeProperties.getIncludeSqls())
//有值时:只有配置的sql添加权限控制
|| dataScopeProperties.getIncludeSqls().contains(ms.getId())) {
//判断排除的sql
if(CollUtil.isEmpty(dataScopeProperties.getIgnoreSqls())
|| !dataScopeProperties.getIgnoreSqls().contains(ms.getId())){
PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
String sql = boundSql.getSql();
try {
Select select = explainQuerySql(sql);
reform(select.getSelectBody());
mpBs.sql(select.toString());
} catch (JSQLParserException e) {
throw new RuntimeException(e);
}
}
}
}
public Select explainQuerySql(String sql) throws JSQLParserException {
CCJSqlParserManager parserManager = new CCJSqlParserManager();
Select select = (Select) parserManager.parse(new StringReader(sql));
return select;
}
/**
* 递归对查询和解析后的子查询进行改造
* @param selectBody
* @param <T>
* @throws JSQLParserException
*/
public <T extends SelectBody>void reform(SelectBody selectBody) throws JSQLParserException {
// 如果是plainSelect的话进行改造
if(selectBody instanceof PlainSelect&& ObjectUtil.isNotNull(sqlHandler)){
PlainSelect select = (PlainSelect) selectBody;
// 获取权限的where条件
String scopeWhereSql = sqlHandler.handleScopeSql();
// 如果条件不是空的话才对select进行改造
if(StrUtil.isNotBlank(scopeWhereSql)){
// 需要改造的别名列表,自动增加到where条件中
List<String> tableAliasList = new ArrayList<>();
FromItem fromItem = select.getFromItem();
String tableAlias = explainFromItem(fromItem);
// 获取from的表字段,如果from是子查询则进行递归
if(fromItem instanceof Table){
String upperTableName = ((Table) fromItem).getName().toUpperCase();
if(tableInfoMap.containsKey(upperTableName)){
if (!tableInfoMap.get(upperTableName).getIgnore()) {
tableAliasList.add(StrUtil.isNotBlank(tableAlias)? tableAlias: "");
}
}else{
boolean ignore = true;
if(isReformTable(upperTableName)){
tableAliasList.add(StrUtil.isNotBlank(tableAlias)? tableAlias: "");
ignore = false;
}
// 写入缓存
tableInfoMap.put(upperTableName, new TableConfig(upperTableName, ignore));
}
}else if(fromItem instanceof SubSelect){
reform(((SubSelect) fromItem).getSelectBody());
}
// 获取join列表,然后获取对应的表或者递归子查询
List<Join> joinList = select.getJoins();
if (CollUtil.isNotEmpty(joinList)) {
for (Join join : joinList) {
if(join.getRightItem() instanceof Table){
String joinTable = ((Table) join.getRightItem()).getName().toUpperCase();
String joinAlias = ((Table) join.getRightItem()).getAlias().getName();
if(tableInfoMap.containsKey(joinTable)){
if (!tableInfoMap.get(joinTable).getIgnore()) {
tableAliasList.add(StrUtil.isNotBlank(joinAlias)? joinAlias: "");
}
}else{
boolean ignore = true;
if(isReformTable(joinTable)){
tableAliasList.add(StrUtil.isNotBlank(joinAlias)? joinAlias: "");
ignore = false;
}
// 写入缓存
tableInfoMap.put(joinTable, new TableConfig(joinTable, ignore));
}
}
if(join.getRightItem() instanceof SubSelect){
reform(((SubSelect) join.getRightItem()).getSelectBody());
}
}
}
// 如果改造的表是空的话则不改造对应的select
if(CollUtil.isNotEmpty(tableAliasList)){
reformWhere(select, scopeWhereSql, tableAliasList);
}
}
// 如果select不是plainSelect的话则进行递归改造
}else if(selectBody instanceof WithItem&& Objects.nonNull(((WithItem)selectBody).getSubSelect())){
reform(((WithItem)selectBody).getSubSelect().getSelectBody());
}
}
/**
* 判断表是否需要改造
* @param table
* @return
* 1. 判断表是否在需要改造的范围
* 1.1 如果表在inclde的set中(是否存在没用通配符的情况写入配置)
* 1.2 进行通配符匹配判断范围
* 2. 在改造的范围中进行提出
* 2.1 判断是不是完全匹配上ignore列表中
* 2.2 判断是否在通配符过滤
*/
private boolean isReformTable(String table){
return
// 1. 判断表是否在需要改造的范围
(dataScopeProperties.getIncludeTables().contains(table)
||dataScopeProperties.getIncludeTables().stream().anyMatch(item->
pathPatternParser.parse(item.toUpperCase()).matches(PathContainer.parsePath(table))
))&& (
// 如果没有忽略列表的话在范围中直接返回
CollUtil.isEmpty(dataScopeProperties.getIgnoreTables())
// 在改造的范围中进行忽略表
||!(dataScopeProperties.getIgnoreTables().contains(table)||
dataScopeProperties.getIgnoreTables().stream().anyMatch(item->
pathPatternParser.parse(item.toUpperCase()).matches(PathContainer.parsePath(table))
)));
}
/**
* 解析from中的东西
* @param fromItem
* @return
* @throws JSQLParserException
*/
private String explainFromItem(FromItem fromItem) throws JSQLParserException {
// 别名
String alias = "";
if(Objects.nonNull(fromItem)){
// 如果from的东西是表的话
if (fromItem instanceof Table) {
Alias tablealias = ((Table) fromItem).getAlias();
if(Objects.nonNull(tablealias)&& StrUtil.isNotBlank(tablealias.getName())){
alias = tablealias.getName();
}else{
alias = ((Table) fromItem).getName();
}
}
// 如果from的子查询
if(fromItem instanceof SubSelect){
SelectBody subSelectBody = ((SubSelect) fromItem).getSelectBody();
reform(subSelectBody);
}
}
return alias;
}
/**
* 改造where条件
* @param select
* @param whereSql where 条件
* @param aliasName 需要添加权限的表别名
* @return
* @throws JSQLParserException
*/
private SelectBody reformWhere(PlainSelect select, String whereSql, List<String> aliasName) throws JSQLParserException {
// todo 处理exists
if(StrUtil.isNotBlank(whereSql)&& CollUtil.isNotEmpty(aliasName)){
for (String alias : aliasName) {
Expression expression = CCJSqlParserUtil
.parseCondExpression(whereSql);
expression.accept(new ExpressionVisitorAdapter(){
@Override
public void visit(Column column) {
if(Objects.isNull(column.getTable())|| ALIAS_SYNBOL.equals(column.getTable().toString())){
Table table = new Table();
table.setAlias(new Alias(alias));
column.setTable(table);
}
}
});
if(ObjectUtil.isNull(select.getWhere())){
select.setWhere(expression);
}else {
AndExpression andExpression = new AndExpression(select.getWhere(), expression);
select.setWhere(andExpression);
}
}
}
return select;
}
public class TableConfig{
private String tableName;
private Boolean isIgnore;
public TableConfig(String tableName, Boolean isIgnore) {
this.tableName = tableName;
this.isIgnore = isIgnore;
}
public String getTableName() {
return tableName;
}
public Boolean getIgnore() {
return isIgnore;
}
}
}
package com.central.common.datascope.mp.interceptor;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import java.sql.SQLException;
/**
* 示例
*
* @author jarvis create by 2023/2/2
*/
@Slf4j
public class EnableQuerySqlLogInnerInterceptor implements InnerInterceptor{
private InnerInterceptor delegate;
public EnableQuerySqlLogInnerInterceptor(InnerInterceptor delegate) {
Assert.notNull(delegate, "委派类不能为空");
this.delegate = delegate;
}
@Override
public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
PluginUtils.MPBoundSql mpBs = PluginUtils.mpBoundSql(boundSql);
String sql = boundSql.getSql();
log.info("执行mapperId{},原始sql为{}", ms.getId(), sql);
delegate.beforeQuery(executor, ms, parameter, rowBounds, resultHandler, boundSql);
log.info("执行mapperId{}, 修改sql为{}", ms.getId(), mpBs.sql());
}
}
package com.central.common.datascope.mp.sql.handler;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.central.common.context.LoginUserContextHolder;
import com.central.common.enums.DataScope;
import com.central.common.feign.UserService;
import com.central.common.model.SysRole;
import com.central.common.model.SysUser;
import com.central.common.properties.DataScopeProperties;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
import java.util.Objects;
/**
* 个人权限的处理器
*
* @author jarvis create by 2023/1/10
*/
public class CreatorDataScopeSqlHandler implements SqlHandler{
@Autowired
UserService userService;
@Autowired
private DataScopeProperties dataScopeProperties;
/**
* 返回需要增加的where条件,返回空字符的话则代表不需要权限控制
*
* @return where条件
* 如果角色是全部权限的话则不进行控制,如果是个人权限的话则自动加入create_id = user_id
*/
@Override
public String handleScopeSql() {
SysUser user = LoginUserContextHolder.getUser();
Assert.notNull(user, "登陆人不能为空");
List<SysRole> roleList = userService.findRolesByUserId(user.getId());
return StrUtil.isBlank(dataScopeProperties.getCreatorIdColumnName())
||CollUtil.isEmpty(roleList)
|| roleList.stream().anyMatch(item-> Objects.isNull(item.getDataScope()) || DataScope.ALL.equals(item.getDataScope()))
? DO_NOTHING:
// 这里确保有配置权限范围控制的字段
// 1. 如果没有配置角色的情况默认采用只读全部的记录
// 2. 如果有配置角色的话判断是否存在有ALL获取null的情况,如果没有ALL的话读取个人创建记录
String.format("%s = '%s'", dataScopeProperties.getCreatorIdColumnName(), user.getId());
}
}
package com.central.common.datascope.mp.sql.handler;
/**
* 示例
*
* @author jarvis create by 2023/1/8
*/
public class DefaultSqlHandler implements SqlHandler{
@Override
public String handleScopeSql() {
return DO_NOTHING;
}
}
package com.central.common.datascope.mp.sql.handler;
/**
* 数据权限的sql获取接口
*
* @author jarvis create by 2023/1/8
*/
public interface SqlHandler {
/**
* 通过这个字符替换成别名,自动的
*/
String ALIAS_SYNBOL = "alias_";
/**
* 空字符串
*/
String DO_NOTHING = "";
/**
* 返回需要增加的where条件,返回空字符的话则代表不需要权限控制
* @return where条件
*/
String handleScopeSql();
}
package com.central.common.enums;
import lombok.Getter;
/**
* 枚举类型
*
* @author jarvis create by 2023/1/10
*/
@Getter
public enum DataScope implements ZltEnum{
ALL(0, "全部权限"), CREATOR(1, "创建者权限");
DataScope(Integer id, String content) {
this.id = id;
this.content = content;
}
private Integer id;
private String content;
}
package com.central.common.enums;
/**
* 接口
*
* @author jarvis create by 2023/1/20
*/
public interface ZltEnum {
/**
* 获取id
* @return
*/
Integer getId();
/**
* 获取内容
* @return
*/
String getContent();
}
......@@ -3,12 +3,15 @@ package com.central.common.feign;
import com.central.common.constant.ServiceNameConstants;
import com.central.common.feign.fallback.UserServiceFallbackFactory;
import com.central.common.model.LoginAppUser;
import com.central.common.model.SysRole;
import com.central.common.model.SysUser;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
/**
* @author zlt
*/
......@@ -48,4 +51,22 @@ public interface UserService {
*/
@GetMapping(value = "/users-anon/openId", params = "openId")
LoginAppUser findByOpenId(@RequestParam("openId") String openId);
/**
* 获取带角色的用户信息
* @param username
* @return
*/
@GetMapping(value = "/users/roleUser/{username}")
public SysUser selectRoleUser(@PathVariable("username") String username);
/**
* 获取用户的角色
*
* @param
* @return
*/
@GetMapping("/users/{id}/roles")
public List<SysRole> findRolesByUserId(@PathVariable("id") Long id);
}
......@@ -2,10 +2,14 @@ package com.central.common.feign.fallback;
import com.central.common.feign.UserService;
import com.central.common.model.LoginAppUser;
import com.central.common.model.SysRole;
import com.central.common.model.SysUser;
import org.springframework.cloud.openfeign.FallbackFactory;
import lombok.extern.slf4j.Slf4j;
import java.util.Collections;
import java.util.List;
/**
* userService降级工场
*
......@@ -40,6 +44,29 @@ public class UserServiceFallbackFactory implements FallbackFactory<UserService>
log.error("通过openId查询用户异常:{}", openId, throwable);
return new LoginAppUser();
}
/**
* 获取带角色的用户信息
*
* @param username
* @return
*/
@Override
public SysUser selectRoleUser(String username) {
log.error("通过用户名查询用户异常:{}", username, throwable);
return new SysUser();
}
/**
* 获取用户的角色
*
* @param id@return
*/
@Override
public List<SysRole> findRolesByUserId(Long id) {
log.error("通过用户id查询角色列表异常:{}", id, throwable);
return Collections.emptyList();
}
};
}
}
......@@ -29,6 +29,7 @@ public class SysMenu extends SuperEntity {
* 请求的类型
*/
private String pathMethod;
private Long creatorId;
@TableField(exist = false)
private List<SysMenu> subMenus;
......
......@@ -2,6 +2,7 @@ package com.central.common.model;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.central.common.enums.DataScope;
import lombok.Data;
import lombok.EqualsAndHashCode;
......@@ -18,4 +19,9 @@ public class SysRole extends SuperEntity {
private String name;
@TableField(exist = false)
private Long userId;
/**
* 数据权限字段
*/
private DataScope dataScope;
private Long creatorId;
}
......@@ -27,6 +27,7 @@ public class SysUser extends SuperEntity {
private Boolean enabled;
private String type;
private String openId;
private Long creatorId;
@TableLogic
private boolean isDel;
......
package com.central.common.passwordEncoder;
import cn.hutool.crypto.SmUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
* SM3
*
* @author zlt
* @version 1.0
* @date 2022/12/29
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
@Slf4j
public class SM3PasswordEncoder implements PasswordEncoder {
@Override
public String encode(CharSequence rawPassword) {
return SmUtil.sm3(rawPassword.toString());
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
if (rawPassword == null) {
throw new IllegalArgumentException("rawPassword cannot be null");
}
if (encodedPassword == null || encodedPassword.length() == 0) {
log.warn("Empty encoded password");
return false;
}
String rawPasswordEncoded = this.encode(rawPassword.toString());
return rawPasswordEncoded.equals(encodedPassword);
}
}
package com.central.common.properties;
import cn.hutool.core.collection.CollUtil;
import com.google.common.collect.ImmutableSet;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/**
* 示例
*
* @author jarvis create by 2023/1/8
*/
@ConfigurationProperties(prefix = "zlt.datascope")
@Data
public class DataScopeProperties {
private static final Set<String> INGORE_SQL_ID = ImmutableSet
.of("com.central.user.mapper.findRolesByUserId"
, "com.central.user.mapper.SysUserMapper.selectList"
, "com.central.user.mapper.SysUserRoleMapper.findRolesByUserId"
, "com.central.user.mapper.SysRoleMenuMapper.findMenusByRoleIds");
/**
* 是否开启权限控制
*/
private Boolean enabled = Boolean.FALSE;
/**
* 是否开启打印sql的修改情况
*/
private Boolean enabledSqlDebug = Boolean.FALSE;
/**
* 配置那些表不执行权限控制
*/
private Set<String> ignoreTables = Collections.emptySet();
/**
* 指定那些sql不执行权限控制
*/
private Set<String> ignoreSqls = INGORE_SQL_ID;
/**
* 配置那些表执行数据权限控制,默认是*则表示全部
*/
private Set<String> includeTables = Collections.singleton("*");
/**
* 指定那些sql执行数据权限控制
* 1. 为空时:所有sql都添加权限控制
* 2. 有值时:只有配置的sql添加权限控制
*/
private Set<String> includeSqls = Collections.emptySet();
/**
* 指定创建人id的字段名
*/
private String creatorIdColumnName = "creator_id";
public void setIgnoreSqls(Set<String> ignoreSqls) {
Set<String> ingoreSet = new HashSet<>();
ingoreSet.addAll(INGORE_SQL_ID);
if(CollUtil.isNotEmpty(ignoreSqls)){
ingoreSet.addAll(ignoreSqls);
}
this.ignoreSqls = ingoreSet;
}
}
......@@ -8,6 +8,8 @@ import com.central.common.model.SysUser;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
......@@ -66,4 +68,14 @@ public class LoginUserUtils {
}
return user;
}
public static SysUser getCurrentUser(boolean isFull) {
// 从请求上下文里获取 Request 对象
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest contextRequest = requestAttributes.getRequest();
if (contextRequest != null) {
return LoginUserUtils.getCurrentUser(contextRequest, isFull);
}
return null;
}
}
package com.central.common.utils;
import com.central.common.passwordEncoder.SM3PasswordEncoder;
import org.springframework.security.crypto.argon2.Argon2PasswordEncoder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.DelegatingPasswordEncoder;
......@@ -35,6 +36,7 @@ public class PwdEncoderUtil {
encoders.put("SHA-256", new org.springframework.security.crypto.password.MessageDigestPasswordEncoder("SHA-256"));
encoders.put("sha256", new org.springframework.security.crypto.password.StandardPasswordEncoder());
encoders.put("argon2", new Argon2PasswordEncoder());
encoders.put("SM3", new SM3PasswordEncoder());
Assert.isTrue(encoders.containsKey(encodingId), encodingId + " is not found in idToPasswordEncoder");
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-commons</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>zlt-common-spring-boot-starter</artifactId>
<description>公共通用组件</description>
......
......@@ -5,7 +5,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-commons</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
......
......@@ -5,6 +5,11 @@ import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.central.common.datascope.mp.interceptor.DataScopeInnerInterceptor;
import com.central.common.datascope.mp.interceptor.EnableQuerySqlLogInnerInterceptor;
import com.central.common.datascope.mp.sql.handler.CreatorDataScopeSqlHandler;
import com.central.common.datascope.mp.sql.handler.SqlHandler;
import com.central.common.properties.DataScopeProperties;
import com.central.common.properties.TenantProperties;
import com.central.db.interceptor.CustomTenantInterceptor;
import com.central.db.properties.MybatisPlusAutoFillProperties;
......@@ -23,7 +28,7 @@ import org.springframework.context.annotation.Bean;
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
@EnableConfigurationProperties(MybatisPlusAutoFillProperties.class)
@EnableConfigurationProperties({MybatisPlusAutoFillProperties.class, DataScopeProperties.class})
public class MybatisPlusAutoConfigure {
@Autowired
private TenantLineHandler tenantLineHandler;
......@@ -34,11 +39,20 @@ public class MybatisPlusAutoConfigure {
@Autowired
private MybatisPlusAutoFillProperties autoFillProperties;
@Autowired
private DataScopeProperties dataScopeProperties;
@Bean
@ConditionalOnMissingBean
public SqlHandler sqlHandler(){
return new CreatorDataScopeSqlHandler();
}
/**
* 分页插件,自动识别数据库类型
*/
@Bean
public MybatisPlusInterceptor paginationInterceptor() {
public MybatisPlusInterceptor paginationInterceptor(SqlHandler sqlHandler) {
MybatisPlusInterceptor mpInterceptor = new MybatisPlusInterceptor();
boolean enableTenant = tenantProperties.getEnable();
//是否开启多租户隔离
......@@ -47,6 +61,11 @@ public class MybatisPlusAutoConfigure {
tenantLineHandler, tenantProperties.getIgnoreSqls());
mpInterceptor.addInnerInterceptor(tenantInterceptor);
}
if(dataScopeProperties.getEnabled()){
DataScopeInnerInterceptor dataScopeInnerInterceptor = new DataScopeInnerInterceptor(dataScopeProperties, sqlHandler);
mpInterceptor.addInnerInterceptor(Boolean.TRUE.equals(dataScopeProperties.getEnabledSqlDebug())
? new EnableQuerySqlLogInnerInterceptor(dataScopeInnerInterceptor): dataScopeInnerInterceptor);
}
mpInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return mpInterceptor;
}
......
......@@ -5,7 +5,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-commons</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
......
......@@ -5,7 +5,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-commons</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
......
......@@ -5,7 +5,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-commons</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
......
......@@ -5,7 +5,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-commons</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
......
......@@ -5,7 +5,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-commons</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
......
......@@ -5,7 +5,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-commons</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
......
......@@ -5,7 +5,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-commons</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
......
......@@ -5,7 +5,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-commons</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
......
......@@ -5,7 +5,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>central-platform</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
......
......@@ -6,7 +6,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-demo</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>dubbo-demo</artifactId>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>central-platform</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>zlt-demo</artifactId>
<packaging>pom</packaging>
......
......@@ -6,7 +6,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-demo</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>resources-server-demo</artifactId>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-demo</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>rocketmq-demo</artifactId>
<packaging>pom</packaging>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>rocketmq-demo</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>rocketmq-consume</artifactId>
<description>rocketMQ消费者demo</description>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>rocketmq-demo</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>rocketmq-produce</artifactId>
<description>rocketMQ生产者demo</description>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>rocketmq-demo</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>rocketmq-transactional</artifactId>
<description>rocketMQ事务消息demo</description>
......
......@@ -5,7 +5,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>seata-demo</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>account-service</artifactId>
......
......@@ -5,7 +5,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>seata-demo</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>business-service</artifactId>
......
......@@ -5,7 +5,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>seata-demo</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>order-service</artifactId>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-demo</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>seata-demo</artifactId>
<description>seata分布式事务demo</description>
......
......@@ -5,7 +5,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>seata-demo</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>seata-common-starter</artifactId>
......
......@@ -5,7 +5,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>seata-demo</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>storage-service</artifactId>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-demo</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>sharding-jdbc-demo</artifactId>
<description>sharding-jdbc分库分表demo</description>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>sso-demo</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>oidc-sso</artifactId>
<description>OIDC协议单点登录demo</description>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-demo</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>sso-demo</artifactId>
<packaging>pom</packaging>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>sso-demo</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>ss-sso</artifactId>
<description>springSecurity单点登录demo</description>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>sso-demo</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>web-sso</artifactId>
<description>前后端分离单点登录demo</description>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-demo</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>txlcn-demo</artifactId>
<description>txlcn分布式事务demo</description>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>txlcn-demo</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>txlcn-demo-common</artifactId>
<name>demo-common</name>
......
......@@ -3,7 +3,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>txlcn-demo</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
......
package org.txlcn.demo;
import com.central.common.lb.annotation.EnableFeignInterceptor;
import com.codingapi.txlcn.tc.config.EnableDistributedTransaction;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
......@@ -14,6 +15,7 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@SpringBootApplication
@EnableDiscoveryClient
@EnableDistributedTransaction
@EnableFeignInterceptor
public class ServiceAApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceAApplication.class, args);
......
......@@ -3,7 +3,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>txlcn-demo</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>txlcn-demo-spring-service-b</artifactId>
......
......@@ -3,7 +3,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>txlcn-demo</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>txlcn-demo-spring-service-c</artifactId>
......
......@@ -6,7 +6,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-demo</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>websocket-demo</artifactId>
......
......@@ -24,12 +24,13 @@ CREATE TABLE `oauth_client_details` (
`client_name` varchar(128) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT '应用名称',
`support_id_token` tinyint(1) DEFAULT 1 COMMENT '是否支持id_token',
`id_token_validity` int(11) DEFAULT 60 COMMENT 'id_token有效期',
`creator_id` int(11) COMMENT '创建人id',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of oauth_client_details
-- ----------------------------
INSERT INTO `oauth_client_details` VALUES (1, 'webApp', NULL, '$2a$10$06msMGYRH8nrm4iVnKFNKOoddB8wOwymVhbUzw/d3ZixD7Nq8ot72', 'webApp', 'app', 'authorization_code,password,refresh_token,client_credentials,implicit,password_code,openId,mobile_password', NULL, NULL, 3600, NULL, '{"LOGOUT_NOTIFY_URL_LIST":"http://127.0.0.1:8082/logoutNotify"}', 'true', NULL, NULL, 'pc端', 1, 60);
INSERT INTO `oauth_client_details` VALUES (1, 'webApp', NULL, '$2a$10$06msMGYRH8nrm4iVnKFNKOoddB8wOwymVhbUzw/d3ZixD7Nq8ot72', 'webApp', 'app', 'authorization_code,password,refresh_token,client_credentials,implicit,password_code,openId,mobile_password', 'http://127.0.0.1:8082/callback.html', NULL, 3600, NULL, '{"LOGOUT_NOTIFY_URL_LIST":"http://127.0.0.1:8082/logoutNotify"}', 'true', NULL, NULL, 'pc端', 1, 60);
INSERT INTO `oauth_client_details` VALUES (2, 'app', NULL, '$2a$10$i3F515wEDiB4Gvj9ym9Prui0dasRttEUQ9ink4Wpgb4zEDCAlV8zO', 'app', 'app', 'authorization_code,password,refresh_token', 'http://127.0.0.1:8081/callback.html', NULL, 3600, NULL, '{"LOGOUT_NOTIFY_URL_LIST":"http://127.0.0.1:8081/logoutNotify"}', 'true', NULL, NULL, '移动端', 1, 60);
INSERT INTO `oauth_client_details` VALUES (3, 'zlt', NULL, '$2a$10$/o.wuORzVcXaezmYVzwYMuoY7qeWXBALwQmkskXD/7C6rqfCyPrna', 'zlt', 'all', 'authorization_code,password,refresh_token,client_credentials', 'http://127.0.0.1:8080/singleLogin', NULL, 3600, 28800, '{}', 'true', '2018-12-27 00:50:30', '2018-12-27 00:50:30', '第三方应用', 1, 60);
\ No newline at end of file
此差异已折叠。
------------更新语句
Use `user-center`;
alter table sys_role add data_scope varchar(32) DEFAULT 'ALL' comment '数据权限范围配置:ALL/全部权限,CREATOR/创建者权限';
alter table sys_user add `creator_id` int(11) COMMENT '创建人id';
update sys_user set creator_id = 1;
alter table sys_role add `creator_id` int(11) COMMENT '创建人id';
update sys_role set creator_id = 1;
alter table sys_menu add `creator_id` int(11) COMMENT '创建人id';
update sys_menu set creator_id = 1;
Use `oauth-center`;
alter table oauth_client_details add `creator_id` int(11) COMMENT '创建人id';
update oauth_client_details set creator_id = 1;
\ No newline at end of file
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>central-platform</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>zlt-gateway</artifactId>
<packaging>pom</packaging>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-gateway</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>sc-gateway</artifactId>
<description>spring cloud gateway网关</description>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-job</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>job-admin</artifactId>
<packaging>jar</packaging>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-job</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>job-core</artifactId>
<packaging>jar</packaging>
......
......@@ -6,7 +6,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-job</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>job-executor-samples</artifactId>
<packaging>jar</packaging>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>central-platform</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>zlt-job</artifactId>
<packaging>pom</packaging>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-monitor</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>log-center</artifactId>
<dependencies>
......
......@@ -3,7 +3,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>central-platform</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>zlt-monitor</artifactId>
<packaging>pom</packaging>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-monitor</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>sc-admin</artifactId>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>central-platform</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>zlt-transaction</artifactId>
<description>事务</description>
......
......@@ -3,7 +3,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>zlt-transaction</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>txlcn-tm</artifactId>
......
......@@ -4,7 +4,7 @@
<parent>
<groupId>com.zlt</groupId>
<artifactId>central-platform</artifactId>
<version>5.5.0</version>
<version>5.6.0</version>
</parent>
<artifactId>zlt-uaa</artifactId>
<description>认证中心</description>
......
package com.central.oauth.config;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
......
......@@ -3,19 +3,21 @@ package com.central.oauth.filter;
import com.central.common.constant.SecurityConstants;
import com.central.common.context.TenantContextHolder;
import com.central.common.model.Result;
import com.central.oauth.handler.decryptParamHandler.IDecryptParamHandler;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.common.util.OAuth2Utils;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.security.Principal;
import java.util.Map;
......@@ -34,17 +36,23 @@ import java.util.Map;
@Component
@Aspect
public class OauthTokenAspect {
@Resource
private IDecryptParamHandler decryptParamHandler;
@Around("execution(* org.springframework.security.oauth2.provider.endpoint.TokenEndpoint.postAccessToken(..))")
public Object handleControllerMethod(ProceedingJoinPoint joinPoint) throws Throwable {
try {
Object[] args = joinPoint.getArgs();
Principal principal = (Principal) args[0];
if (!(principal instanceof Authentication)) {
throw new InsufficientAuthenticationException(
throw new OAuth2Exception(
"There is no client authentication. Try adding an appropriate authentication filter.");
}
String clientId = getClientId(principal);
Map<String, String> parameters = (Map<String, String>) args[1];
//解密参数
decryptParamHandler.decryptParams(parameters);
String grantType = parameters.get(OAuth2Utils.GRANT_TYPE);
if (!parameters.containsKey(SecurityConstants.ACCOUNT_TYPE_PARAM_NAME)) {
parameters.put(SecurityConstants.ACCOUNT_TYPE_PARAM_NAME, SecurityConstants.DEF_ACCOUNT_TYPE);
......@@ -74,7 +82,7 @@ public class OauthTokenAspect {
private String getClientId(Principal principal) {
Authentication client = (Authentication) principal;
if (!client.isAuthenticated()) {
throw new InsufficientAuthenticationException("The client is not authenticated.");
throw new OAuth2Exception("The client is not authenticated.");
}
String clientId = client.getName();
if (client instanceof OAuth2Authentication) {
......
package com.central.oauth.handler.decryptParamHandler;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import java.util.Map;
/**
* 解密参数的处理接口
*
* @author zlt
* @version 1.0
* @date 2022/12/29
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
public interface IDecryptParamHandler {
String SEPARATOR = ";";
/**
* 需要解密的参数名,多个以 ; 隔离
* 例如:decrypt_param=username;password
*/
String PARAM_KEY_DECRYPT_PARAM = "decrypt_param";
/**
* 根据 parameters里面decrypt_param 的值进行参数解密,并把解密后的值替换原值
* @param parameters 参数集合
*/
default void decryptParams(Map<String, String> parameters) {
if (CollUtil.isNotEmpty(parameters)) {
//从 parameters 中获取 decrypt_param 参数值
String decryptParam = parameters.get(PARAM_KEY_DECRYPT_PARAM);
//如果参数decrypt_param有值,则进行参数解密
if (StrUtil.isNotEmpty(decryptParam)) {
String[] paramNames = decryptParam.split(SEPARATOR);
this.decrypt(paramNames, parameters);
}
}
}
/**
* 解密并更新参数值
* @param paramNames 需要解密的参数名
* @param parameters 参数集合(参数名:参数值)
*/
void decrypt(String[] paramNames, Map<String, String> parameters);
}
package com.central.oauth.handler.decryptParamHandler;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import com.central.oauth2.common.properties.AuthProperties;
import com.central.oauth2.common.properties.SecurityProperties;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.stereotype.Service;
import java.util.Map;
/**
* 使用rsa算法对参数进行解密
*
* @author zlt
* @version 1.0
* @date 2022/12/29
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
@Service
public class RsaDecryptParamHandler implements IDecryptParamHandler {
private final AuthProperties authProperties;
public RsaDecryptParamHandler(SecurityProperties securityProperties) {
this.authProperties = securityProperties.getAuth();
}
@Override
public void decrypt(String[] paramNames, Map<String, String> parameters) {
RSA rsaTools = SecureUtil.rsa(authProperties.getDecryptParamPrivateKey(), null);
String value;
for (String param : paramNames) {
value = parameters.get(param);
if (StrUtil.isNotEmpty(value)) {
//解密
value = this.decrypt(rsaTools, value, param);
//更新参数为解密后的值
parameters.put(param, value);
}
}
}
private String decrypt(RSA rsaTools, String value, String param) {
try {
return rsaTools.decryptStr(value, KeyType.PrivateKey);
} catch (Exception e) {
throw new OAuth2Exception("参数 " + param + " 解密失败!");
}
}
}
......@@ -41,4 +41,6 @@ public class Client extends SuperEntity {
*/
@TableField(value = "id_token_validity")
private Integer idTokenValiditySeconds = 60;
private Long creatorId;
}
......@@ -3,6 +3,7 @@ package com.central.oauth.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.central.common.context.LoginUserContextHolder;
import com.central.common.lock.DistributedLock;
import com.central.common.redis.template.RedisRepository;
import com.central.common.constant.SecurityConstants;
......@@ -45,6 +46,9 @@ public class ClientServiceImpl extends SuperServiceImpl<ClientMapper, Client> im
public Result saveClient(Client client) throws Exception {
client.setClientSecret(passwordEncoder.encode(client.getClientSecretStr()));
String clientId = client.getClientId();
if (client.getId() == null) {
client.setCreatorId(LoginUserContextHolder.getUser().getId());
}
super.saveOrUpdateIdempotency(client, lock
, LOCK_KEY_CLIENTID+clientId
, new QueryWrapper<Client>().eq("client_id", clientId)
......
......@@ -37,4 +37,10 @@ zlt:
tenant:
enable: true
ignoreTables:
- oauth_client_details
\ No newline at end of file
- oauth_client_details
# 数据权限
datascope:
enabled: false
includeSqls:
# 应用列表
- com.central.oauth.mapper.ClientMapper.findList
\ No newline at end of file
package com.central.oauth2.common.util;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.junit4.SpringRunner;
/**
* RSA加密测试
*
* @author zlt
* @version 1.0
* @date 2023/1/30
* <p>
* Blog: https://zlt2000.gitee.io
* Github: https://github.com/zlt2000
*/
@RunWith(SpringRunner.class)
public class RsaUtilsTest {
/**
* 私钥
*/
private final static String PRIVATE_KEY = "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDq7iw/3r2Fk/sFQR4BcmWrnASZnYIhlTj7kkANjwi6bnmoZoTmpcTAxpX4zYcVZTg9lsd8f5EYQgzCOQBFGiT3eSsWcm67BOMvCDJRKwqbkzu/cSTzN2qzjvi/Wo7GoToGYfP1Al+CcC0VjHATJVGhDXb4gCGk7MNTevPTZVHTmQYKuAZTqzPEO2npxD670AIY/L+4p0hDoftoz+jEzI+XAr0ffyeLovFqLurnqqnoXWnt2vGHwJYlnePQ2JwHlk+c4y2sYvmV+eJ8cGMH4IMle/yR99jTPAvcn4uufIVukp414wlmnKShhbzk93P7xacT0oYwzcR454P9Bf858x0VAgMBAAECggEBAJxK94VGWi+T01wbhirQQHN6yFSqRPiyncY/9f0PO29MMAOosKIBhnP5qaxsj4HcZR4UQYLCG3VX+8T6xwMx8YXyRogYeTJSfhG8Ej2NtPDrcsRaMYrdQ09RvosPZA0hFclJQVOu0HumxVegpq8WFMhgfNW16KwgF5JiKfRpY5aw4NDWZFmdNExdymrWPheI8pWBq/U+l8oqrekhbiEKXM2UXmLlKTS9Nk46LRYwaaiDW8JEFuPdx0cnakb+ecCXGd/8Cc8Hxn/mLyvqS1cWHT3J+lXRkfcnNnrJTR9qhf9l077XBMJqVckFEpK4kKbXHZd957ISAxq48Tm+xMX9KAECgYEA995szPToU0BxTTtOD4Z4c5JvbURQEcDQl/dB+qCQnu/orW5ZWv4++lHq2SZPjzbt7M8OaoRN8A5zYcNrYe4kBhLOLqHdaS1yUGIIjAejEAJplR5GqI3T5qzaLjpyiUZpO0mOcwAazCevnSXH6uO5jP0sjwxwaXz4OsTcpHIXHqECgYEA8qMXhh+G88+vTELL/2dHhtTIf7IAJLQ37c1Xrm6uwOHPfiDr256Lc4EzF8QAQqlHoYm1jRK7xDfFymY/SJKJVhYehWlNilnMuDuDOqseC/Zn2KgjMSjLLVkbp25DcpAu6SSiWlBvemrV3jivX/MU0BFp8HjbrlUcl12lRtYgrfUCgYB+iN2iA6RWW597fbrr0gnLdgXMEgOODJBwA5l7CFzLxk1Ru/OBsCkWQJtTH2ueALyVF16UodXnpnjgf5Jh++AH+bGnvJn7B2hEAMe8NGnZ0mFz7nDDuyNhrvvyfYPa8EboLTS7IGKNtfTAlHjqQDaI8vW8UO1R7KoL1lOM33FOAQKBgQDt/Z6jReU+3CUbbiFeANWdoLSQ2+1cExEQxWsNgy8Rreux0WTG4/nwb3fIBc4jlJrYDZTwLMHTssjkv+muq1zd/ZAuV51g6LfutSEAuLseDLDLSBBMtbCkaFTBo1uw0U/SCsbcQy01K/leoMcUG//8HjiFUGZZ1s3WgloM4xbmyQKBgAipgnoEyzvUfe2OMOc5ARGNSGZG4JGTGCyfnrYvYfffWpAokklHOkZMumeSWJXkx5F+MgJd9fxBK9S57PZ09gWkoeSVg0xcz5QMjh8BswfCdyet/CXQtwIfK0Wf1gWdAxC6vvv3DQ7zXbTlvqMdVOFzCKlocCYkzWMvIsejWXnW";
/**
* 公钥
*/
private final static String PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6u4sP969hZP7BUEeAXJlq5wEmZ2CIZU4+5JADY8Ium55qGaE5qXEwMaV+M2HFWU4PZbHfH+RGEIMwjkARRok93krFnJuuwTjLwgyUSsKm5M7v3Ek8zdqs474v1qOxqE6BmHz9QJfgnAtFYxwEyVRoQ12+IAhpOzDU3rz02VR05kGCrgGU6szxDtp6cQ+u9ACGPy/uKdIQ6H7aM/oxMyPlwK9H38ni6Lxai7q56qp6F1p7drxh8CWJZ3j0NicB5ZPnOMtrGL5lfnifHBjB+CDJXv8kffY0zwL3J+LrnyFbpKeNeMJZpykoYW85Pdz+8WnE9KGMM3EeOeD/QX/OfMdFQIDAQAB";
private static RSA rsaTools;
@BeforeClass
public static void init() {
rsaTools = SecureUtil.rsa(PRIVATE_KEY, PUBLIC_KEY);
}
@Test
public void testDecrypt() {
String value = "admin";
String result = rsaTools.encryptBcd(value, KeyType.PublicKey);
System.out.println(result);
}
@Test
public void testEncrypt() {
String value = "8A806900A16294BF11F3D0455ADE2759CCC8C52F0BB5DEF731A0E5F596203401899B545B36E7072EC4CC1AA2FDE7481589783D555D36EDDDC19587D62B6AB39A6478FF75600F2B3671816D33C2AF6776F3865838EA2D90060E01C014B6F0DAE7D0D09EC80FF3F2ABFE5F12F111A72390A0083534789F49D9CA36CF39D071622B75C5B5F2BEC609F7C7EE53E324FA0443AC31BE40FF9B6693AE5BEAC0BFDC677794E7A5B503B3A3F571DD6AB5169598F5FC59D63EF60E572FFDF3CA2DCB818A2448C6E25CC46B17CBB232B0F46BC05C916EEB05E9C852B0729C3DE28C7FD679B89E370FB829ACB4485A7346E50AA06655A5A9DFDA5685145A6142A04ACF72D689";
String result = rsaTools.decryptStr(value, KeyType.PrivateKey);
System.out.println(result);
}
}
FROM nginx:1.21.0
LABEL MAINTAINER=Andy
RUN rm -rf /usr/share/nginx/html/*
COPY src/main/resources/static/ /usr/share/nginx/html/
# docker run --name zlt-web \
# -v /host/path/apiUrl.js:/usr/share/nginx/html/module/apiUrl.js:ro
# -d zlt-web:4.5
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册