Spring Security 中,想在权限中使用通配符,怎么做?

若依前后端分离框架学习-5:权限管理     上一章自己创建了一个模块,我们注意到前端代码中对于按钮有v-hasPermi="[‘xxx:testxxx:add’]“这种代码。服务端有@PreAuthorize(”@ss.hasPermi(‘xxx:testxxx:add’)")这种代码。这是为了分别在前端和服务端限制用户进行非权限操作的。接下来,我们举个例子进行具体分析。     我们来看“新增”按钮对应的前端代码: <el-col :span="1.5" 阅读详情

小伙伴们知道,在 Shiro 中,默认是支持权限通配符的,例如系统用户有如下一些权限:

  • system:user:add
  • system:user:delete
  • system:user:select
  • system:user:update
  • ...

现在给用户授权的时候,我们可以像上面这样,一个权限一个权限的配置,也可以直接用通配符:

  • system:user:*

这个通配符就表示拥有针对用户的所有权限。

当然这是 Shiro 里边的,对 Shiro 不熟悉的小伙伴,可以在公众号后台回复 shiro,查看松哥之前录的视频教程。

今天我们来聊聊 Spring Security 中对此如何处理,也顺便来看看 TienChin 项目中,这块该如何改进。

1. SpEL

要搞明白基于注解的权限管理,那么得首先理解 SpEL,不需要了解多深入,我这里就简单介绍下。

Spring Expression Language(简称 SpEL)是一个支持查询和操作运行时对象导航图功能的强大的表达式语言。它的语法类似于传统 EL,但提供额外的功能,最出色的就是函数调用和简单字符串的模板函数。

SpEL 给 Spring 社区提供一种简单而高效的表达式语言,一种可贯穿整个 Spring 产品组的语言。这种语言的特性基于 Spring 产品的需求而设计,这是它出现的一大特色。

在我们离不开 Spring 框架的同时,其实我们也已经离不开 SpEL 了,因为它太好用、太强大了,SpEL 在整个 Spring 家族中也处于一个非常重要的位置。但是很多时候,我们对它的只了解一个大概,其实如果你系统的学习过 SpEL,那么上面 Spring Security 那个注解其实很好理解。

我先通过一个简单的例子来和大家捋一捋 SpEL。

为了省事,我就创建一个 Spring Boot 工程来和大家演示,创建的时候不用加任何额外的依赖,就最最基础的依赖即可。

代码如下:

String expressionStr = "1 + 2";
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression(expressionStr);

expressionStr 是我们自定义的一个表达式字符串,这个字符串通过一个 ExpressionParser 对象将之解析为一个 Expression,接下来就可以执行这个 exp 了。

执行的时候有两种方式,对于我们上面这种不带任何额外变量的,我们可以直接执行,直接执行的方式如下:

Object value = exp.getValue();
System.out.println(value.toString());

这个打印结果为 3。

我记得之前有个小伙伴在群里问想执行一个字符串表达式,但是不知道怎么办,js 中有 eval 函数很方便,我们 Java 中也有 SpEL,一样也很方便。

不过很多时候,我们要执行的表达式可能比较复杂,这时候上面这种调用方式就不太够用了。

此时我们可以为要调用的表达式设置一个上下文环境,这个时候就会用到 EvaluationContext 或者它的子类,如下:

StandardEvaluationContext context = new StandardEvaluationContext();
System.out.println(exp.getValue(context));

当然上面这个表达式不需要设置上下文环境,我举一个需要设置上下文环境的例子。

例如我现在有一个 User 类,如下:

public class User {
    private Integer id;
    private String username;
    private String address;
    //省略 getter/setter
}

现在我的表达式是这样:

String expression = "#user.username";
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression(expression);
StandardEvaluationContext ctx = new StandardEvaluationContext();
User user = new User();
user.setAddress("广州");
user.setUsername("javaboy");
user.setId(99);
ctx.setVariable("user", user);
String value = exp.getValue(ctx, String.class);
System.out.println("value = " + value);

这个表达式就表示获取 user 对象的 username 属性。将来创建一个 user 对象,放到 StandardEvaluationContext 中,并基于此对象执行表达式,就可以打印出来想要的结果。

如果我们将 user 对象设置为 rootObject,那么表达式中就不需要 user 了,如下:

String expression = "username";
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression(expression);
StandardEvaluationContext ctx = new StandardEvaluationContext();
User user = new User();
user.setAddress("广州");
user.setUsername("javaboy");
user.setId(99);
ctx.setRootObject(user);
String value = exp.getValue(ctx, String.class);
System.out.println("value = " + value);

表达式就一个 username 字符串,将来执行的时候,会自动从 user 中找到 username 的值并返回。

当然表达式也可以是方法,例如我在 User 类中添加如下两个方法:

public String sayHello(Integer age) {
    return "hello " + username + ";age=" + age;
}
public String sayHello() {
    return "hello " + username;
}

我们就可以通过表达式调用这两个方法,如下:

调用有参的 sayHello:

String expression = "sayHello(99)";
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression(expression);
StandardEvaluationContext ctx = new StandardEvaluationContext();
User user = new User();
user.setAddress("广州");
user.setUsername("javaboy");
user.setId(99);
ctx.setRootObject(user);
String value = exp.getValue(ctx, String.class);
System.out.println("value = " + value);

就直接写方法名然后执行就行了。

调用无参的 sayHello:

String expression = "sayHello";
ExpressionParser parser = new SpelExpressionParser();
Expression exp = parser.parseExpression(expression);
StandardEvaluationContext ctx = new StandardEvaluationContext();
User user = new User();
user.setAddress("广州");
user.setUsername("javaboy");
user.setId(99);
ctx.setRootObject(user);
String value = exp.getValue(ctx, String.class);
System.out.println("value = " + value);

这些就都好懂了。

甚至,我们的表达式也可以涉及到 Spring 中的一个 Bean,例如我们向 Spring 中注册如下 Bean:

@Service("us")
public class UserService {
    public String sayHello(String name) {
        return "hello " + name;
    }
}

然后通过 SpEL 表达式来调用这个名为 us 的 bean 中的 sayHello 方法,如下:

@Autowired
BeanFactory beanFactory;
@Test
void contextLoads() {
    String expression = "@us.sayHello('javaboy')";
    ExpressionParser parser = new SpelExpressionParser();
    Expression exp = parser.parseExpression(expression);
    StandardEvaluationContext ctx = new StandardEvaluationContext();
    ctx.setBeanResolver(new BeanFactoryResolver(beanFactory));
    String value = exp.getValue(ctx, String.class);
    System.out.println("value = " + value);
}

给配置的上下文环境设置一个 bean 解析器,这个 bean 解析器会自动跟进名字从 Spring 容器中找打响应的 bean 并执行对应的方法。

当然,关于 SpEL 的玩法还有很多,我就不一一列举了。这里主要是想让小伙伴们知道,有这么个技术,方便大家理解 @PreAuthorize 注解的原理。

总结一下:

  1. 在使用 SpEL 的时候,如果表达式直接写的就是方法名,那是因为在构建 SpEL 上下文的时候,已经设置了 RootObject 了,我们所调用的方法,实际上就是 RootObject 对象中的方法。
  2. 在使用 SpEL 对象的时候,如果像调用非 RootObject 对象中的方法,那么表达式需要加上 @对象名 作为前缀,例如前面案例的 @us。

2. 自定义权限该如何写

那么自定义权限到底该如何写呢?首先我们来看下在 Spring Security 中,不涉及到通配符的权限该怎么处理。

松哥举一个简单的例子,我们创建一个 Spring Boot 工程,引入 Web 和 Security 依赖,为了方便,这里的用户我直接创建在内存中,配置如下:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig {

    @Bean
    UserDetailsService userDetailsService() {
        InMemoryUserDetailsManager m = new InMemoryUserDetailsManager();
        m.createUser(User.withUsername("javaboy").password("{noop}123").authorities("system:user:add","system:user:delete").build());
        return m;
    }

    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http.authorizeRequests().anyRequest().authenticated()
                .and()
                .formLogin()
                .permitAll();
        return http.build();
    }

}

都是常规配置,没啥好说的。注意前面的注解,开启基于注解的权限控制。

这里我多啰嗦一句,大家看创建用户的时候,调用的是 authorities 方法去设置权限的,这个跟 roles 方法其实没啥大的区别,调用 roles 方法会自动为你设置的字符串添加一个 ROLE_ 前缀,其他的其实都一样。在 Spring Security 中,role 和 permission 仅仅只是人为划分出来的东西,底层的实现包括判断逻辑基本上都是没有区别的。

接下来我们定义四个测试接口,如下:

@RestController
public class UserController {

    @GetMapping("/add")
    @PreAuthorize("hasPermission('/add','system:user:add')")
    public String addUser() {
        return "add";
    }
    @GetMapping("/delete")
    @PreAuthorize("hasPermission('/delete','system:user:delete')")
    public String deleteUser() {
        return "delete";
    }
    @GetMapping("/update")
    @PreAuthorize("hasPermission('/update','system:user:update')")
    public String updateUser() {
        return "update";
    }
    @GetMapping("/select")
    @PreAuthorize("hasPermission('/select','system:user:select')")
    public String selectUser() {
        return "select";
    }
}

接口访问都需要不同的权限。

此时如果大家启动项目去此时,系统会提示你四个接口统统都不具备权限,这是啥原因呢?我们来继续分析。

小伙伴们看这里,调用的时候 @PreAuthorize 注解中执行写方法名,不用写对象名,说明调用的方法是 RootObject 中的方法,这里的 RootObject 实际上就是 SecurityExpressionRoot,我们来看看这个对象中的 hasPermission 方法:

@Override
public boolean hasPermission(Object target, Object permission) {
	return this.permissionEvaluator.hasPermission(this.authentication, target, permission);
}
@Override
public boolean hasPermission(Object targetId, String targetType, Object permission) {
	return this.permissionEvaluator.hasPermission(this.authentication, (Serializable) targetId, targetType,
			permission);
}

最终的调用又指向了 permissionEvaluator 对象。

在 Spring Security 中,permissionEvaluator 有一个统一的接口就是 PermissionEvaluator,但是这个接口只有一个实现类,就是 DenyAllPermissionEvaluator,看名字就知道,这是拒绝所有。

public class DenyAllPermissionEvaluator implements PermissionEvaluator {

	private final Log logger = LogFactory.getLog(getClass());

	/**
	 * @return false always
	 */
	@Override
	public boolean hasPermission(Authentication authentication, Object target, Object permission) {
		return false;
	}

	/**
	 * @return false always
	 */
	@Override
	public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType,
			Object permission) {
		return false;
	}

}

这两个方法里啥都没干,直接返回了 false,这下就破案了!

所以,在 Spring Security 中,如果想判断权限,需要自己提供一个 PermissionEvaluator 的实例,我们来看下:

@Component
public class CustomPermissionEvaluator implements PermissionEvaluator {
    @Override
    public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
        for (GrantedAuthority authority : authorities) {
            if (authority.getAuthority().equals(permission)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
        return false;
    }
}

我这里的判断逻辑比较简单,所以只需要实现第一个方法就行了,这个方法三个参数,第一个参数就是当前登录成功的用户对象,后面两个参数则是我们在 @PreAuthorize("hasPermission('/select','system:user:select')") 注解中的两个参数,现在该有的东西都有了,我们只需要判断需要的权限当前用户是否有就行了。

这个自定义的权限评估器写好之后,注册到 Spring 容器就行了,其他什么事情都不用做。

接下来我们就可以对刚才的四个接口进行测试了,测试过程我就不演示了,小伙伴们自行用 postman 测试就行了。

3. 权限通配符

看明白了上面的逻辑,现在不用我说,大家也知道权限通配符在 Spring Security 中是不支持的(无论你在 @PreAuthorize 注解中写的 SpEL 是哪个,调用的是哪个方法,都是不支持权限通配符的)。

例如我现在这样描述我的用户权限:

@Bean
UserDetailsService userDetailsService() {
    InMemoryUserDetailsManager m = new InMemoryUserDetailsManager();
    m.createUser(User.withUsername("javaboy").password("{noop}123").authorities("system:user:*").build());
    return m;
}

我想用 system:user:* 字符串表示 javaboy 具有针对用户的所有权限。

直接这样写肯定是不行的,最终字符串比较一定是不会通过的。

那么怎么办呢?用正则似乎也不太行,因为 * 在正则中不代表所有字符,如果拆解字符串去比较,功能虽然也行得通,但是比较麻烦。

想来想去,想到一个办法,不知道小伙伴们是否还记得我们之前在 vhr 中用过的 AntPathMatcher,用这个不就行了!

修改后的 CustomPermissionEvaluator 如下:

@Component
public class CustomPermissionEvaluator implements PermissionEvaluator {

    AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Override
    public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
        Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
        for (GrantedAuthority authority : authorities) {
            if (antPathMatcher.match(authority.getAuthority(), (String) permission)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
        return false;
    }
}

修改之后,现在只要用户具备 system:user:* 权限,就四个接口都能访问了。

4. TienChin 项目怎么做的?

TienChin 项目用的是 RuoYi-Vue 脚手架,我们来看下这个脚手架的实现方式:

@PreAuthorize("@ss.hasPermi('tienchin:channel:query')")
@GetMapping("/list")
public TableDataInfo getChannelList() {
    startPage();
    List<Channel> list = channelService.list();
    return getDataTable(list);
}

看了前面的讲解,现在 @ss.hasPermi('tienchin:channel:query') 应该很好懂了:

  • ss 是一个注册在 Spring 容器中的 bean,对应的类位于 org.javaboy.tienchin.framework.web.service.PermissionService 中。
  • 很明显,hasPermi 就是这个类中的方法。

这个 hasPermi 方法的逻辑其实很简单:

public boolean hasPermi(String permission) {
    if (StringUtils.isEmpty(permission)) {
        return false;
    }
    LoginUser loginUser = SecurityUtils.getLoginUser();
    if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions())) {
        return false;
    }
    return hasPermissions(loginUser.getPermissions(), permission);
}
private boolean hasPermissions(Set<String> permissions, String permission) {
    return permissions.contains(ALL_PERMISSION) || permissions.contains(StringUtils.trim(permission));
}

这个判断逻辑很简单,就是获取到当前登录的用户,判断当前登录用户的权限集合中是否具备当前请求所需要的权限。具体的判断逻辑没啥好说的,就是看集合中是否存在某个字符串,从判断的逻辑中我们也可以看出来,这个权限也是不支持通配符的。

 

Spring Boot+Spring Security:基于URL动态权限:准备工作 - 第14篇 需求缘起 在上一节说明了几种方案,但是不管是选择哪一种方案,权限持久化相关操作总是少不了的,本节先做下准备工作。 一、准备工作 1.1 创建实体类Permission 创建实体类,用于存储权限的信息: package com.kfit.permission.bean; import java.util.List; import javax.persistence.... 阅读详情

相关推荐

不用标注数据!用SAM 3零成本搞定遥感图像分割:SegEarth-OV3保姆级上手教程

本文介绍了如何利用SAM 3和SegEarth-OV3实现零标注遥感图像分割,提供从环境配置到结果优化的完整教程。通过开放词汇语义分割技术,用户无需标注数据即可快速获得专业级分割结果,适用于光伏板统计、灾害评估等场景。

weixin_30415113的博客 585

springSecurity登录的全过程

整个流程就是:进入接口—>进行验证—>获取用户信息—>创建token—>存入redis—>返回/*** 自定义权限实现,ss取自SpringSecurity首字母*/*** 所有权限标识/*** 管理员角色权限标识/*** 验证用户是否具备某权限** @param permission 权限字符串* @return 用户是否具备某权限System . out . println("拥用这个权限才能通过" + permission);...

XuDream的博客 3538

Opencv4.5.1 微信二维码识别功能 QRCode 编译与使用 C++

部分参考:https://mp.weixin.qq.com/s/2GZAJAUPHTXFOKDRv-D21Q 一、下载源码 https://github.com/opencv 二、源码编译 ① 在cmake中添加源码编译路径和生成路径,第一次点击configure。 ② 添加contrib路径 第一次configure后,找到OPENCV_EXTRA_MODULES_PATH,将contrib路径添加进来,注意要具体到modules/,继续configure。 ..

zaibeijixing的专栏 1万+

权限想要细化到按钮,怎么做?

首先小伙伴们都知道权限有不同的颗粒度,在 vhr 项目中,整体上我是基于请求地址去处理权限的,这个粒度算粗还是算细呢?有的小伙伴们可能认为这个权限粒度太粗,所谓细粒度的权限应该是基于按钮的。如果有小伙伴们做过前后端不分的开发,应该会有这样的体会:在 Shiro 或者 Spring Security 框架中,都提供了一些标签,通过这些标签可以做到在满足某种角色或者权限的情况下,显示某个按钮;当用户不具备某种角色或者权限的时候,按钮则会自动隐藏起来。但是大家想想,按钮的显示与隐藏不过是前端页面为了提高用户体验而

江南一点雨的专栏 3477

CDO批量处理nc文件:5分钟搞定CMIP6数据双线性插值(附完整代码)

本文详细介绍了如何使用CDO工具链中的`remapbil`命令,快速实现CMIP6数据的批量双线性插值处理。通过环境配置、核心操作步骤、高级优化技巧及典型报错解决方案,帮助科研人员高效处理大规模nc文件,显著提升气象数据处理效率。

weixin_29267307的博客 292

车载机器人终极解决方案:从功能叠加到生态融合的颠覆性变革

本文提出一种融合智能汽车与家居技术的车载机器人架构。其创新点包括:1)基于多模态传感器的拟人化硬件设计,实现声源定位误差<5°、体温检测精度±0.3℃;2)跨模态情感计算引擎,综合面部表情、心率等数据构建三维情绪模型;3)协议自适应中间件,支持小米、华为等多品牌智能家居设备即插即用;4)环境自适应舵机控制,-30℃环境下扭矩保持率达92.5%。测试数据显示,该方案使交互步骤减少60%,用户满意度提升58%,日均使用时长增加2.3倍,为"人-车-家"生态融合提供了可行技术路径。

qq_42671193的博客 1125

SpringSecurity从0到1搭建详细教程二——添加权限

SpringSecurity从0到1搭建详细教程二——添加权限(默认写死权限集合)

m0_47743175的博客 605

【AI智能体】Spring AI Tool 从使用到实战详解

Spring AI Tool

congge 5865

SpringSecurity:权限控制

文章目录SpringSecurity:权限控制1 数据准备2 创建 POJO、Mapper、Service3 自定义PermissionEvaluator SpringSecurity:权限控制 1 数据准备 创建 sys_permission 表并插入数据 CREATE TABLE `sys_permission` ( `id` int(11) NOT NULL AUTO_INCREMENT, `url` varchar(255) DEFAULT NULL, `role_id` int(1

拒绝熬夜啊的博客 1523

LVGL v8学习笔记 | 09 - 进度条控件的使用方法(bar)

lv_bar_set_range必须放在lv_bar_set_mode前面,否则不生效。bar对象的API在lv_bar.h中声明,以lv_bar_xxx命名。此事件可以用来在进度条更新值之后更新别的控件(比如进度条旁边的文字)。可以看到,默认创建的进度条值是0到100。(3)设置进度条的范围值(最大值和最小值)(2)获取进度条的起始值。(3)获取进度条的最小值。(4)获取进度条的最大值。(1)设置进度条的当前值。(2)设置进度条的起始值。(1)获取进度条当前值。(5)获取进度条的模式。

Mculover666的博客(嵌入式) 1729

Unity中使用TCP和UDP传输摄像头视频的实践

本文探讨了在Unity中通过TCP和UDP协议传输摄像头视频的实现方法。TCP通过自定义消息帧保证数据完整性但效率较低,UDP传输速度快但可能丢帧。文章提供了Python和Unity的代码示例,分析了两种协议的适用场景:TCP适合要求数据完整性的应用,UDP则适合追求实时性的场景。最终选择取决于具体需求,并需要注意线程安全与同步机制。

m0_74337424的博客 145

Spring Security ,如何在权限中使用通配符?

2022-07-06 13:15·来敲个bug小伙伴们知道,在 Shiro 中,默认是支持权限通配符的,例如系统用户有如下一些权限:现在给用户授权的时候,我们可以像上面这样,一个权限一个权限的配置,也可以直接用通配符:这个通配符就表示拥有针对用户的所有权限。当然这是 Shiro 里边的,对 Shiro 不熟悉的小伙伴,可以在公众号后台回复 shiro,查看松哥之前录的视频教程。今天我们来聊聊 Spring Security 中对此如何处理,也顺便来看看 TienChin 项目中,这块该如何改进。要搞明白基于

vvei777的博客 660

结构优化软件:OptiStruct_(11).拓扑优化

在OptiStruct中,设计空间可以通过定义设计区域来实现。设计区域是结构中可以进行材料变化的部分。几何区域:通过几何选择工具选择特定的区域。网格区域:通过网格选择工具选择特定的单元。假设我们有一个简单的梁结构模型,网格文件为beam.fem。我们希望在梁的中部进行拓扑优化,以减轻重量并保持刚度。

kkchenjj的博客 1367

Spring Security 中如何让上级拥有下级的所有权限?

答案是能! 松哥之前写过类似的文章,但是主要是讲了用法,今天我们来看看原理! 本文基于当前 Spring Security 5.3.4 来分析,为什么要强调最新版呢?因为在在 5.0.11 版中,角色继承配置和现在不一样。旧版的方案我们现在不讨论了,直接来看当前最新版是怎么处理的。 1.角色继承案例 我们先来一个简单的权限案例。 创建一个 Spring Boot 项目,添加 Spring Security 依赖,并创建两个测试用户,如下: @Override protected void configure

江南一点雨的专栏 3591

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

Spring Security- 动态 URL 权限控制的实现思路

Spring Security 动态 URL 权限控制实现 本文介绍了一种基于 Spring Security 的动态 URL 权限控制方案,主要解决传统静态权限配置不灵活的问题。文章包含以下核心内容: 需求背景:传统注解或配置方式无法满足运行时动态调整权限的需求,特别是在多租户、复杂业务场景下。 技术方案: 采用"拦截器+权限决策器"架构 通过自定义 SecurityMetadataSource 从数据库加载权限规则 使用 AccessDecisionManager 进行实时权限验证 实现步骤: 设计 R

千淘万漉虽辛苦,吹尽狂沙始到金 1万+

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Spring Security(17)——基于方法的权限控制

本文主要介绍Spring Security进行方法级别的权限控制的几种手段。包括使用intercept-methods、使用Pointcut、使用JSR-250注解、使用Spring自身定义的@Secured注解、使用支持表达式的注解等,以及在进行方法级别的权限控制时会使用到的一些Advice。

Elim的博客 1万+

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

如何在 Spring Security 中自定义权限表达式

在前面的文章中,松哥已经和小伙伴们聊了 Spring Security 中的权限表达式了,还没看过的小伙伴们可以先看下,本文将在前文的基础上继续完善:经过上篇文章的学习,小伙伴们已经知道了,在 Spring Security 中,@PreAuthorize、@PostAuthorize 等注解都是支持 SpEL 表达式的。在 SpEL 表达式中,如果上来就直接写要执行的方法名,那么就说明这个方法是 RootObject 对象中的方法,如果要执行其他对象的方法,那么还需要写上对象的名字,例如如下两个例子: 上

江南一点雨的专栏 3271

Spring Security—基于方法的权限控制

1.1intercept-methods定义方法权限控制 intercept-methods是需要定义在bean元素下的,通过它可以定义对当前的bean的某些方法进行权限控制,具体方法是使用其下的子元素protect进行定义的。protect元素需要指定两个属性,access和method,method表示需要拦截的方法名称,可以使用通配符,access表示执行对应的方法...

sscout的博客 1219

Spring Security- 动态角色与权限的实时刷新

Spring Security 动态权限实时刷新方案 本文探讨了在企业级应用中实现动态角色与权限实时刷新的技术方案。针对传统静态权限配置的局限性,提出基于Spring Security的动态权限管理方法,核心思路包括: 自定义权限评估器,结合SpEL表达式实现灵活控制 设计RBAC权限模型,将权限数据存储在可变数据源 通过方法级安全注解(@PreAuthorize)实现细粒度控制 创建动态权限服务实时查询用户权限 使用缓存策略优化频繁的权限查询 方案优势在于无需重启服务或重新登录即可实现权限变更秒级生效,满

千淘万漉虽辛苦,吹尽狂沙始到金 1万+

【Spring Security OAuth2】- Security控制授权- Spring Security授权简介

授权又是什么概念呢?你是谁?你能干什么?前面讲解的全是认证,也就是解决你是谁的问题;这章讲解你能干什么的问题。很多人叫权限控制,鉴权,授权等;最终的核心目的都是一样的,控制这个用户能在系统中干什么?上图意思就是说,页面能看到的只是体验和ui交互问题;而对应后台某一个url的是否能被访问被认为是权限。

smart_an的专栏 1122

使用spring进行权限验证的三种方式

这是最直接的方式,通过实现 接口,在请求处理前进行拦截验证。创建拦截器类: 注册拦截器: 适用场景: 基于 Session 的登录验证。 需要细粒度控制拦截路径(支持通配符)。 2. 使用 Servlet 过滤器(Filter) 过滤器(Filter)是 Java Servlet 规范的一部分,可以在请求进入 Spring MVC 前进行拦截。创建过滤器类: 配置过滤器顺序和路径: 适用场景: 需要更底层的控制(在所有 Spring 组件之前拦截)。 处理静态资源或非 Spring

qq_73276037的博客 928

Sa-Token:替代Spring Security的高效Java权限框架

权限认证是系统安全的核心组件,传统方案如Spring Security虽然功能完善但配置复杂。现代权限框架通过注解驱动和智能路由等机制,显著简化了RBAC实现流程。在分布式架构下,高效的会话管理方案能降低60%以上的Redis操作损耗,这对高并发系统尤为重要。Sa-Token作为新兴Java权限框架,通过本地缓存+异步刷新等创新设计,在电商、SaaS等场景中实现了权限热更新和5ms级鉴权响应。相比传统方案,其注解式开发模式可使代码量减少90%,特别适合需要快速迭代的中台项目。

leonard61306500的专栏 669
上一篇: Spring从入门到精通(一)—Spring概述、Spring的优势和体系结构
Java777i
博客等级 码龄4年 1粉丝 4原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值