首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Spring Security 基于表达式的权限控制:内置表达式、3种应用示例

这几天好忙呀!

忙的时候有点烦躁(别来惹我!),闲的时候又有点发慌(都来惹我呀!),哈哈!

最近在忙增删改查,为了节约代码,一个控制器供好几个菜单访问,这就用到了权限控制,想不起来用哪个表达式,来,一起翻一下。

Spring Security 提供了基于 Spring 表达式语言 (Spring EL) 的权限控制能力,可用于 URL 访问、方法调用等场景,支持灵活的动态权限校验。主要内容包括:URL 权限控制、方法权限控制、自定义表达式扩展等。

先来看内置表达式有哪些?

一、内置表达式

在Spring Security框架中,SecurityExpressionRoot(安全表达式基类)提供了一些内置表达式。

这些内置表达式可以拿来即用,不需要额外配置。

接下来看应用。

二、URL 权限控制

通过HttpSecurity对象配置 URL 权限控制。启用表达式支持后,可以结合用户角色、IP 地址等条件进行细粒度的权限校验。

1、基本配置

配置示例:允许具有ROLE_USER角色的用户访问所有 URL。

@Overrideprotected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/**").access("hasRole('ROLE_USER')") .and() .formLogin() .and() .logout();}

2、基于 IP 地址的访问控制

允许特定 IP 地址的用户访问资源:

@Overrideprotected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/**").hasIpAddress("192.168.0.15") .and() .formLogin() .and() .logout();}

3、案例:基于子网的访问控制

允许192.168.1.0/24网段内的用户访问:

@Overrideprotected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/**").hasIpAddress('192.168.1.0/24') .and() .formLogin() .and() .logout();}

三、 方法权限控制

Spring Security 提供了 4 种注解,用于在方法级别实现权限控控制@PreAuthorize、@PostAuthorize、@PreFilter、@PostFilter。

3.1 方法调用前的权限校验

@PreAuthorize用于在方法调用前进行权限检查。

案例 1:基于角色的权限控制

仅允许具有ROLE_ADMIN角色的用户调用addUser方法。

@RestControllerpublic class UserController { @PreAuthorize("hasRole('ROLE_ADMIN')") public void addUser(User user) { // 添加用户逻辑 }}

如果匹配的权限为ROLE_ADMIN 或 ROLE_ADMIN1,可以使用hasAnyRole('ROLE_ADMIN','ROLE_ADMIN1') 或hasRole('ROLE_ADMIN') or hasRole('ROLE_ADMIN1')。

案例 2:基于参数的权限控制

限制只能查询 ID 小于 10 的用户。

@RestControllerpublic class UserController { @PreAuthorize("#id < 10") public User findUserById(int id) { return new User(id); }}

3.2 方法调用后的权限校验

@PostAuthorize用于在方法执行完成后对返回结果进行权限检查。

案例:检查返回结果,仅当返回对象的 ID 为偶数时允许访问。

@PostAuthorize("returnObject.id % 2 == 0")public User getUser(int id) { return new User(id);}

3.3 集合过滤

使用@PreFilter和@PostFilter对集合类型的参数或返回值进行过滤。

案例:返回结果过滤,仅返回 ID 为偶数的用户。

@PostFilter("filterObject.id % 2 == 0")public List<User> getUsers() { return List.of(new User(1), new User(2), new User(3), new User(4));}

四、 自定义权限表达式

如果内置的表达式无法满足需求,可以通过实现PermissionEvaluator接口来自定义权限逻辑。

1、实现自定义 PermissionEvaluator

以下代码实现了简单的字符串匹配逻辑:

@Configurationpublic class MyPermissionEvaluator implements PermissionEvaluator { @Override public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) { boolean accessable = false; //匿名访问时,无权限 if(authentication.getPrincipal().toString().compareToIgnoreCase("anonymousUser") != 0){ //中间用冒号分隔 String privilege = targetDomainObject + ":" + permission; for(GrantedAuthority authority : authentication.getAuthorities()){ if(privilege.equalsIgnoreCase(authority.getAuthority())){ accessable = true; break; } } return accessable; } return accessable; } /** * 总是认为有权限返回true,否则返回false */ @Override public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) { return false; }}

2、应用自定义表达式

在方法级别使用自定义表达式:

@PreAuthorize("hasPermission('user', 'ROLE_USER')")public User getUser(int id) { return new User(id);}

最后总结

Spring Security 的基于表达式的权限控制功能强大而灵活,可通过内置与自定义表达式满足复杂权限需求。

时间匆忙,稍微整理一下,有些示例代码还需要交给时间检验。

  • 发表于:
  • 原文链接https://page.om.qq.com/page/OiMprxcld8hMv_3nnuwAv7qA0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券