Spring Security基于权限而非角色的授权配置问题咨询
Alright, let's tackle this Spring Security authorization issue you're facing. The problem here is that your current setup isn't properly enforcing the required permission combinations for Page A, which is why users with the User role can access it. Let's fix this step by step.
First, let's align on your requirements:
- Page A: Requires all three permissions (
ADD,VIEW,EDIT) — only Admin and Manager have these - Page B: Requires both
ADDandVIEWpermissions — all three user types qualify
Step 1: Ensure Permissions Are Properly Assigned to Roles
First, you need to make sure your UserDetailsService correctly maps each role to its corresponding permissions. Don't just add role authorities—include the specific permissions too. Here's a sample implementation:
@Service public class CustomUserDetailsService implements UserDetailsService { @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // Replace with your actual user retrieval logic (e.g., database call) return switch (username) { case "admin" -> new User( "admin", "{noop}admin123", // {noop} for plain text passwords (remove in production) AuthorityUtils.createAuthorityList("ROLE_ADMIN", "ADD", "EDIT", "VIEW") ); case "manager" -> new User( "manager", "{noop}manager123", AuthorityUtils.createAuthorityList("ROLE_MANAGER", "ADD", "EDIT", "VIEW") ); case "user" -> new User( "user", "{noop}user123", AuthorityUtils.createAuthorityList("ROLE_USER", "ADD", "VIEW") ); default -> throw new UsernameNotFoundException("User not found: " + username); }; } }
Step 2: Configure Authorization Rules with Permission Checks
Now, update your SecurityFilterChain to use permission-based checks instead of role-based ones. Use hasAllAuthorities() to enforce that a user must possess all specified permissions to access a resource:
@Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth // Page A: Require ALL of ADD, VIEW, EDIT permissions .requestMatchers("/page-a/**").hasAllAuthorities("ADD", "VIEW", "EDIT") // Page B: Require both ADD and VIEW permissions .requestMatchers("/page-b/**").hasAllAuthorities("ADD", "VIEW") // Allow anonymous access to login page (adjust as needed) .requestMatchers("/login").permitAll() // All other routes require authentication .anyRequest().authenticated() ) .formLogin(form -> form.permitAll()) // Enable form login .logout(logout -> logout.permitAll()); // Enable logout return http.build(); } }
Why This Fixes Your Issue
The problem you were seeing (User accessing Page A) likely came from one of these mistakes:
- You were using role-based checks like
hasAnyRole("ADMIN", "MANAGER")but had misconfigured role assignments. - You used
hasAnyAuthority()instead ofhasAllAuthorities(), which would allow users with any of the permissions (not all) to access Page A. - Your
UserDetailsServicewasn't correctly assigning permissions to roles (e.g., accidentally giving User theEDITpermission).
With the above setup:
- Users with the
Userrole only haveADDandVIEWpermissions, so they fail thehasAllAuthorities("ADD", "VIEW", "EDIT")check for Page A. - All users (Admin, Manager, User) pass the
hasAllAuthorities("ADD", "VIEW")check for Page B, as expected.
Alternative: Using SpEL Expressions
If you prefer, you can use Spring Expression Language (SpEL) for more flexibility. The equivalent rules would be:
.requestMatchers("/page-a/**").access("hasAuthority('ADD') and hasAuthority('VIEW') and hasAuthority('EDIT')") .requestMatchers("/page-b/**").access("hasAuthority('ADD') and hasAuthority('VIEW')")
This works exactly the same as hasAllAuthorities(), but gives you more control if you need to add complex logic later.
内容的提问来源于stack exchange,提问作者vikas

