”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > Spring 中使用 @Secured 注解的方法安全性

Spring 中使用 @Secured 注解的方法安全性

发布于2024-07-31
浏览:569

Method security with @Secured Annotation in Spring

该注解提供了一种向业务方法添加安全配置的方法。

它将使用角色来检查用户是否有权调用此方法。注解是 Spring Security 的一部分。因此,要启用它的使用,您需要 spring security 依赖项。

示例场景

您有一个包含产品 CRUD 的应用程序。在此 CRUD 中,您希望使用两个特定角色来控制操作。

  • 用户:可以创建产品并查看产品。但无法更新或删除产品。
  • 管理员:可以进行所有用户操作,还可以更新和删除产品。

您可以使用@Secured 来管理这些角色对每个操作的访问权限。

运营角色

我们可以在示例场景中定义以下角色。

  • ROLE_USER、ROLE_ADMIN

读书:

  • ROLE_USER、ROLE_ADMIN

更新:

  • ROLE_ADMIN

删除:

  • ROLE_ADMIN

让我们看一个代码示例并观察应用程序的行为。

添加 Spring Security 依赖

要使用 @Secured 注释,请添加 Spring Security 的 Maven 依赖项:


    org.springframework.boot
    spring-boot-starter-security

使用@Secured注释方法

我们使用 @Secured 注释方法,定义哪些角色可以访问方法行为。

public class Product {

    private Long id;
    private String name;
    private BigDecimal value;

    //getters and setters
}

@Service
public class ProductService {

    @Secured({"ROLE_USER", "ROLE_ADMIN"})
    public Product createProduct(Product product) {
        // Logic for creating a product
        return product;
    }

    @Secured({"ROLE_USER", "ROLE_ADMIN"})
    public Product getProductById(Long id) {
        // Logic for fetching a product
        return null;
    }

    @Secured("ROLE_ADMIN")
    public Product updateProduct(Product product) {
        // Logic for updating a product
        return product;
    }

    @Secured("ROLE_ADMIN")
    public void deleteProduct(Long id) {
        // Logic for deleting a product
    }
}

应用配置

您需要添加@EnableGlobalMethodSecurity(securedEnabled = true)来配置您的Spring应用程序以使用@Secured启用方法安全性。

@SpringBootApplication
@EnableTransactionManagement
@EnableGlobalMethodSecurity(securedEnabled = true)
public class MasteryApplication {

    public static void main(String[] args) {
        SpringApplication.run(MasteryApplication.class, args);
    }

}

测试行为

在我们的示例中,我们将使用测试来测试行为,因此我们添加 spring boot 测试依赖项。


    org.springframework.security
    spring-security-test
    test


然后我们创建测试来验证是否使用模拟用户并为其分配特定角色,我们可以测试每个角色中的用户以及我们的应用程序的行为方式。通过这样做,我们可以确保只有正确的角色才能执行允许的操作。

@SpringBootTest
class ProductServiceTests {

    @Autowired
    private ProductService productService;

    @Test
    @WithMockUser(roles = "USER")
    void testCreateProductAsUser() {
        Product product = new Product();
        assertDoesNotThrow(() -> productService.createProduct(product));
    }

    @Test
    @WithMockUser(roles = "ADMIN")
    void testCreateProductAsAdmin() {
        Product product = new Product();
        assertDoesNotThrow(() -> productService.createProduct(product));
    }

    @Test
    @WithAnonymousUser
    void testCreateProductAsAnonymous() {
        Product product = new Product();
        assertThrows(AccessDeniedException.class, () -> productService.createProduct(product));
    }

    @Test
    @WithMockUser(roles = "USER")
    void testGetProductByIdAsUser() {
        assertDoesNotThrow(() -> productService.getProductById(1L)); // Assuming product with ID 1 exists
    }

    @Test
    @WithMockUser(roles = "ADMIN")
    void testGetProductByIdAsAdmin() {
        assertDoesNotThrow(() -> productService.getProductById(1L));
    }

    @Test
    @WithAnonymousUser
    void testGetProductByIdAsAnonymous() {
        assertThrows(AccessDeniedException.class, () -> productService.getProductById(1L));
    }

    @Test
    @WithMockUser(roles = "USER")
    void testUpdateProductAsUser() {
        Product product = new Product();
        assertThrows(AccessDeniedException.class, () -> productService.updateProduct(product));
    }

    @Test
    @WithMockUser(roles = "ADMIN")
    void testUpdateProductAsAdmin() {
        Product product = new Product();
        assertDoesNotThrow(() -> productService.updateProduct(product));
    }

    @Test
    @WithAnonymousUser
    void testUpdateProductAsAnonymous() {
        Product product = new Product();
        assertThrows(AccessDeniedException.class, () -> productService.updateProduct(product));
    }

    @Test
    @WithMockUser(roles = "USER")
    void testDeleteProductAsUser() {
        assertThrows(AccessDeniedException.class, () -> productService.deleteProduct(1L));
    }

    @Test
    @WithMockUser(roles = "ADMIN")
    void testDeleteProductAsAdmin() {
        assertDoesNotThrow(() -> productService.deleteProduct(1L));
    }

    @Test
    @WithAnonymousUser
    void testDeleteProductAsAnonymous() {
        assertThrows(AccessDeniedException.class, () -> productService.deleteProduct(1L));
    }
}

就是这样,现在您可以使用带有 @Secured 注释的角色来管理用户对应用程序的访问。

如果你喜欢这个话题,记得关注我。在接下来的几天里,我将详细解释 Spring 注解!敬请关注!

跟我来!

版本声明 本文转载于:https://dev.to/tiuwill/method-security-with-secured-annotation-in-spring-1hgk?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 为什么在 C 语言中从字符中减去“0”会显示其数值?
    为什么在 C 语言中从字符中减去“0”会显示其数值?
    解码字符值:为什么减去“0”会泄露数字表示出现一个令人费解的问题:为什么从a中减去“0” C 中的字符揭示了它所代表的数值?为了解开这个谜团,让我们深入研究一下ASCII(美国信息交换标准代码)领域,它为每个字符分配数字代码。 '0' 保留此数字序列中的第一个位置,后续字符逐渐分配更...
    编程 发布于2024-12-21
  • 如何在 PHP 中组合两个关联数组,同时保留唯一 ID 并处理重复名称?
    如何在 PHP 中组合两个关联数组,同时保留唯一 ID 并处理重复名称?
    在 PHP 中组合关联数组在 PHP 中,将两个关联数组组合成一个数组是一项常见任务。考虑以下请求:问题描述:提供的代码定义了两个关联数组,$array1 和 $array2。目标是创建一个新数组 $array3,它合并两个数组中的所有键值对。 此外,提供的数组具有唯一的 ID,而名称可能重合。要求...
    编程 发布于2024-12-21
  • 如何启用和禁用MySQL查询审计一小时?
    如何启用和禁用MySQL查询审计一小时?
    在 MySQL 中启用查询审核如果您希望监控并记录在 MySQL 数据库上执行的所有查询一个小时,您可以可以打开审核日志记录。审核日志记录配置启用审核日志记录和转储将日志写入文件,请在 MySQL 控制台中执行以下命令:SET global log_output = 'FILE'; SET glob...
    编程 发布于2024-12-21
  • 如何使用 JavaScript 创建可悬停的选择框选项?
    如何使用 JavaScript 创建可悬停的选择框选项?
    可悬停选择框选项当前的问题涉及创建一个选择框,当将字段悬停在该选择框上时,选项说明可见,而不是单击打开options.实现为了实现此功能,我们利用了 JavaScript 方法:如下:$('#selectUl li:not(":first")').addClass('unsele...
    编程 发布于2024-12-21
  • 解析 JSON 数据时如何解决“TypeError:字符串索引必须是整数”?
    解析 JSON 数据时如何解决“TypeError:字符串索引必须是整数”?
    避免“TypeError:字符串索引必须是整数”当尝试将 JSON 文件中的数据转换为可理解的 CSV 格式时,您可能会遇到“TypeError:字符串索引必须是整数”错误。当像字典一样访问字符串的字段时,会出现此错误。让我们探索解决方案。理解错误要理解该错误,需要注意的是,Python 中的字符串...
    编程 发布于2024-12-21
  • Bootstrap 4 Beta 中的列偏移发生了什么?
    Bootstrap 4 Beta 中的列偏移发生了什么?
    Bootstrap 4 Beta:列偏移的删除和恢复Bootstrap 4 在其 Beta 1 版本中引入了重大更改柱子偏移了。然而,随着 Beta 2 的后续发布,这些变化已经逆转。从 offset-md-* 到 ml-auto在 Bootstrap 4 Beta 1 中, offset-md-*...
    编程 发布于2024-12-21
  • 如何使用 jQuery 禁用和启用输入字段?
    如何使用 jQuery 禁用和启用输入字段?
    使用 jQuery 禁用和启用输入字段使用 HTML 表单元素时,通常需要为用户禁用或启用某些输入字段相互作用。 jQuery 提供了多种方法来完成这些任务。禁用输入字段在 jQuery 版本 1.6 及更高版本中禁用输入字段的首选方法是通过 prop( ) function:$("inp...
    编程 发布于2024-12-21
  • 在 Go 中对 App Engine 模板进行单元测试时如何解决路径问题?
    在 Go 中对 App Engine 模板进行单元测试时如何解决路径问题?
    如何在 Go 的单元测试中解决 App Engine 模板的路径规范使用 App Engine 和 Go 时,使用内置模板包可能会遇到挑战在单元测试期间。具体来说,该问题是由于服务器无法在测试环境中找到模板文件的路径而出现的。问题原因在常规应用程序执行期间,当前目录是 app.yaml 所在的应用程...
    编程 发布于2024-12-21
  • 在 Go 中使用 WebSocket 进行实时通信
    在 Go 中使用 WebSocket 进行实时通信
    构建需要实时更新的应用程序(例如聊天应用程序、实时通知或协作工具)需要比传统 HTTP 更快、更具交互性的通信方法。这就是 WebSockets 发挥作用的地方!今天,我们将探讨如何在 Go 中使用 WebSocket,以便您可以向应用程序添加实时功能。 在这篇文章中,我们将介绍: WebSocke...
    编程 发布于2024-12-21
  • 除了“if”语句之外:还有哪些地方可以在不进行强制转换的情况下使用具有显式“bool”转换的类型?
    除了“if”语句之外:还有哪些地方可以在不进行强制转换的情况下使用具有显式“bool”转换的类型?
    无需强制转换即可上下文转换为 bool您的类定义了对 bool 的显式转换,使您能够在条件语句中直接使用其实例“t”。然而,这种显式转换提出了一个问题:“t”在哪里可以在不进行强制转换的情况下用作 bool?上下文转换场景C 标准指定了四种值可以根据上下文转换为的主要场景bool:语句:if、whi...
    编程 发布于2024-12-21
  • 如何在 PHP 中求和日期间隔?
    如何在 PHP 中求和日期间隔?
    在 PHP 中添加日期间隔在 PHP 中,我们可能会遇到需要添加两个或多个日期间隔来计算以小时和分钟为单位的总持续时间的情况。要实现此总和,我们可以按照以下步骤操作:为每个时间间隔创建 DateTime 对象。使用 diff() 方法计算每对对象之间的差异。 $a = new DateTime('1...
    编程 发布于2024-12-21
  • 如何使用 jQuery 检索“data-id”属性值?
    如何使用 jQuery 检索“data-id”属性值?
    使用 jQuery 访问 data-id 属性使用 jQuery Quicksand 插件时,通常需要检索被单击元素的“data-id”属性将信息传递到各种 Web 服务。下面介绍如何有效获取该属性值:'data-id'属性可以使用jQuery中的.attr()方法来访问。语法如下:...
    编程 发布于2024-12-21
  • 如何通过一次查询高效删除多个MySQL表中的数据?
    如何通过一次查询高效删除多个MySQL表中的数据?
    在 MySQL 中使用单个查询从多个表中删除数据当处理由公共字段关联的多个表时,可能需要删除有关用户的信息同时从所有表中。此查询不是执行多个 DELETE 语句,而是探索在单个查询中执行删除的可能性。建议的查询涉及使用以分号分隔的多个 DELETE 语句:DELETE FROM table1 WHE...
    编程 发布于2024-12-21
  • 如何使用 Intent.putExtra() 在 Activity 之间发送整数数组?
    如何使用 Intent.putExtra() 在 Activity 之间发送整数数组?
    使用 Intent.putExtra() 发送数组在 Activity 之间传输数据时,可能需要传递数组等复杂的数据结构。本文探讨如何使用 Intent.putExtra() 有效地将整数数组从一个活动 (A) 发送到另一个活动 (B)。问题:In活动 A 中,初始化了一个整数数组,并打算将其发送到...
    编程 发布于2024-12-21
  • 如何强制浏览器刷新动态图像以显示更新?
    如何强制浏览器刷新动态图像以显示更新?
    使用 Cachebreaker 进行动态图像刷新访问每次加载时提供新图像的动态图像源时,强制刷新至关重要在网页上显示更新后的图像。在后台加载新图像并尝试替换页面上的现有图像时会出现此问题。尽管加载了新图像,但在刷新页面之前它可能不会显示。要解决此问题,可以将缓存破坏器附加到图像 URL 的末尾:ne...
    编程 发布于2024-12-21

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3