mirror of
https://gitee.com/smallc/blade-tool.git
synced 2026-07-10 18:39:44 +08:00
🎉 4.8.0.RELEASE 新增接口权限模块,增强系统安全性
This commit is contained in:
parent
92770ff35e
commit
80a2844c4a
40
README.md
40
README.md
|
|
@ -1,14 +1,9 @@
|
|||
<p align="center">
|
||||
<img src="https://img.shields.io/badge/Release-V4.8.0-blue.svg" alt="Downloads">
|
||||
<img src="https://img.shields.io/badge/JDK-17+-green.svg" alt="Build Status">
|
||||
<img src="https://img.shields.io/badge/license-LGPL%20v3-blue.svg" alt="Build Status">
|
||||
<img src="https://img.shields.io/badge/Spring%20Cloud-2025-blue.svg" alt="Coverage Status">
|
||||
<img src="https://img.shields.io/badge/Spring%20Boot-3.5-blue.svg" alt="Downloads">
|
||||
<a href="https://central.sonatype.com/artifact/org.springblade/blade-core-bom/versions">
|
||||
<img src="https://img.shields.io/nexus/r/https/oss.sonatype.org/org.springblade/blade-core-bom.svg?style=flat-square" alt="Downloads">
|
||||
</a>
|
||||
<a href="https://oss.sonatype.org/content/repositories/snapshots/org/springblade/blade-core-bom/">
|
||||
<img src="https://img.shields.io/nexus/s/https/oss.sonatype.org/org.springblade/blade-core-bom.svg?style=flat-square" alt="Downloads">
|
||||
</a>
|
||||
<br/>
|
||||
<a target="_blank" href="https://bladex.cn">
|
||||
<img src="https://img.shields.io/badge/Author-Small%20Chill-ff69b4.svg" alt="Downloads">
|
||||
|
|
@ -39,15 +34,14 @@
|
|||
|----------------------|------------|
|
||||
| Java | 17+ |
|
||||
| NodeJS | 18+ |
|
||||
| Spring | 6.2.11 |
|
||||
| Spring Boot | 3.5.6 |
|
||||
| Spring Cloud | 2025.0.0 |
|
||||
| Spring Cloud Alibaba | 2023.0.3.3 |
|
||||
| Nacos Alibaba | 3.1.0 |
|
||||
| Spring | 6.2.15 |
|
||||
| Spring Boot | 3.5.9 |
|
||||
| Spring Cloud | 2025.0.1 |
|
||||
| Spring Cloud Alibaba | 2025.0.0.0 |
|
||||
| Nacos Alibaba | 3.1.1 |
|
||||
| Mybatis Plus | 3.5.19 |
|
||||
|
||||
|
||||
|
||||
## 工程结构
|
||||
```
|
||||
blade-tool
|
||||
|
|
@ -93,20 +87,20 @@ blade-tool
|
|||
|
||||
## 官方产品
|
||||
|
||||
| 简介 | 演示地址 |
|
||||
|---------------|------------------------------------------------------|
|
||||
| BladeX企业级开发平台 | [https://saber3.bladex.cn](https://saber3.bladex.cn) |
|
||||
| BladeX可视化数据大屏 | [https://data.bladex.cn](https://data.bladex.cn) |
|
||||
| BladeX物联网开发平台 | [https://iot.bladex.cn](https://iot.bladex.cn) |
|
||||
| BladeX大模型开发平台 | [https://ai.bladex.cn](https://ai.bladex.cn) |
|
||||
| 简介 | 演示地址 |
|
||||
|-----------------|------------------------------------------------------|
|
||||
| BladeX企业级开发平台 | [https://saber3.bladex.cn](https://saber3.bladex.cn) |
|
||||
| BladeX可视化数据大屏 | [https://data.bladex.cn](https://data.bladex.cn) |
|
||||
| BladeX物联网开发平台 | [https://iot.bladex.cn](https://iot.bladex.cn) |
|
||||
| BladeXAI大模型平台 | [https://ai.bladex.cn/](https://ai.bladex.cn/) |
|
||||
|
||||
## 前端项目
|
||||
|
||||
| 简介 | 地址 |
|
||||
|--------------------|----------------------------------------------------------------------------------------------------|
|
||||
| 前端框架Sword(基于React) | [https://gitee.com/smallc/Sword](https://gitee.com/smallc/Sword) |
|
||||
| 前端框架Saber(基于Vue2) | [https://gitee.com/smallc/Saber](https://gitee.com/smallc/Saber) |
|
||||
| 前端框架Saber3(基于Vue3) | [https://gitee.com/smallc/Saber3](https://gitee.com/smallc/Saber/tree/3.x/) |
|
||||
| 简介 | 地址 |
|
||||
|--------------------|------------------------------------------------------------------------------|
|
||||
| 前端框架Saber3(基于Vue3) | [https://gitee.com/smallc/Saber3](https://gitee.com/smallc/Saber) |
|
||||
| 前端框架Saber(基于Vue2) | [https://gitee.com/smallc/Saber2](https://gitee.com/smallc/Saber/tree/vue2/) |
|
||||
| 前端框架Sword(基于React) | [https://gitee.com/smallc/Sword](https://gitee.com/smallc/Sword) |
|
||||
|
||||
## 后端项目
|
||||
| 简介 | 地址 |
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@
|
|||
<dependency>
|
||||
<groupId>de.codecentric</groupId>
|
||||
<artifactId>spring-boot-admin-starter-client</artifactId>
|
||||
<version>${spring.boot.admin.version}</version>
|
||||
</dependency>
|
||||
<!-- Nacos -->
|
||||
<dependency>
|
||||
|
|
|
|||
|
|
@ -33,6 +33,10 @@
|
|||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-core-tool</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springblade</groupId>
|
||||
<artifactId>blade-starter-cache</artifactId>
|
||||
</dependency>
|
||||
<!--Jdbc-->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
|
|
|
|||
|
|
@ -15,10 +15,34 @@
|
|||
*/
|
||||
package org.springblade.core.secure.annotation;
|
||||
|
||||
import org.springblade.core.tool.utils.StringPool;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 权限注解 用于检查权限 规定访问权限
|
||||
* 权限注解,用于检查权限,规定访问权限
|
||||
* 支持以下几种使用方式:
|
||||
* <p>
|
||||
* 1. 单个属性模式:
|
||||
* <pre>{@code
|
||||
* @PreAuth(permission = "user:add")
|
||||
* @PreAuth(role = "admin")
|
||||
* }</pre>
|
||||
*
|
||||
* 2. 组合属性模式:
|
||||
* <pre>{@code
|
||||
* @PreAuth(role = "admin", permission = "user:add")
|
||||
* }</pre>
|
||||
*
|
||||
* 3. SpEL表达式模式:
|
||||
* <pre>{@code
|
||||
* @PreAuth("#userVO.id<10")
|
||||
* @PreAuth("hasRole('admin')")
|
||||
* @PreAuth("hasPermission('user:add')")
|
||||
* @PreAuth("hasPermission(#test) and hasRole('admin')")
|
||||
* }</pre>
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
|
|
@ -27,10 +51,19 @@ import java.lang.annotation.*;
|
|||
public @interface PreAuth {
|
||||
|
||||
/**
|
||||
* Spring el
|
||||
* 文档地址:https://docs.spring.io/spring/docs/4.3.16.RELEASE/spring-framework-reference/htmlsingle/#expressions-operators-logical
|
||||
* Spring el表达式
|
||||
*/
|
||||
String value();
|
||||
String value() default StringPool.EMPTY;
|
||||
|
||||
/**
|
||||
* 接口权限编码
|
||||
*/
|
||||
String permission() default StringPool.EMPTY;
|
||||
|
||||
/**
|
||||
* 角色权限
|
||||
*/
|
||||
String role() default StringPool.EMPTY;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@
|
|||
*/
|
||||
package org.springblade.core.secure.aspect;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
|
|
@ -22,6 +24,7 @@ import org.aspectj.lang.reflect.MethodSignature;
|
|||
import org.springblade.core.secure.annotation.PreAuth;
|
||||
import org.springblade.core.secure.auth.AuthFun;
|
||||
import org.springblade.core.secure.exception.SecureException;
|
||||
import org.springblade.core.secure.utils.AuthUtil;
|
||||
import org.springblade.core.tool.api.ResultCode;
|
||||
import org.springblade.core.tool.utils.ClassUtil;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
|
|
@ -34,6 +37,7 @@ import org.springframework.expression.Expression;
|
|||
import org.springframework.expression.ExpressionParser;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
|
|
@ -42,13 +46,20 @@ import java.lang.reflect.Method;
|
|||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@Slf4j
|
||||
@Aspect
|
||||
@RequiredArgsConstructor
|
||||
public class AuthAspect implements ApplicationContextAware {
|
||||
|
||||
/**
|
||||
* 权限处理函数
|
||||
*/
|
||||
private final AuthFun authFun;
|
||||
|
||||
/**
|
||||
* 表达式处理
|
||||
*/
|
||||
private static final ExpressionParser SPEL_PARSER = new SpelExpressionParser();
|
||||
private static final ExpressionParser EXPRESSION_PARSER = new SpelExpressionParser();
|
||||
|
||||
/**
|
||||
* 切 方法 和 类上的 @PreAuth 注解
|
||||
|
|
@ -74,20 +85,30 @@ public class AuthAspect implements ApplicationContextAware {
|
|||
* @param point 切点
|
||||
*/
|
||||
private boolean handleAuth(ProceedingJoinPoint point) {
|
||||
// 读取权限注解,优先方法上,没有则读取类
|
||||
MethodSignature ms = (MethodSignature) point.getSignature();
|
||||
Method method = ms.getMethod();
|
||||
// 读取权限注解,优先方法上,没有则读取类
|
||||
PreAuth preAuth = ClassUtil.getAnnotation(method, PreAuth.class);
|
||||
// 处理接口权限属性验证
|
||||
if (StringUtil.isNotBlank(preAuth.permission()) && !authFun.hasPermission(preAuth.permission())) {
|
||||
return false;
|
||||
}
|
||||
// 处理角色权限属性验证
|
||||
if (StringUtil.isNotBlank(preAuth.role()) && !authFun.hasRole(preAuth.role())) {
|
||||
return false;
|
||||
}
|
||||
// 判断表达式
|
||||
String condition = preAuth.value();
|
||||
if (StringUtil.isNotBlank(condition)) {
|
||||
Expression expression = SPEL_PARSER.parseExpression(condition);
|
||||
Expression expression = EXPRESSION_PARSER.parseExpression(condition);
|
||||
// 方法参数值
|
||||
Object[] args = point.getArgs();
|
||||
StandardEvaluationContext context = getEvaluationContext(method, args);
|
||||
return expression.getValue(context, Boolean.class);
|
||||
return Boolean.TRUE.equals(expression.getValue(context, Boolean.class));
|
||||
} else {
|
||||
// 判断用户是否通过鉴权
|
||||
return AuthUtil.hasAuth();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -99,7 +120,7 @@ public class AuthAspect implements ApplicationContextAware {
|
|||
*/
|
||||
private StandardEvaluationContext getEvaluationContext(Method method, Object[] args) {
|
||||
// 初始化Sp el表达式上下文,并设置 AuthFun
|
||||
StandardEvaluationContext context = new StandardEvaluationContext(new AuthFun());
|
||||
StandardEvaluationContext context = new StandardEvaluationContext(authFun);
|
||||
// 设置表达式支持spring bean
|
||||
context.setBeanResolver(new BeanFactoryResolver(applicationContext));
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
|
|
@ -114,7 +135,7 @@ public class AuthAspect implements ApplicationContextAware {
|
|||
private ApplicationContext applicationContext;
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
public void setApplicationContext(@NonNull ApplicationContext applicationContext) throws BeansException {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,15 +15,15 @@
|
|||
*/
|
||||
package org.springblade.core.secure.auth;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.springblade.core.launch.constant.TokenConstant;
|
||||
import org.springblade.core.secure.BladeUser;
|
||||
import org.springblade.core.secure.handler.IPermissionHandler;
|
||||
import org.springblade.core.secure.utils.AuthUtil;
|
||||
import org.springblade.core.secure.utils.SecureUtil;
|
||||
import org.springblade.core.tool.constant.RoleConstant;
|
||||
import org.springblade.core.tool.utils.CollectionUtil;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
import org.springblade.core.tool.utils.WebUtil;
|
||||
import org.springblade.core.tool.utils.*;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
|
|
@ -33,6 +33,37 @@ import java.util.Objects;
|
|||
*/
|
||||
public class AuthFun {
|
||||
|
||||
/**
|
||||
* 权限校验处理器
|
||||
*/
|
||||
private static IPermissionHandler permissionHandler;
|
||||
|
||||
private static IPermissionHandler getPermissionHandler() {
|
||||
if (permissionHandler == null) {
|
||||
permissionHandler = SpringUtil.getBean(IPermissionHandler.class);
|
||||
}
|
||||
return permissionHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断角色是否具有接口权限(全量校验)
|
||||
*
|
||||
* @return {boolean}
|
||||
*/
|
||||
public boolean permissionAll() {
|
||||
return getPermissionHandler().permissionAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断角色是否具有接口权限
|
||||
*
|
||||
* @param permission 权限编号
|
||||
* @return {boolean}
|
||||
*/
|
||||
public boolean hasPermission(String permission) {
|
||||
return getPermissionHandler().hasPermission(permission);
|
||||
}
|
||||
|
||||
/**
|
||||
* 放行所有请求
|
||||
*
|
||||
|
|
@ -51,6 +82,27 @@ public class AuthFun {
|
|||
return hasRole(RoleConstant.ADMIN);
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否已授权
|
||||
*
|
||||
* @return {boolean}
|
||||
*/
|
||||
public boolean hasAuth() {
|
||||
return AuthUtil.hasAuth();
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否有时间授权
|
||||
*
|
||||
* @param start 开始时间
|
||||
* @param end 结束时间
|
||||
* @return {boolean}
|
||||
*/
|
||||
public boolean hasTimeAuth(Integer start, Integer end) {
|
||||
Integer hour = DateUtil.hour();
|
||||
return hour >= start && hour <= end;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否有该角色权限
|
||||
*
|
||||
|
|
@ -61,6 +113,21 @@ public class AuthFun {
|
|||
return hasAnyRole(role);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否具有所有角色权限
|
||||
*
|
||||
* @param role 角色集合
|
||||
* @return {boolean}
|
||||
*/
|
||||
public boolean hasAllRole(String... role) {
|
||||
for (String r : role) {
|
||||
if (!hasRole(r)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否有该角色权限
|
||||
*
|
||||
|
|
@ -68,7 +135,11 @@ public class AuthFun {
|
|||
* @return {boolean}
|
||||
*/
|
||||
public boolean hasAnyRole(String... role) {
|
||||
String userRole = SecureUtil.getUser().getRoleName();
|
||||
BladeUser user = AuthUtil.getUser();
|
||||
if (user == null) {
|
||||
return false;
|
||||
}
|
||||
String userRole = user.getRoleName();
|
||||
if (StringUtil.isBlank(userRole)) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -94,4 +165,29 @@ public class AuthFun {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否有该请求头
|
||||
*
|
||||
* @param header 请求头
|
||||
* @return {boolean}
|
||||
*/
|
||||
public boolean hasHeader(String header) {
|
||||
HttpServletRequest request = WebUtil.getRequest();
|
||||
String value = Objects.requireNonNull(request).getHeader(header);
|
||||
return StringUtil.isNotBlank(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否有该请求头
|
||||
*
|
||||
* @param header 请求头
|
||||
* @param key 请求值
|
||||
* @return {boolean}
|
||||
*/
|
||||
public boolean hasHeader(String header, String key) {
|
||||
HttpServletRequest request = WebUtil.getRequest();
|
||||
String value = Objects.requireNonNull(request).getHeader(header);
|
||||
return StringUtil.equals(value, key);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@ package org.springblade.core.secure.config;
|
|||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springblade.core.secure.aspect.AuthAspect;
|
||||
import org.springblade.core.secure.auth.AuthFun;
|
||||
import org.springblade.core.secure.handler.BladePermissionHandler;
|
||||
import org.springblade.core.secure.handler.IPermissionHandler;
|
||||
import org.springblade.core.secure.interceptor.ClientInterceptor;
|
||||
import org.springblade.core.secure.interceptor.SecureInterceptor;
|
||||
import org.springblade.core.secure.props.BladeAuthProperties;
|
||||
|
|
@ -66,7 +69,13 @@ public class SecureConfiguration implements WebMvcConfigurer {
|
|||
|
||||
@Bean
|
||||
public AuthAspect authAspect() {
|
||||
return new AuthAspect();
|
||||
return new AuthAspect(new AuthFun());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(IPermissionHandler.class)
|
||||
public IPermissionHandler permissionHandler() {
|
||||
return new BladePermissionHandler(jdbcTemplate);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
/**
|
||||
* Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.com).
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springblade.core.secure.constant;
|
||||
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
|
||||
/**
|
||||
* 权限校验常量
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public interface PermissionConstant {
|
||||
|
||||
/**
|
||||
* 获取角色所有的权限编号
|
||||
*
|
||||
* @param size 数量
|
||||
* @return string
|
||||
*/
|
||||
static String permissionAllStatement(int size) {
|
||||
return StringUtil.format("select scope_path as path from blade_scope_api where id in (select scope_id from blade_role_scope where scope_category = 2 and role_id in ({}))", buildHolder(size));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取角色指定的权限编号
|
||||
*
|
||||
* @param size 数量
|
||||
* @return string
|
||||
*/
|
||||
static String permissionCodeStatement(int size) {
|
||||
return StringUtil.format("select resource_code as code from blade_scope_api where resource_code = ? and id in (select scope_id from blade_role_scope where scope_category = 2 and role_id in ({}))", buildHolder(size));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Sql占位符
|
||||
*
|
||||
* @param size 数量
|
||||
* @return String
|
||||
*/
|
||||
static String buildHolder(int size) {
|
||||
StringBuilder builder = StringUtil.builder().append("?,".repeat(Math.max(0, size)));
|
||||
return StringUtil.removeSuffix(builder.toString(), ",");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
/**
|
||||
* Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.com).
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springblade.core.secure.handler;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springblade.core.secure.BladeUser;
|
||||
import org.springblade.core.secure.utils.AuthUtil;
|
||||
import org.springblade.core.cache.utils.CacheUtil;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springblade.core.tool.utils.StringPool;
|
||||
import org.springblade.core.tool.utils.WebUtil;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.springblade.core.secure.constant.PermissionConstant.permissionAllStatement;
|
||||
import static org.springblade.core.secure.constant.PermissionConstant.permissionCodeStatement;
|
||||
import static org.springblade.core.cache.utils.CacheUtil.SYS_CACHE;
|
||||
|
||||
/**
|
||||
* 默认授权校验类
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
public class BladePermissionHandler implements IPermissionHandler {
|
||||
|
||||
private static final String SCOPE_CACHE_ROLE = "apiScope:role:";
|
||||
|
||||
private static final String SCOPE_CACHE_CODE = "apiScope:code:";
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
@Override
|
||||
public boolean permissionAll() {
|
||||
HttpServletRequest request = WebUtil.getRequest();
|
||||
BladeUser user = AuthUtil.getUser();
|
||||
if (request == null || user == null) {
|
||||
return false;
|
||||
}
|
||||
String uri = request.getRequestURI();
|
||||
List<String> paths = permissionPath(user.getRoleId());
|
||||
if (paths.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
return paths.stream().anyMatch(uri::contains);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(String permission) {
|
||||
HttpServletRequest request = WebUtil.getRequest();
|
||||
BladeUser user = AuthUtil.getUser();
|
||||
if (request == null || user == null) {
|
||||
return false;
|
||||
}
|
||||
List<String> codes = permissionCode(permission, user.getRoleId());
|
||||
return !codes.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取接口权限地址
|
||||
*
|
||||
* @param roleId 角色id
|
||||
* @return permissions
|
||||
*/
|
||||
private List<String> permissionPath(String roleId) {
|
||||
List<String> permissions = CacheUtil.get(SYS_CACHE, SCOPE_CACHE_ROLE, roleId, List.class);
|
||||
if (permissions == null) {
|
||||
List<Long> roleIds = Func.toLongList(roleId);
|
||||
permissions = jdbcTemplate.queryForList(permissionAllStatement(roleIds.size()), String.class, roleIds.toArray());
|
||||
CacheUtil.put(SYS_CACHE, SCOPE_CACHE_ROLE, roleId, permissions);
|
||||
}
|
||||
return permissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取接口权限信息
|
||||
*
|
||||
* @param permission 权限编号
|
||||
* @param roleId 角色id
|
||||
* @return permissions
|
||||
*/
|
||||
private List<String> permissionCode(String permission, String roleId) {
|
||||
String cacheKey = permission + StringPool.COLON + roleId;
|
||||
List<String> permissions = CacheUtil.get(SYS_CACHE, SCOPE_CACHE_CODE, cacheKey, List.class);
|
||||
if (permissions == null) {
|
||||
List<Object> args = new ArrayList<>(Collections.singletonList(permission));
|
||||
List<Long> roleIds = Func.toLongList(roleId);
|
||||
args.addAll(roleIds);
|
||||
permissions = jdbcTemplate.queryForList(permissionCodeStatement(roleIds.size()), String.class, args.toArray());
|
||||
CacheUtil.put(SYS_CACHE, SCOPE_CACHE_CODE, cacheKey, permissions);
|
||||
}
|
||||
return permissions;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
/**
|
||||
* Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.com).
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springblade.core.secure.handler;
|
||||
|
||||
/**
|
||||
* 权限校验通用接口
|
||||
*
|
||||
* @author Chill
|
||||
*/
|
||||
public interface IPermissionHandler {
|
||||
|
||||
/**
|
||||
* 判断角色是否具有接口权限(全量校验)
|
||||
*
|
||||
* @return {boolean}
|
||||
*/
|
||||
boolean permissionAll();
|
||||
|
||||
/**
|
||||
* 判断角色是否具有接口权限
|
||||
*
|
||||
* @param permission 权限编号
|
||||
* @return {boolean}
|
||||
*/
|
||||
boolean hasPermission(String permission);
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -303,6 +303,15 @@ public class SecureUtil {
|
|||
return (null == user) ? StringPool.EMPTY : user.getClientId();
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否已授权
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public static boolean hasAuth() {
|
||||
return getUser() != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取Claims
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,170 +0,0 @@
|
|||
/**
|
||||
* Copyright (c) 2018-2099, Chill Zhuang 庄骞 (bladejava@qq.com).
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springblade.core.tool.utils;
|
||||
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/**
|
||||
* 缓存工具类
|
||||
*
|
||||
* @author Chill
|
||||
* @deprecated in favor of {org.springblade.core.cache.utils.CacheUtil}.
|
||||
*/
|
||||
@Deprecated
|
||||
public class CacheUtil {
|
||||
|
||||
public static final String SYS_CACHE = "blade:sys";
|
||||
|
||||
private static CacheManager cacheManager;
|
||||
|
||||
/**
|
||||
* 获取缓存工具
|
||||
*
|
||||
* @return CacheManager
|
||||
*/
|
||||
private static CacheManager getCacheManager() {
|
||||
if (cacheManager == null) {
|
||||
cacheManager = SpringUtil.getBean(CacheManager.class);
|
||||
}
|
||||
return cacheManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓存对象
|
||||
*
|
||||
* @param cacheName 缓存名
|
||||
* @return Cache
|
||||
*/
|
||||
public static Cache getCache(String cacheName) {
|
||||
return getCacheManager().getCache(cacheName);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓存
|
||||
*
|
||||
* @param cacheName 缓存名
|
||||
* @param keyPrefix 缓存键前缀
|
||||
* @param key 缓存键值
|
||||
* @return Cache
|
||||
*/
|
||||
@Nullable
|
||||
public static Object get(String cacheName, String keyPrefix, Object key) {
|
||||
if (Func.hasEmpty(cacheName, keyPrefix, key)) {
|
||||
return null;
|
||||
}
|
||||
Cache.ValueWrapper wrapper = getCache(cacheName).get(keyPrefix.concat(String.valueOf(key)));
|
||||
return wrapper == null ? null : wrapper.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓存
|
||||
*
|
||||
* @param cacheName 缓存名
|
||||
* @param keyPrefix 缓存键前缀
|
||||
* @param key 缓存键值
|
||||
* @param type 转换类型
|
||||
* @param <T> 类型
|
||||
* @return Cache
|
||||
*/
|
||||
@Nullable
|
||||
public static <T> T get(String cacheName, String keyPrefix, Object key, @Nullable Class<T> type) {
|
||||
if (Func.hasEmpty(cacheName, keyPrefix, key)) {
|
||||
return null;
|
||||
}
|
||||
return getCache(cacheName).get(keyPrefix.concat(String.valueOf(key)), type);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取缓存
|
||||
*
|
||||
* @param cacheName 缓存名
|
||||
* @param keyPrefix 缓存键前缀
|
||||
* @param key 缓存键值
|
||||
* @param valueLoader 重载对象
|
||||
* @param <T> 类型
|
||||
* @return Cache
|
||||
*/
|
||||
@Nullable
|
||||
public static <T> T get(String cacheName, String keyPrefix, Object key, Callable<T> valueLoader) {
|
||||
if (Func.hasEmpty(cacheName, keyPrefix, key)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final String fullKey = keyPrefix.concat(String.valueOf(key));
|
||||
Cache cache = getCache(cacheName);
|
||||
Cache.ValueWrapper valueWrapper = cache.get(fullKey);
|
||||
|
||||
if (valueWrapper != null) {
|
||||
return (T) valueWrapper.get();
|
||||
}
|
||||
|
||||
try {
|
||||
T value = valueLoader.call();
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
cache.put(fullKey, value);
|
||||
return value;
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置缓存
|
||||
*
|
||||
* @param cacheName 缓存名
|
||||
* @param keyPrefix 缓存键前缀
|
||||
* @param key 缓存键值
|
||||
* @param value 缓存值
|
||||
*/
|
||||
public static void put(String cacheName, String keyPrefix, Object key, @Nullable Object value) {
|
||||
getCache(cacheName).put(keyPrefix.concat(String.valueOf(key)), value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除缓存
|
||||
*
|
||||
* @param cacheName 缓存名
|
||||
* @param keyPrefix 缓存键前缀
|
||||
* @param key 缓存键值
|
||||
*/
|
||||
public static void evict(String cacheName, String keyPrefix, Object key) {
|
||||
if (Func.hasEmpty(cacheName, keyPrefix, key)) {
|
||||
return;
|
||||
}
|
||||
getCache(cacheName).evict(keyPrefix.concat(String.valueOf(key)));
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空缓存
|
||||
*
|
||||
* @param cacheName 缓存名
|
||||
*/
|
||||
public static void clear(String cacheName) {
|
||||
if (Func.isEmpty(cacheName)) {
|
||||
return;
|
||||
}
|
||||
getCache(cacheName).clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -597,4 +597,13 @@ public class DateUtil {
|
|||
return format(LocalDate.now(), "yyyyMMdd");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前小时
|
||||
*
|
||||
* @return 当前小时 (0-23)
|
||||
*/
|
||||
public static Integer hour() {
|
||||
return LocalDateTime.now().getHour();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,9 +16,13 @@
|
|||
package org.springblade.core.datascope.handler;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springblade.core.cache.utils.CacheUtil;
|
||||
import org.springblade.core.datascope.constant.DataScopeConstant;
|
||||
import org.springblade.core.datascope.model.DataScopeModel;
|
||||
import org.springblade.core.tool.utils.*;
|
||||
import org.springblade.core.tool.utils.CollectionUtil;
|
||||
import org.springblade.core.tool.utils.Func;
|
||||
import org.springblade.core.tool.utils.StringPool;
|
||||
import org.springblade.core.tool.utils.StringUtil;
|
||||
import org.springframework.jdbc.core.BeanPropertyRowMapper;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
|
||||
|
|
@ -26,7 +30,7 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static org.springblade.core.tool.utils.CacheUtil.SYS_CACHE;
|
||||
import static org.springblade.core.cache.utils.CacheUtil.SYS_CACHE;
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
|||
13
pom.xml
13
pom.xml
|
|
@ -36,7 +36,7 @@
|
|||
|
||||
<properties>
|
||||
<!-- Blade-Tool Version -->
|
||||
<revision>4.7.1-SNAPSHOT</revision>
|
||||
<revision>4.8.0</revision>
|
||||
<module.name>org.springblade.blade.tool</module.name>
|
||||
<!-- jdk Version -->
|
||||
<java.version>17</java.version>
|
||||
|
|
@ -256,6 +256,17 @@
|
|||
<artifactId>blade-starter-api-crypto</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
<!-- Admin -->
|
||||
<dependency>
|
||||
<groupId>de.codecentric</groupId>
|
||||
<artifactId>spring-boot-admin-starter-server</artifactId>
|
||||
<version>${spring.boot.admin.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.codecentric</groupId>
|
||||
<artifactId>spring-boot-admin-starter-client</artifactId>
|
||||
<version>${spring.boot.admin.version}</version>
|
||||
</dependency>
|
||||
<!-- common -->
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user