![](/img/trans.png)
[英]Spring security programmatic in-memory UserDetailsService: username and roles, NO password
[英]Spring security db UserDetailsService doesn't take in account the roles of users
我有一個玩具Web應用程序,我要在其中登錄從數據庫獲取的用戶。
它可以工作,但是我可以使用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在哪里檢查角色。
問候,
如user3030447在評論中所述:
角色必須以ROLE_ *開頭。
例如,如果要使用hasRole('EDIT')
,則必須像下面這樣創建GrantedAuthority:
new SimpleGrantedAuthority("ROLE_EDIT");
從配置中刪除.anyRequest().authenticated()
,因為如果您請求ROLE檢查用戶必須通過身份驗證,則在由安全過濾器檢查時,它顯然具有優先權
您可以使用hasAuthority()
或hasAnyAuthority()
函數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.