Sitemap

@Preauthorize — Different Ways to Use This Annotation!

3 min readNov 30, 2024

--

Spring Security + Preauthorize is powerful tool and we will see different ways we can harness this tool.

Press enter or click to view image in full size
Photo by You Le on Unsplash

We saw how to secure applications using Spring Security and @Preauthorize annotation. Here is a refresher —

Here is how you setup this security feature —

Setting Up @PreAuthorize in Spring Security

  1. Enable Method Security: To use @PreAuthorize, enable method security in your Spring configuration:

@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// Security configurations
}

2. Define Roles and Authorities: Ensure that roles and authorities are properly configured in the security setup.

Different ways to use @PreAuthorize —

  • Annotation Placement: @PreAuthorize can be placed on methods in service or controller classes.
  • Syntax: @PreAuthorize("expression"), where the expression is written in SpEL.

Examples of @PreAuthorize Expressions

  1. Role-Based Access:

@PreAuthorize("hasRole('ADMIN')")
public void adminOnlyMethod() {
// Only users with the "ADMIN" role can access this method
}

2. Multiple Roles:


@PreAuthorize("hasAnyRole('USER', 'ADMIN')")
public void userOrAdminMethod() {
// Users with either "USER" or "ADMIN" roles can access this method
}

3. Checking Authorities:


@PreAuthorize("hasAuthority('READ_PRIVILEGE')")
public void readPrivilegeMethod() {
// Users with the "READ_PRIVILEGE" authority can access this method
}

4. Complex Conditions Using SpEL:


@PreAuthorize("#userId == authentication.principal.id or hasRole('ADMIN')")
public void updateUserProfile(Long userId) {
// Allows access if the logged-in user's ID matches the given userId, or if they have "ADMIN" role
}

5. Access Based on Method Parameters:


@PreAuthorize("#username == authentication.name")
public void accessOwnProfile(String username) {
// Allows access only if the provided username matches the logged-in user's username
}

Some more advanced way for special use cases —

I havn’t used these since most of the times, roles and authorities are checked in basic applications but its good to know they exist.

Get Full Stack Developer’s stories in your inbox

Join Medium for free to get updates from this writer.

6. Custom Methods in SpEL

You can define custom methods in a PermissionEvaluator or a SecurityExpressionHandler and use them in @PreAuthorize expressions.


@PreAuthorize("@customPermissionEvaluator.hasAccess(authentication, #resourceId)")
public void accessResource(Long resourceId) {
// Custom logic for access control
}

7. Checking Principal Details

You can directly access details from the Principal object or Authentication object.


@PreAuthorize("authentication.principal.username == #username")
public void accessOwnData(String username) {
// User can only access their own data
}

8. Combining Logical Expressions

You can combine multiple conditions using logical operators (and, or, not).

@PreAuthorize("hasRole('ADMIN') or (hasRole('USER') and #userId == principal.id)")
public void adminOrSelfUpdate(Long userId) {
// Admins can access, or users can access their own data
}

9. Denying Access Explicitly

Use denyAll() to block access to a method explicitly.

@PreAuthorize("denyAll()")
public void restrictedMethod() {
// No one can access this method
}

10. Accessing Custom Attributes

If you’ve added custom claims or attributes to the security context (e.g., via JWT tokens), you can access them using SpEL.

@PreAuthorize("hasAuthority('ADMIN') and #region == authentication.details['region']")
public void regionSpecificAction(String region) {
// Only admins with a specific region can perform this action
}

11. Allowing All Access

Use permitAll() to allow access to everyone.

@PreAuthorize("permitAll()")
public void openAccessMethod() {
// Open to all users
}

12. Dynamic Logic with Beans

Inject beans for more dynamic logic.

@PreAuthorize("@securityService.canAccess(authentication, #resource)")
public void dynamicAccess(Resource resource) {
// Use a service to determine access
}

13. . Using Environment Properties

You can also use environment variables or Spring properties in expressions.

@PreAuthorize("@environment.getProperty('feature.enabled') == 'true'")
public void featureToggleMethod() {
// Accessible only if a feature toggle is enabled
}

Well well well, this was a heavy article even while I was collecting all the information, because I have used only 4–5 of these in my work.

But I hope this helps somebody!!

--

--

Written by Full Stack Developer

This blog is curated just for you, if you are a Developer planning to appear for interviews OR looking out for new & interesting things happening in Java Space.