{"id":236,"date":"2024-07-11T18:11:31","date_gmt":"2024-07-11T21:11:31","guid":{"rendered":"https:\/\/springmasteryhub.com\/?p=236"},"modified":"2024-07-11T18:11:31","modified_gmt":"2024-07-11T21:11:31","slug":"method-security-with-secured-annotation-in-spring","status":"publish","type":"post","link":"https:\/\/springmasteryhub.com\/?p=236","title":{"rendered":"Method security with @Secured Annotation in Spring"},"content":{"rendered":"\n<p>This annotation provides a way to add security configuration to business methods.<\/p>\n\n\n\n<p>It will use roles to check if a user has permission to call this method. The annotation is part of spring security. So to enable its usage you need the spring security dependency.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Example Scenario<\/h2>\n\n\n\n<p>You have an application that has a product CRUD. In this CRUD you want to control the operations using two specific roles.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>User:<\/strong> can create the product and see the product. But cannot update or delete a product.<\/li>\n\n\n\n<li><strong>Admin:<\/strong> that can do all the user operations and can also update and delete a product.<\/li>\n<\/ul>\n\n\n\n<p>You can use @Secured to manage the access of those roles on each operation.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Roles for Operations<\/h3>\n\n\n\n<p>We can define the following roles in our example scenario.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>ROLE_USER, ROLE_ADMIN<\/li>\n<\/ul>\n\n\n\n<p>To read:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>ROLE_USER, ROLE_ADMIN<\/li>\n<\/ul>\n\n\n\n<p>To update:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>ROLE_ADMIN<\/li>\n<\/ul>\n\n\n\n<p>To delete:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>ROLE_ADMIN<\/li>\n<\/ul>\n\n\n\n<p>Let&#8217;s look at a code example and observe the application behavior.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Adding Spring Security Dependency<\/h3>\n\n\n\n<p>To work with the <code>@Secured<\/code> annotation, add the Maven dependency for Spring Security:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n&lt;dependency&gt;\n    &lt;groupId&gt;org.springframework.boot&lt;\/groupId&gt;\n    &lt;artifactId&gt;spring-boot-starter-security&lt;\/artifactId&gt;\n&lt;\/dependency&gt;\n\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Annotating Methods with @Secured<\/h3>\n\n\n\n<p>We annotate the methods with @Secured defining which roles can access the method behavior.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\npublic class Product {\n    \n    private Long id;\n    private String name;\n    private BigDecimal value;\n    \n    \/\/getters and setters\n}\n\n@Service\npublic class ProductService {\n\n    @Secured({&quot;ROLE_USER&quot;, &quot;ROLE_ADMIN&quot;})\n    public Product createProduct(Product product) {\n        \/\/ Logic for creating a product\n        return product;\n    }\n\n    @Secured({&quot;ROLE_USER&quot;, &quot;ROLE_ADMIN&quot;})\n    public Product getProductById(Long id) {\n        \/\/ Logic for fetching a product\n        return null;\n    }\n\n    @Secured(&quot;ROLE_ADMIN&quot;)\n    public Product updateProduct(Product product) {\n        \/\/ Logic for updating a product\n        return product;\n    }\n\n    @Secured(&quot;ROLE_ADMIN&quot;)\n    public void deleteProduct(Long id) {\n        \/\/ Logic for deleting a product\n    }\n}\n\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Application configuration<\/h3>\n\n\n\n<p>You need to add the @EnableGlobalMethodSecurity(securedEnabled = true) to configure your Spring application to use enable method security using @Secured.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\n@SpringBootApplication\n@EnableTransactionManagement\n@EnableGlobalMethodSecurity(securedEnabled = true)\npublic class MasteryApplication {\n\n\tpublic static void main(String&#x5B;] args) {\n\t\tSpringApplication.run(MasteryApplication.class, args);\n\t}\n\n}\n\n<\/pre><\/div>\n\n\n<h3 class=\"wp-block-heading\">Testing the Behavior<\/h3>\n\n\n\n<p>In our example we are going to test the behavior using tests, so we add the spring boot test dependency.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n&lt;dependency&gt;\n    &lt;groupId&gt;org.springframework.security&lt;\/groupId&gt;\n    &lt;artifactId&gt;spring-security-test&lt;\/artifactId&gt;\n    &lt;scope&gt;test&lt;\/scope&gt;\n&lt;\/dependency&gt;\n\n\n<\/pre><\/div>\n\n\n<p>Then we create tests to validate if using a mock user and assign specific roles to him, we can test users in each role and how our application behaves. By doing that we can ensure that only the right roles can perform the allowed actions.<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: java; title: ; notranslate\" title=\"\">\n@SpringBootTest\nclass ProductServiceTests {\n\n    @Autowired\n    private ProductService productService;\n\n    @Test\n    @WithMockUser(roles = &quot;USER&quot;)\n    void testCreateProductAsUser() {\n        Product product = new Product();\n        assertDoesNotThrow(() -&gt; productService.createProduct(product));\n    }\n\n    @Test\n    @WithMockUser(roles = &quot;ADMIN&quot;)\n    void testCreateProductAsAdmin() {\n        Product product = new Product();\n        assertDoesNotThrow(() -&gt; productService.createProduct(product));\n    }\n\n    @Test\n    @WithAnonymousUser\n    void testCreateProductAsAnonymous() {\n        Product product = new Product();\n        assertThrows(AccessDeniedException.class, () -&gt; productService.createProduct(product));\n    }\n\n    @Test\n    @WithMockUser(roles = &quot;USER&quot;)\n    void testGetProductByIdAsUser() {\n        assertDoesNotThrow(() -&gt; productService.getProductById(1L)); \/\/ Assuming product with ID 1 exists\n    }\n\n    @Test\n    @WithMockUser(roles = &quot;ADMIN&quot;)\n    void testGetProductByIdAsAdmin() {\n        assertDoesNotThrow(() -&gt; productService.getProductById(1L));\n    }\n\n    @Test\n    @WithAnonymousUser\n    void testGetProductByIdAsAnonymous() {\n        assertThrows(AccessDeniedException.class, () -&gt; productService.getProductById(1L));\n    }\n\n    @Test\n    @WithMockUser(roles = &quot;USER&quot;)\n    void testUpdateProductAsUser() {\n        Product product = new Product();\n        assertThrows(AccessDeniedException.class, () -&gt; productService.updateProduct(product));\n    }\n\n    @Test\n    @WithMockUser(roles = &quot;ADMIN&quot;)\n    void testUpdateProductAsAdmin() {\n        Product product = new Product();\n        assertDoesNotThrow(() -&gt; productService.updateProduct(product));\n    }\n\n    @Test\n    @WithAnonymousUser\n    void testUpdateProductAsAnonymous() {\n        Product product = new Product();\n        assertThrows(AccessDeniedException.class, () -&gt; productService.updateProduct(product));\n    }\n\n    @Test\n    @WithMockUser(roles = &quot;USER&quot;)\n    void testDeleteProductAsUser() {\n        assertThrows(AccessDeniedException.class, () -&gt; productService.deleteProduct(1L));\n    }\n\n    @Test\n    @WithMockUser(roles = &quot;ADMIN&quot;)\n    void testDeleteProductAsAdmin() {\n        assertDoesNotThrow(() -&gt; productService.deleteProduct(1L));\n    }\n\n    @Test\n    @WithAnonymousUser\n    void testDeleteProductAsAnonymous() {\n        assertThrows(AccessDeniedException.class, () -&gt; productService.deleteProduct(1L));\n    }\n}\n\n<\/pre><\/div>\n\n\n<p>That\u2019s it, now you can manage user access to the application using roles with the @Secured annotation.<\/p>\n\n\n\n<p>If you like this topic, make sure to follow me. In the following days, I\u2019ll be explaining more about Spring annotations! Stay tuned!<\/p>\n\n\n\n<p><a href=\"https:\/\/twitter.com\/WillianFMoya\">Willian Moya (@WillianFMoya) \/ X (twitter.com)<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/www.linkedin.com\/in\/willianmoya\/\">Willian Ferreira Moya | LinkedIn<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This annotation provides a way to add security configuration to business methods. It will use roles to check if a user has permission to call this method. The annotation is part of spring security. So to enable its usage you need the spring security dependency. Example Scenario You have an application that has a product [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[6],"tags":[13,18,20,22,23],"class_list":["post-236","post","type-post","status-publish","format-standard","hentry","category-spring","tag-java","tag-programming","tag-software-development","tag-spring-boot","tag-spring-framework"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/springmasteryhub.com\/index.php?rest_route=\/wp\/v2\/posts\/236","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/springmasteryhub.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/springmasteryhub.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/springmasteryhub.com\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/springmasteryhub.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=236"}],"version-history":[{"count":0,"href":"https:\/\/springmasteryhub.com\/index.php?rest_route=\/wp\/v2\/posts\/236\/revisions"}],"wp:attachment":[{"href":"https:\/\/springmasteryhub.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=236"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/springmasteryhub.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=236"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/springmasteryhub.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=236"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}