Spring Security / Spring Boot - 如何为用户设置ROLES

时间:2016-06-03 12:57:38

标签: java spring spring-mvc spring-security spring-boot

当我使用安全性登录时,我无法使用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")也不起作用。

4 个答案:

答案 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
);

示例:sample1 sample2 sample3

在DB中,您可以将角色名称存储为 - (例如)数据库中的ADMIN / EDITOR / VIEWER,​​或者将角色存储为ROLE_ADMIN / ROLE _...然后您可能想要使用hasRole / hasAuthoriy。希望它有所帮助。

供参考,请看这里:

Spring Security Related 1

Spring Security Related 2

答案 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) 只是返回一个字符串数组,其中包含您需要的所有角色。

希望能帮到你