【问题标题】:Spring security db UserDetailsService doesn't take in account the roles of usersSpring security db UserDetailsS​​ervice 不考虑用户的角色
【发布时间】:2015-01-27 16:36:43
【问题描述】:

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

它可以工作,但是我可以使用 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在哪里检查角色。

问候,

【问题讨论】:

  • 启用调试日志(log4j.logger.org.springframework.security=DEBUG, stdout, fileout - for log4j)它会告诉你很多。
  • 请把ROLE_ADMIN改成ADMIN试试看。
  • @Mithun 访问功能不需要“ROLE_”。见docs.spring.io/spring-security/site/docs/3.2.5.RELEASE/…
  • @Evgeni - 感谢您的纠正。

标签: java spring security login


【解决方案1】:

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

【讨论】:

  • 我还必须将 ROLE_ 添加到从数据库获取的角色中,但现在可以使用。如果我让你提到的那行,那么我可以在任何地方对每个角色进行身份验证,所以你是对的,谢谢。
【解决方案2】:

正如 user3030447 在评论中所说:

角色必须以 ROLE_* 开头。

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

new SimpleGrantedAuthority("ROLE_EDIT");

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 2018-07-30
      • 2012-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-07
      • 2011-07-26
      • 2017-10-27
      • 2011-09-01
      相关资源
      最近更新 更多