Spring security db UserDetailsService 没有考虑用户的角色
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()
函数。
我有一个玩具网络应用程序,我想在其中登录从数据库中获取的用户。
它有效,但是,我可以使用 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()
函数。