You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot + Security的hasRole与hasAuthority权限控制失效问题

问题分析与解决方案

嘿,我一眼就看穿问题根源了——你的Spring Security配置顺序搞反了,再加上UserDetailsService里硬编码了权限,这俩问题叠加起来直接让权限控制完全失效。

核心问题1:HttpSecurity规则顺序错误

Spring Security的授权规则是从上到下依次匹配,一旦匹配到对应规则就会停止后续匹配。你现在的配置里先写了anyRequest().authenticated(),这意味着所有请求只要通过认证就允许访问,后面的/admin/**、/alumno/**这些规则根本不会被执行!这就是Teacher用户能随意访问Admin接口的原因。

修正后的安全配置类

把anyRequest().authenticated()移到所有具体路径规则的后面,同时把密码编码器声明为Bean方便Spring统一管理:

@Configuration @EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
            .antMatchers("/resources/**").permitAll()
            // 先配置具体路径的权限规则
            .antMatchers("/admin/**").hasAuthority("Admin")
            .antMatchers("/alumno/**").hasAuthority("Student")
            .antMatchers("/profesor/**").hasAuthority("Teacher")
            // 最后配置通用规则
            .anyRequest().authenticated()
            .and()
            .formLogin()
            .usernameParameter("email")
            .passwordParameter("password")
            .loginProcessingUrl("/j_spring_security_check")
            .loginPage("/login").failureUrl("/login?error=true")
            .defaultSuccessUrl("/admin/home")
            .permitAll()
            .and()
            .logout()
            .permitAll();
    }

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

核心问题2:UserDetailsService硬编码权限

你的UserDetailsServiceImpl里不管用户实际角色是什么,都硬塞了"Teacher"权限,这会导致所有用户都只有Teacher权限(或者说数据库里的真实角色完全没被读取)。你需要从UsuarioEntity中获取用户的实际角色,再转换为GrantedAuthority。

假设你的UsuarioEntity有getRoles()方法(返回角色列表,比如List<String>),修正后的代码如下:

@Service
public class UserDetailsServiceImpl implements UserDetailsService{
    @Autowired
    private UsuarioDao usuarioDao;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        UsuarioEntity usuarioEntity = usuarioDao.findByUsuario(username);
        if (usuarioEntity == null) {
            throw new UsernameNotFoundException("用户不存在:" + username);
        }

        Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
        // 从用户实体中读取真实角色,转换为权限对象
        for (String role : usuarioEntity.getRoles()) {
            grantedAuthorities.add(new SimpleGrantedAuthority(role));
        }

        // 注意:数据库中密码必须是BCrypt加密后的字符串,明文会导致认证失败
        return new User(
            usuarioEntity.getUsuario(),
            usuarioEntity.getPassword(),
            grantedAuthorities
        );
    }
}

关于hasRole()和hasAuthority()的注意点

如果你想用hasRole("Admin"),那么对应的GrantedAuthority需要是"ROLE_Admin"(Spring Security会自动给hasRole的参数加上ROLE_前缀);如果用hasAuthority("Admin"),则直接匹配字符串"Admin"。要确保配置和UserDetailsService中的权限字符串完全一致,不能混用。

测试验证

修改后重启应用:

  • 用Admin角色用户登录,应该能正常访问/admin/home
  • 用Teacher角色用户登录,访问/admin/home会被拦截,返回403禁止访问或跳转到登录页

内容的提问来源于stack exchange,提问作者Luisao

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:56:43