Spring Security 中的权限注解很神奇吗?

本文探讨了Spring Security中的@PreAuthorize权限注解的使用,通过讲解SpEL(Spring Expression Language)来帮助理解其工作原理。文章首先介绍了SpEL的基础知识,包括表达式的解析和执行,以及如何在表达式中引用对象和调用方法。接着,文章详细解释了@PreAuthorize注解的权限检查流程,涉及到Spring Security的FilterSecurityInterceptor和PreInvocationAuthorizationAdviceVoter。最后,文章强调了学习SpEL的重要性,以便更好地理解和利用Spring Security的注解授权。

最近有个小伙伴在微信群里问 Spring Security 权限注解的问题:

很多时候事情就是这么巧,松哥最近在做的 tienchin 也是基于注解来处理权限问题的,所以既然大家有这个问题,咱们就一块来聊聊这个话题。

当然一些基础的知识我就不讲了,对于 Spring Security 基本用法尚不熟悉的小伙伴,可在公众号后台回复 ss,有原创的系列教程。

1. 具体用法

先来看看 Spring Security 权限注解的具体用法,如下:

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

类似于上面这样,意思就是说,当前用户需要具备 tienchin:channel:query 权限,才能执行当前的接口方法。

那么要搞明白 @PreAuthorize 注解的原理,我觉得得从两个方面入手:

  • 首先明白 Spring 中提供的 SpEL。
  • 其次搞明白 Spring Security 中对方法注解的处理规则。

我们一个一个来看。

2. 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 对象,

一直想做一款后台管理系统,看了很多优秀的开源项目但是发现没有合适自己的。于是利用空闲休息时间开始自己写一套后台系统。如此有了若依管理系统。她可以用于所有的Web应用程序,如网站管理后台,网站会员中心,CMS,CRM,OA。所有前端后台代码封装过后十分精简易上手,出错效率低。同时支持移动客户端访问。系统会陆续更新一些实用功能。 您是否在找一套合适后台管理系统。 您是否在找一套代码易读易懂后台管理系统。 那么,现在若依来了。诚意奉献之作 若依是给刚出生的女儿取的名字 寓意:你若不离不弃,我必生死相依 内置功能 用户管理:用户是系统操作者。 部门管理:配置系统组织机构。 岗位管理:岗位是用户所属职务。 菜单管理:配置系统菜单(支持控制到按钮)。 角色管理:角色菜单权限分配。 字典管理:对系统中经常使用的一些较为固定的数据进行维护。 操作日志:系统操作日志记录(含异常)。 登录日志:系统登录情况记录(含异常)。 在线用户:当前系统中活跃用户状态监控。 连接池监视:监视当期系统数据库连接池状态,可进行分析SQL找出系统性能瓶颈。 为何选择若依 是一个完全响应式,基于Bootstrap3.3.6最新版本开发的主题。 她可以用于所有的Web应用程序,如网站管理后台,网站会员中心,CMS,CRM,OA。 拥有良好的代码结构,层次结构清晰。内置一系列基础功能。 操作权限控制精密细致,对所有管理链接都进行权限验证,可控制到按钮。 提供在线功能代码生成工具,提高开发效率及质量。 提供常用工具类封装,日志、国际化、缓存、验证、字典等数据。 兼容目前最流行浏览器(IE7+、Chrome、Firefox)手机移动端也支持。 技术选型 1、后端 核心框架:Spring Boot 安全框架:Apache Shiro 模板引擎:Thymeleaf 持久层框架:MyBatis 数据库连接池:Druid 缓存框架:Ehcache 日志管理:SLF4J 工具类:Apache Commons Fastjson POJO:Lombok 2、前端 框架:Bootstrap 数据表格:Bootstrap Table 客户端验证:JQuery Validation 树结构控件:zTree 弹出层:layer 3、平台 服务器中间件:SpringBoot内置 数据库支持:目前仅提供MySql数据库的支持,但不限于数据库 开发环境:Java、Eclipse、Maven、Git
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值