当我使用安全性登录时,我无法使用request.isUserInRole()
方法。我认为没有设置用户的角色。
这是我的安全配置:
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled=true)
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private DataSource dataSource;
@Autowired
private UserDetailsServiceImplementation userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/signup").permitAll()
.antMatchers("/").permitAll()
//.antMatchers("/first").hasAuthority("Service_Center")
.antMatchers("/login").permitAll()
.anyRequest().fullyAuthenticated()
.and().formLogin()
.loginPage("/login")
.usernameParameter("email")
.passwordParameter("password")
.defaultSuccessUrl("/default")
.failureUrl("/login?error").permitAll()
.and().logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login?logout")
.deleteCookies("JSESSIONID")
.invalidateHttpSession(true).permitAll();
}
@Autowired
public void configAuthentication(AuthenticationManagerBuilder auth)
throws Exception {
auth.userDetailsService(userDetailsService);
}
}
这是我的User
实体:
@Entity
@Table(name="user")
public class User implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name="user_id")
private Long userID;
@Column(name="email_address", nullable = false, unique = true)
private String emailAddress;
@Column(name="password")
private String password;
@Column(name = "role", nullable = false)
@Enumerated(EnumType.STRING)
private Role role;
public User() {
super();
}
public User(String emailAddress, String password) {
this.emailAddress = emailAddress;
this.password = password;
}
public Long getUserID() {
return userID;
}
public void setUserID(Long userID) {
this.userID = userID;
}
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Role getRole() {
return role;
}
public void setRole(Role role) {
this.role = role;
}
@Override
public String toString() {
return "User [userID=" + userID + ", emailAddress=" + emailAddress
+ ", password=" + password + ", role=" + role + "]";
}
public UserDetails toCurrentUserDetails() {
return CurrentUserDetails.create(this);
}
}
这是我的枚举Role
:
public enum Role {
Fleet_Company, Service_Center, Admin
}
这是我的UserDetailsServiceImplementation
:
@Component
public class UserDetailsServiceImplementation implements UserDetailsService {
@Autowired
private UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {
if ( username == null || username.isEmpty() ){
throw new UsernameNotFoundException("username is empty");
}
User foundUser = userRepository.findByEmailAddress(username);
if( foundUser != null ){
System.out.println("FOUND");
return foundUser.toCurrentUserDetails();
}
throw new UsernameNotFoundException( username + "is not found");
}
}
这是实现UserDetails
的类:
public class CurrentUserDetails implements UserDetails {
private Long userID;
private String emailAddress;
private String password;
private Role role;
public CurrentUserDetails(Long userID, String emailAddress, String password, Role role) {
super();
this.userID = userID;
this.emailAddress = emailAddress;
this.password = password;
this.role = role;
}
/* public static UserDetails create(Users entity) {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
for(Authorities auth: entity.getAuthorities()){
authorities.add(new SimpleGrantedAuthority(auth.getId().getAuthority()));
}
return new MyUserDetail(entity.getUserId(), entity.getLoginId(), entity.getPassword(), entity.getDisplayName(), authorities);
}*/
public Long getUserID(){
return this.userID;
}
public Role getRole(){
return this.role;
}
@Override
public String getPassword() {
return this.password;
}
public String getEmailAddress() {
return this.emailAddress;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
public static UserDetails create(User entity) {
System.out.println(entity.getUserID()+ entity.getEmailAddress()+ entity.getPassword()+ entity.getRole());
return new CurrentUserDetails(entity.getUserID(), entity.getEmailAddress(), entity.getPassword(), entity.getRole());
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
// TODO Auto-generated method stub
return null;
}
@Override
public String getUsername() {
// TODO Auto-generated method stub
return null;
}
}
基本上,我们可以看到我的MySQL数据库上只有一个表,它有四列,其中一列是'角色'。
但就像我说的那样,当我使用request.isUserInRole("Service_Center")
时,它返回FALSE。 .antMatchers("/first").hasAuthority("Service_Center")
也不起作用。
答案 0 :(得分:7)
创建UserDetails时,您应自行填写角色内容:
public class SecurityUser implements UserDetails{
String ROLE_PREFIX = "ROLE_";
String userName;
String password;
String role;
public SecurityUser(String username, String password, String role){
this.userName = username;
this.password = password;
this.role = role;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> list = new ArrayList<GrantedAuthority>();
list.add(new SimpleGrantedAuthority(ROLE_PREFIX + role));
return list;
}
基本上,您需要做的是覆盖方法:getAuthorities
,并将您的角色字段的内容填入GrantedAuthority
列表。
答案 1 :(得分:1)
Divelnto,zapl和thorinkor说的是对的。但问题应该是关于&#34;角色&#34;而不是&#34;角色&#34;。或者,如果您将用户和角色放在一个表中,那么它的设计就会很糟糕。您可能希望重新审视您的设计方法。您应该有一个单独的角色实体。在您的UserService中,您可以执行以下操作:
AppUser user = userRepository.findByUsername(username);
Set<GrantedAuthority> grantedAuthorities = new HashSet<>(); // use list if you wish
for (AppRole role : user.getRoles()) {
grantedAuthorities.add(new SimpleGrantedAuthority(role.getName()));
}
return new org.springframework.security.core.userdetails.User(
user.getUsername(),
user.getPassword(),
grantedAuthorities
);
在DB中,您可以将角色名称存储为 - (例如)数据库中的ADMIN / EDITOR / VIEWER,或者将角色存储为ROLE_ADMIN / ROLE _...然后您可能想要使用hasRole / hasAuthoriy。希望它有所帮助。
供参考,请看这里:
答案 2 :(得分:1)
要添加角色,您需要有一个包含用户名及其相应角色的表。
假设用户具有两个角色,即ADMIN和USER
一个用户可以具有多个角色。
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
final List<SimpleGrantedAuthority> authorities = new LinkedList<>();
if (enabled) {
if (this.getUser().isAdmin()) {
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
}
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
}
return authorities;
}
这可以称为
private UsernamePasswordAuthenticationToken getAuthentication(
final String token, final HttpServletRequest req,
final HttpServletResponse res){
return new UsernamePasswordAuthenticationToken(userAccount, null,
userAccount.getAuthorities());
}
答案 3 :(得分:0)
您也可以通过这种方式使用 User.builder 对象加载角色或权限。此示例从 http 请求接收令牌,并获取 TOKEN 中的列表 o ROLES。你可以有一个简单的字符串列表,其中包含你需要的角色并加载到 UserDetail 实现中:
private UserDetails userDetails(final Claims claims) {
UserDetails userDetails = User.builder()
.username(resolveUserName(claims))
.password(resolveUserPassword())
.roles(userRoles(claims))
.build();
return userDetails;
}
其中 userRoles(claims) 只是返回一个字符串数组,其中包含您需要的所有角色。
希望能帮到你