Spring security db UserDetailsS​​ervice 没有考虑用户的角色

Spring security db UserDetailsService doesn't take in account the roles of users

我有一个玩具网络应用程序,我想在其中登录从数据库中获取的用户。

它有效,但是,我可以使用 USER 角色登录,而我应该只使用具有 ADMIN 角色的用户登录。

这是我的代码:

Servlet 3.0 引导程序

public class Bootstraper extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class<?>[]{JPAConfig.class, WebSecurityConfig.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class<?>[]{MvcConfig.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    @Override
    protected Filter[] getServletFilters() {
        return new Filter[]{new DelegatingFilterProxy("springSecurityFilterChain"), new OpenEntityManagerInViewFilter()};
    }
}

用户实体:

@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column(unique = true)
    private String name;

    @Column
    private String password;

    @Column
    private boolean enabled;

    @OneToMany(mappedBy = "user", fetch = FetchType.EAGER)
    private Set<Role> roles = new HashSet<>();

    public User() {
    }

    public User(String name, String password, boolean enabled) {
        this.name = name;
        this.password = password;
        this.enabled = enabled;
    }

    public Long getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public boolean isEnabled() {
        return enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    public Set<Role> getRoles() {
        return roles;
    }

    public void setRoles(Set<Role> roles) {
        this.roles = roles;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", password='" + password + '\'' +
                ", enabled=" + enabled +
                '}';
    }
}

角色实体:

@Entity
@Table(name = "roles")
public class Role {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Column
    private String role;

    @JoinColumn(name = "u_id")
    @ManyToOne
    private User user;

    public Role() {
    }

    public Role(String role) {
        this.role = role;
    }

    public Long getId() {
        return id;
    }

    public String getRole() {
        return role;
    }

    public void setRole(String role) {
        this.role = role;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    @Override
    public String toString() {
        return "Role{" +
                "id=" + id +
                ", role='" + role + '\'' +
                ", user=" + user +
                '}';
    }
}

我的客户用户详细信息服务:

@Service
public class MyUserDetailsService implements UserDetailsService {

    @Autowired
    private UsersService usersService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = usersService.getUser(username);
        if (user != null) {
            List<GrantedAuthority> authorityList = user.getRoles().stream()
                    .map(role -> new SimpleGrantedAuthority(role.getRole()))
                    .collect(Collectors.toList());

            return new org.springframework.security.core.userdetails.User(username, user.getPassword(), user.isEnabled(), true, true, true, authorityList);
        }

        return null;
    }
}

我在数据库中保留我的角色,作为字符串:USER、MODERATOR、ADMIN

我的 Spring 安全配置:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private static final Logger LOGGER = LoggerFactory.getLogger(WebSecurityConfig.class);

    @Autowired
    private MyUserDetailsService userDetailsService;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.authorizeRequests()
                .antMatchers("/resources/**").permitAll()
                .anyRequest().authenticated()
                .antMatchers("/**").access("hasRole('ROLE_ADMIN')")
                .and().formLogin()
                .loginPage("/login")
                .permitAll().and()
                .logout().permitAll();

        http.csrf().disable();
    }
}

问题是伙计们,我说过我希望每个用户都拥有 ROLE_ADMIN,但我仍然可以使用只有 USER 角色的用户登录。我不明白为什么。

我进行了调试,我的用户从数据库中成功获取,一切正常,但我不知道 Spring 在哪里检查角色。

此致,

从配置中删除您的 .anyRequest().authenticated(),因为如果您请求 ROLE 检查用户必须经过身份验证,它显然在安全过滤器检查时优先

正如 user3030447 在评论中所说:

角色必须以 ROLE_* 开头。

例如如果你想使用 hasRole('EDIT'),你必须像这样创建 GrantedAuthority:

new SimpleGrantedAuthority("ROLE_EDIT");

您可以使用 hasAuthority()hasAnyAuthority() 函数。