程序员scholar 程序员scholar
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
首页
  • Java 基础

    • JavaSE
    • JavaIO
    • JavaAPI速查
  • Java 高级

    • JUC
    • JVM
    • Java新特性
    • 设计模式
  • Web 开发

    • Servlet
    • Java网络编程
  • Web 标准

    • HTML
    • CSS
    • JavaScript
  • 前端框架

    • Vue2
    • Vue3
    • Vue3 + TS
    • 微信小程序
    • uni-app
  • 工具与库

    • jQuery
    • Ajax
    • Axios
    • Webpack
    • Vuex
    • WebSocket
    • 第三方登录
  • 后端与语言扩展

    • ES6
    • Typescript
    • node.js
  • Element-UI
  • Apache ECharts
  • 数据结构
  • HTTP协议
  • HTTPS协议
  • 计算机网络
  • Linux常用命令
  • Windows常用命令
  • SQL数据库

    • MySQL
    • MySQL速查
  • NoSQL数据库

    • Redis
    • ElasticSearch
  • 数据库

    • MyBatis
    • MyBatis-Plus
  • 消息中间件

    • RabbitMQ
  • 服务器

    • Nginx
  • Spring框架

    • Spring6
    • SpringMVC
    • SpringBoot
    • SpringSecurity
  • SpringCould微服务

    • SpringCloud基础
    • 微服务之DDD架构思想
  • 日常必备

    • 开发常用工具包
    • Hutoll工具包
    • IDEA常用配置
    • 开发笔记
    • 日常记录
    • 项目部署
    • 网站导航
    • 产品学习
    • 英语学习
  • 代码管理

    • Maven
    • Git教程
    • Git小乌龟教程
  • 运维工具

    • Docker
    • Jenkins
    • Kubernetes
  • 算法笔记

    • 算法思想
    • 刷题笔记
  • 面试问题常见

    • 十大经典排序算法
    • 面试常见问题集锦
关于
GitHub (opens new window)
npm

(进入注册为作者充电)

  • SpringSecurity

    • Spring Security是什么
    • 认证与授权的基本概念
    • Spring Security 的默认配置
    • SpringSecurity的默认登录页
    • Spring Security 的 Filter 机制
    • HttpSecurity 与自定义登录页面
    • Spring Security 的核心组件与扩展
    • Spring Security 中的用户认证与角色管理
    • Spring Security 的授权机制与安全表达式
      • 1. 基于角色的权限控制
        • 1.1 @PreAuthorize 注解
        • 1.2 @Secured 注解
      • 2. 方法级安全控制
        • 2.1 启用方法级安全控制
        • 2.2 方法级权限控制的使用场景
      • 3. 自定义权限判断逻辑
        • 3.1 使用 SpEL 表达式进行权限判断
        • 3.2 自定义权限表达式
    • Security 的 Session 与 Token 管理
    • Spring Security 集成第三方登录
    • Spring Security 集成 QQ 登录与 JWT 认证
    • Spring Security 登录认证源码
    • Spring Security - JWT认证实战
    • Spring Security - JWT授权实战
    • Spring Security 异常处理与自定义逻辑
  • SpringSecurity
  • SpringSecurity
scholar
2024-08-20
目录

Spring Security 的授权机制与安全表达式

# Spring Security 的授权机制与安全表达式

前言

在 Spring Security 中,授权机制是核心功能之一,通过基于角色和权限的控制,可以确保只有经过认证的用户才能访问特定的资源。除了路径权限控制,Spring Security 还支持基于注解的授权控制、方法级别的安全控制以及自定义的权限判断逻辑。

# 1. 基于角色的权限控制

Spring Security 提供了多种注解用于基于角色和权限的控制,最常用的是 @PreAuthorize 和 @Secured。

# 1.1 @PreAuthorize 注解

@PreAuthorize 是 Spring Security 提供的注解,用于在方法执行前进行权限检查。它支持使用 SpEL(Spring Expression Language)表达式进行权限判断。

代码示例:

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;

@Service
public class MyService {

    @PreAuthorize("hasRole('ADMIN')")  // 只有 ADMIN 角色的用户可以访问此方法
    public void adminMethod() {
        // 管理员权限才能执行的逻辑
    }

    @PreAuthorize("hasAnyRole('USER', 'ADMIN')")  // USER 或 ADMIN 角色的用户可以访问此方法
    public void userOrAdminMethod() {
        // 用户或管理员都可以执行的逻辑
    }

    @PreAuthorize("hasAuthority('READ_PRIVILEGE')")  // 具有特定权限的用户可以访问此方法
    public void readPrivilegeMethod() {
        // 具有读取权限的用户才能执行的逻辑
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

重要参数说明:

  • hasRole('ROLE_NAME'):检查用户是否具有指定角色。Spring Security 会为角色自动添加 ROLE_ 前缀,所以 hasRole('ADMIN') 实际上匹配的是 ROLE_ADMIN。
  • hasAnyRole('ROLE1', 'ROLE2'):检查用户是否具有多个角色中的任意一个。
  • hasAuthority('AUTHORITY_NAME'):检查用户是否具有指定权限,与角色不同,权限更细粒度。

使用场景: 当需要对服务层方法进行权限控制时,通过 @PreAuthorize 可以方便地实现基于角色和权限的访问控制。

# 1.2 @Secured 注解

@Secured 是另一个用于角色控制的注解,与 @PreAuthorize 类似,但它不支持 SpEL 表达式,只能用于简单的角色检查。

代码示例:

import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Service;

@Service
public class MyService {

    @Secured("ROLE_ADMIN")  // 只有 ADMIN 角色的用户可以访问此方法
    public void adminMethod() {
        // 管理员权限才能执行的逻辑
    }

    @Secured({"ROLE_USER", "ROLE_ADMIN"})  // USER 或 ADMIN 角色的用户可以访问此方法
    public void userOrAdminMethod() {
        // 用户或管理员都可以执行的逻辑
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

重要参数说明:

  • @Secured:指定允许访问该方法的角色。支持单个角色或多个角色,多个角色时用数组表示。

使用场景: 适用于只需要简单角色控制的场景,尤其是无需复杂权限表达式的场合。

# 2. 方法级安全控制

除了在路径上进行权限控制外,Spring Security 还支持在方法级别进行权限控制,特别是在服务层或业务逻辑层,通过注解可以实现细粒度的访问控制。

# 2.1 启用方法级安全控制

要使用方法级别的安全控制,需要在配置类中启用相关功能:

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)  // 启用 @PreAuthorize 和 @Secured 注解
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    // 其他安全配置
}
1
2
3
4
5
6
7
8
9

重要参数说明:

  • prePostEnabled = true:启用 @PreAuthorize 和 @PostAuthorize 注解,用于方法级别的权限控制。
  • securedEnabled = true:启用 @Secured 注解,用于方法级别的角色控制。

# 2.2 方法级权限控制的使用场景

  • 服务层安全:在服务层方法上使用注解可以确保只有具备特定角色或权限的用户才能执行关键业务逻辑。
  • 业务逻辑权限细化:例如,一个用户只有在具备特定权限时才能访问某些功能,而不仅仅是基于路径的权限控制。

# 3. 自定义权限判断逻辑

在实际应用中,可能需要根据复杂的业务逻辑进行权限判断,这时可以自定义权限表达式。

# 3.1 使用 SpEL 表达式进行权限判断

@PreAuthorize 支持使用 SpEL 表达式来实现复杂的权限控制逻辑。

代码示例:

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;

@Service
public class MyService {

    @PreAuthorize("#username == authentication.name")  // 仅允许当前用户访问自己的信息
    public void accessOwnData(String username) {
        // 只有当前用户可以访问自己的数据
    }

    @PreAuthorize("#user.id == principal.id or hasRole('ADMIN')")  // 用户可以访问自己的数据,管理员可以访问所有数据
    public void accessData(User user) {
        // 复杂的权限控制逻辑
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

重要参数说明:

  • #username == authentication.name:比较方法参数和当前认证对象的用户名,确保用户只能访问自己的信息。
  • principal.id:principal 是当前认证对象,可以通过它获取用户的详细信息。

# 3.2 自定义权限表达式

可以通过自定义 PermissionEvaluator 或 MethodSecurityExpressionHandler 实现更复杂的权限控制。

自定义 PermissionEvaluator 示例:

import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.core.Authentication;
import java.io.Serializable;

public class CustomPermissionEvaluator implements PermissionEvaluator {

    @Override
    public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) {
        // 实现自定义权限判断逻辑
        if (targetDomainObject instanceof Document) {
            Document document = (Document) targetDomainObject;
            return document.getOwner().equals(authentication.getName()) || authentication.getAuthorities().contains(new SimpleGrantedAuthority("ROLE_ADMIN"));
        }
        return false;
    }

    @Override
    public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
        // 另一种方式的权限判断
        return false;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

配置自定义权限表达式:

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

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

    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();
        expressionHandler.setPermissionEvaluator(new CustomPermissionEvaluator());
        return expressionHandler;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

使用场景: 当权限控制逻辑涉及复杂的业务规则(如多重条件判断)时,可以通过自定义权限表达式实现。

总结

  • 基于角色的权限控制:通过 @PreAuthorize 和 @Secured 注解可以实现路径和方法级别的角色和权限控制,适用于简单到中等复杂度的权限需求。
  • 方法级安全控制:启用方法级安全后,可以对服务层方法进行精细化权限控制,确保业务逻辑的安全性。
  • 自定义权限判断逻辑:对于复杂的业务权限需求,可以通过 SpEL 表达式和自定义权限表达式实现灵活的权限控制。
编辑此页 (opens new window)
上次更新: 2024/12/28, 18:32:08
Spring Security 中的用户认证与角色管理
Security 的 Session 与 Token 管理

← Spring Security 中的用户认证与角色管理 Security 的 Session 与 Token 管理→

Theme by Vdoing | Copyright © 2019-2025 程序员scholar
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式