问题
I have a toy web app, in which I want to login the users taken from database.
It works but, I can login with a USER role where I should only login with a user having the ADMIN role.
Here is my code:
Servlet 3.0 bootstraper
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()};
}
}
User entity:
@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 +
'}';
}
}
Role entity:
@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 +
'}';
}
}
My custome userdetailsservice:
@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;
}
}
I am keeping my roles in the db, as strings : USER, MODERATOR, ADMIN
My Spring security config:
@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();
}
}
The problem is guys, that I said I want every user to have the ROLE_ADMIN but I am still able to login also with a user that has only the USER role. I don't understand why.
I have made debug, my user is fetched successfully from the db, all is fine,but I don't know where Spring is checking for roles.
Regards,
回答1:
remove your .anyRequest().authenticated() from configuration since if you request ROLE checking user has to be authenticated it apparently takes precedence when checked by the security filter
回答2:
as user3030447 said in a comment:
Roles must start with ROLE_*.
e.g. if you want to use hasRole('EDIT') you will have to create the GrantedAuthority like this:
new SimpleGrantedAuthority("ROLE_EDIT");
回答3:
You can use hasAuthority() or hasAnyAuthority() functions.
来源:https://stackoverflow.com/questions/28175411/spring-security-db-userdetailsservice-doesnt-take-in-account-the-roles-of-users