{"id":3730,"date":"2025-12-23T10:00:01","date_gmt":"2025-12-23T15:00:01","guid":{"rendered":"https:\/\/www.mymiller.name\/wordpress\/?p=3730"},"modified":"2025-12-23T10:00:01","modified_gmt":"2025-12-23T15:00:01","slug":"beyond-roles-fine-grained-authorization-with-spring-security-acls","status":"publish","type":"post","link":"https:\/\/www.mymiller.name\/wordpress\/spng_security\/beyond-roles-fine-grained-authorization-with-spring-security-acls\/","title":{"rendered":"Beyond Roles: Fine-Grained Authorization with Spring Security ACLs"},"content":{"rendered":"\n<div class=\"wp-block-jetpack-markdown\"><p>Spring Security is a robust framework for securing your Java applications. While roles and authorities provide a good foundation for authorization, sometimes you need more granular control. This is where Access Control Lists (ACLs) shine. ACLs allow you to define permissions at the object level, offering greater flexibility and precision in securing your application.<\/p>\n<p><strong>What are ACLs?<\/strong><\/p>\n<p>Imagine you have a document management system. Using traditional role-based security, you might have roles like \u201cviewer,\u201d \u201ceditor,\u201d and \u201cadmin.\u201d But what if you want to give specific users access to only certain documents? ACLs enable this by attaching a list of permissions directly to each document.<\/p>\n<p><strong>Spring Security ACL in Action<\/strong><\/p>\n<p>Spring Security provides excellent support for ACLs. Let\u2019s break down the key components:<\/p>\n<ul>\n<li><strong>Domain Object:<\/strong> The object you want to secure (e.g., a document, a customer record, a product).<\/li>\n<li><strong>ACL:<\/strong>  A list of permissions associated with the domain object.<\/li>\n<li><strong>SID (Security Identity):<\/strong> Represents a user or a role.<\/li>\n<li><strong>Permission:<\/strong> Defines the action that can be performed on the object (e.g., read, write, delete).<\/li>\n<\/ul>\n<p><strong>Example: Document Management System<\/strong><\/p>\n<p>Let\u2019s say we have a <code>Document<\/code> object:<\/p>\n<pre><code class=\"language-java\">public class Document {\n    private Long id;\n    private String title;\n    private String content;\n    \/\/ ... other fields\n}\n<\/code><\/pre>\n<p>Using Spring Security ACL, we can define permissions for individual users on each document.<\/p>\n<ol>\n<li>\n<p><strong>Database Tables:<\/strong> Spring Security ACL requires a set of database tables to store ACL information. These tables track the relationships between domain objects, SIDs, and permissions. (See \u201cSetting up ACL Tables\u201d section below for details)<\/p>\n<\/li>\n<li>\n<p><strong>Configuration:<\/strong>  You\u2019ll need to configure Spring Security to enable ACLs and specify the relevant database tables. (See \u201cEnabling Spring Security ACLs\u201d section below for details)<\/p>\n<\/li>\n<li>\n<p><strong>Assigning Permissions:<\/strong> You can programmatically assign permissions using <code>AclService<\/code>:<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"language-java\">@Service\npublic class DocumentService {\n\n    @Autowired\n    private AclService aclService;\n\n    public void grantAccess(Document document, User user, Permission permission) {\n        MutableAcl acl = aclService.readAclById(new ObjectIdentityImpl(document));\n        acl.insertAce(acl.getEntries().size(), permission, new PrincipalSid(user.getUsername()), true);\n        aclService.updateAcl(acl);\n    }\n}\n<\/code><\/pre>\n<p>This code grants a specific <code>permission<\/code> to a <code>user<\/code> for the given <code>document<\/code>.<\/p>\n<ol start=\"4\">\n<li><strong>Checking Permissions:<\/strong>  Spring Security provides <code>AclPermissionEvaluator<\/code> to check permissions during security checks:<\/li>\n<\/ol>\n<pre><code class=\"language-java\">@PreAuthorize(&quot;hasPermission(#document, 'READ')&quot;)\npublic Document getDocument(Document document) {\n    \/\/ ...\n}\n<\/code><\/pre>\n<p>This ensures that only users with \u201cREAD\u201d permission on the <code>document<\/code> can access it.<\/p>\n<p><strong>Benefits of Spring Security ACLs:<\/strong><\/p>\n<ul>\n<li><strong>Fine-grained control:<\/strong>  Secure individual objects instead of relying solely on roles.<\/li>\n<li><strong>Flexibility:<\/strong> Easily adapt to changing security requirements by modifying ACL entries.<\/li>\n<li><strong>Improved data security:<\/strong>  Enhance security by restricting access to sensitive data at the object level.<\/li>\n<\/ul>\n<p><strong>Beyond the Basics:<\/strong><\/p>\n<p>Spring Security ACLs offer advanced features like:<\/p>\n<ul>\n<li><strong>Inheritance:<\/strong>  Create hierarchical permission structures.<\/li>\n<li><strong>Auditing:<\/strong> Track changes to ACL entries.<\/li>\n<li><strong>Performance optimization:<\/strong>  Efficiently retrieve and manage ACLs for large numbers of objects.<\/li>\n<\/ul>\n<p><strong>Enabling Spring Security ACLs<\/strong><\/p>\n<p>To enable ACLs in your Spring Security configuration, you need to:<\/p>\n<ol>\n<li>\n<p><strong>Include the <code>spring-security-acl<\/code> dependency:<\/strong> Add this dependency to your project\u2019s <code>pom.xml<\/code> or <code>build.gradle<\/code> file.<\/p>\n<\/li>\n<li>\n<p><strong>Enable ACL support:<\/strong> Add <code>@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)<\/code> to your security configuration class. This enables method-level security annotations like <code>@PreAuthorize<\/code>.<\/p>\n<\/li>\n<li>\n<p><strong>Configure <code>AclService<\/code>:<\/strong> Define a bean of type <code>AclService<\/code> and configure it with your data source and lookup strategy.<\/p>\n<\/li>\n<li>\n<p><strong>Configure <code>AclPermissionEvaluator<\/code>:<\/strong> Define a bean of type <code>AclPermissionEvaluator<\/code> and inject the <code>AclService<\/code>.<\/p>\n<\/li>\n<\/ol>\n<p><strong>Setting up ACL Tables<\/strong><\/p>\n<p>Spring Security ACL requires the following database tables:<\/p>\n<ul>\n<li><strong><code>ACL_SID<\/code>:<\/strong> Stores security identities (SIDs), which can be users or roles.<\/li>\n<li><strong><code>ACL_CLASS<\/code>:<\/strong> Stores information about the domain object classes that are secured with ACLs.<\/li>\n<li><strong><code>ACL_OBJECT_IDENTITY<\/code>:<\/strong>  Links domain objects to their ACL entries.<\/li>\n<li><strong><code>ACL_ENTRY<\/code>:<\/strong> Stores individual permissions (ACEs &#8211; Access Control Entries) for each object.<\/li>\n<\/ul>\n<p>You can create these tables manually or use the <code>JdbcMutableAclService<\/code> to create them automatically.<\/p>\n<p><strong>Using JdbcMutableAclService with PostgreSQL<\/strong><\/p>\n<p><code>JdbcMutableAclService<\/code> provides methods for creating and managing ACLs. Here\u2019s an example of how to use it with PostgreSQL:<\/p>\n<pre><code class=\"language-java\">@Bean\npublic JdbcMutableAclService aclService() {\n    JdbcMutableAclService jdbcMutableAclService = new JdbcMutableAclService(dataSource, lookupStrategy(), aclCache());\n    jdbcMutableAclService.setClassIdentityQuery(&quot;SELECT currval('acl_class_id_seq')&quot;); \/\/ For PostgreSQL\n    jdbcMutableAclService.setSidIdentityQuery(&quot;SELECT currval('acl_sid_id_seq')&quot;); \/\/ For PostgreSQL\n    return jdbcMutableAclService;\n}\n<\/code><\/pre>\n<p>This code creates a <code>JdbcMutableAclService<\/code> bean. The <code>setClassIdentityQuery<\/code> and <code>setSidIdentityQuery<\/code> are specific to PostgreSQL and ensure proper primary key generation using sequences.<\/p>\n<p>By implementing Spring Security ACLs, you gain a powerful tool for managing authorization in your applications. This granular approach enables you to build more secure and flexible systems that adapt to your specific needs.<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":3735,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","jetpack_post_was_ever_published":false,"_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":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[441],"tags":[69,319],"series":[],"class_list":["post-3730","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-spng_security","tag-java-2","tag-spring"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/10\/ai-generated-8686283_1280-jpg.avif","jetpack-related-posts":[{"id":3560,"url":"https:\/\/www.mymiller.name\/wordpress\/spng_security\/zero-trust-with-spring-boot-deep-dive-into-security\/","url_meta":{"origin":3730,"position":0},"title":"Zero Trust with Spring Boot: Deep Dive into Security","author":"Jeffery Miller","date":"September 22, 2025","format":false,"excerpt":"Zero Trust is a paradigm shift in security, assuming no inherent trust within a network. Implementing Zero Trust principles with Spring Boot fortifies your microservices against modern threats. Let\u2019s delve deeper into the key concepts: Secure Communication (HTTPS\/TLS): Encryption: HTTPS encrypts all communication between microservices, preventing eavesdropping and data tampering.\u2026","rel":"","context":"In &quot;Spring Security&quot;","block_context":{"text":"Spring Security","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spng_security\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/Gemini_Generated_Image_y76fbby76fbby76f.jpg?fit=1200%2C1200&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/Gemini_Generated_Image_y76fbby76fbby76f.jpg?fit=1200%2C1200&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/Gemini_Generated_Image_y76fbby76fbby76f.jpg?fit=1200%2C1200&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/Gemini_Generated_Image_y76fbby76fbby76f.jpg?fit=1200%2C1200&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/Gemini_Generated_Image_y76fbby76fbby76f.jpg?fit=1200%2C1200&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":3922,"url":"https:\/\/www.mymiller.name\/wordpress\/spng_security\/beyond-rbac-spring-security-6-oauth-2-1-and-the-zero-trust-evolution\/","url_meta":{"origin":3730,"position":1},"title":"Beyond RBAC: Spring Security 6, OAuth 2.1, and the Zero-Trust Evolution","author":"Jeffery Miller","date":"November 19, 2025","format":false,"excerpt":"The journey to Zero Trust (ZT) is an ongoing architectural evolution, not a single deployment. While the foundational principles\u2014never trust, always verify\u2014are clear, implementing them in a distributed microservice environment requires rigorous adherence to modern standards. For Spring architects and developers, Spring Security 6 and the Spring Authorization Server provide\u2026","rel":"","context":"In &quot;Spring Security&quot;","block_context":{"text":"Spring Security","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spng_security\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/11\/coding-1841550_1280.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/11\/coding-1841550_1280.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/11\/coding-1841550_1280.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/11\/coding-1841550_1280.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/11\/coding-1841550_1280.avif 3x"},"classes":[]},{"id":3641,"url":"https:\/\/www.mymiller.name\/wordpress\/spng_security\/integrating-java-spring-with-keycloak-a-comprehensive-guide\/","url_meta":{"origin":3730,"position":2},"title":"Integrating Java Spring with Keycloak: A Comprehensive Guide","author":"Jeffery Miller","date":"December 24, 2025","format":false,"excerpt":"Java Spring, a popular framework for building enterprise-level applications, can seamlessly integrate with Keycloak, a robust open-source Identity and Access Management (IAM) solution. This combination offers a powerful way to implement secure authentication, authorization, and user management features in your Spring-based applications. Let\u2019s explore how to achieve this integration along\u2026","rel":"","context":"In &quot;Spring Security&quot;","block_context":{"text":"Spring Security","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spng_security\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/08\/ghost-7571881_1280-jpg.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/08\/ghost-7571881_1280-jpg.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/08\/ghost-7571881_1280-jpg.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/08\/ghost-7571881_1280-jpg.avif 2x"},"classes":[]},{"id":3957,"url":"https:\/\/www.mymiller.name\/wordpress\/spring-admin\/mastering-spring-authorization-server-architectural-guide\/","url_meta":{"origin":3730,"position":3},"title":"Mastering Spring Authorization Server: Architectural Guide","author":"Jeffery Miller","date":"December 24, 2025","format":false,"excerpt":"As a Software Architect, transitioning from the legacy spring-security-oauth2 to the modern Spring Authorization Server (SAS) is a critical shift. This guide provides a deep dive into building a robust identity platform integrated with Spring Cloud Gateway and Social Logins. 1. Core Architecture: How it Works Spring Authorization Server is\u2026","rel":"","context":"In &quot;Spring Admin&quot;","block_context":{"text":"Spring Admin","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring-admin\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/12\/Gemini_Generated_Image_dj5ssndj5ssndj5s.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/12\/Gemini_Generated_Image_dj5ssndj5ssndj5s.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/12\/Gemini_Generated_Image_dj5ssndj5ssndj5s.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/12\/Gemini_Generated_Image_dj5ssndj5ssndj5s.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/12\/Gemini_Generated_Image_dj5ssndj5ssndj5s.avif 3x"},"classes":[]},{"id":3816,"url":"https:\/\/www.mymiller.name\/wordpress\/spring\/securing-your-spring-boot-actuator-endpoints-a-comprehensive-guide\/","url_meta":{"origin":3730,"position":4},"title":"Securing Your Spring Boot Actuator Endpoints: A Comprehensive Guide","author":"Jeffery Miller","date":"December 24, 2025","format":false,"excerpt":"Spring Boot Actuator provides invaluable insights into the inner workings of your running application. From health checks and metrics to thread dumps and environment details, these endpoints are crucial for monitoring and managing your application in production. However, exposing them without proper security can open doors to malicious actors, potentially\u2026","rel":"","context":"In &quot;Spring&quot;","block_context":{"text":"Spring","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/04\/ai-generated-8070001_1280.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/04\/ai-generated-8070001_1280.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/04\/ai-generated-8070001_1280.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/04\/ai-generated-8070001_1280.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/04\/ai-generated-8070001_1280.avif 3x"},"classes":[]},{"id":3871,"url":"https:\/\/www.mymiller.name\/wordpress\/spring_events\/tracking-user-lifecycle-capturing-login-failed-login-and-signup-events-in-spring-authorization-server\/","url_meta":{"origin":3730,"position":5},"title":"Tracking User Lifecycle: Capturing Login, Failed Login, and Signup Events in Spring Authorization Server","author":"Jeffery Miller","date":"November 24, 2025","format":false,"excerpt":"Understanding how users interact with your Spring Authorization Server is crucial for security, auditing, and gaining insights into user behavior. By capturing key lifecycle events like successful logins, failed login attempts, and new user signups, you can build a robust monitoring system. This post will guide you through the process\u2026","rel":"","context":"In &quot;Spring Events&quot;","block_context":{"text":"Spring Events","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring_events\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/05\/technology-6701509_1280-1.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/05\/technology-6701509_1280-1.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/05\/technology-6701509_1280-1.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/05\/technology-6701509_1280-1.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/05\/technology-6701509_1280-1.avif 3x"},"classes":[]}],"jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/3730","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/comments?post=3730"}],"version-history":[{"count":1,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/3730\/revisions"}],"predecessor-version":[{"id":3736,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/3730\/revisions\/3736"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/media\/3735"}],"wp:attachment":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/media?parent=3730"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/categories?post=3730"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/tags?post=3730"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/series?post=3730"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}