简体   繁体   中英

Spring Security Set Role On Registration

I'm new to Spring security, so I've followed some tutorials but I'm having trouble understanding how the structure of roles really works under the hood. I have two tables, one for the User:

        @Entity
        @Table(name = "UserProfile", schema = "dbo", catalog = "DevTestTeam")
        public class UserProfileEntity implements UserDetails{

            @Id
            @GeneratedValue(strategy = GenerationType.IDENTITY)
            @Column(name = "id", nullable = false)
            private long id;

            @Column(name = "enabled", nullable = false)
            private boolean enabled;

            @NotEmpty(message = "Enter a password.")
            @Size(min = 6, max = 15, message = "Password must be between 6 and 15 characters.")
            @Column(name = "password", nullable = true, length = 100)
            private String password;

            @NotEmpty(message = "Enter a username.")
            @Size(min = 6, max = 20, message = "Username must be between 6 and 20 characters.")
            @Column(name = "username", nullable = true, length = 20, unique = true)
            private String username;

            @OneToOne
            @JoinColumn(name = "role_id")
            private RoleEntity role;

            public RoleEntity getRole() {
                return role;
            }

            public void setRole(RoleEntity role) {
                this.role = role;
            }

            @Override
            public Collection<? extends GrantedAuthority> getAuthorities() {
                List<GrantedAuthority> authorities = new ArrayList<>();
                authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
                return authorities;
            }

and one for the role:

@Entity
@Table(name = "Role", schema = "dbo", catalog = "DevTestTeam")
public class RoleEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private long id;

@Column(name = "name", nullable = true, length = 255)
private String name;

public long getId() {
    return id;
}

public void setId(long id) {
    this.id = id;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

My confusion comes when creating a new user. I have a registration form backed by a UserProfileEntity object, and that populates the username and password. Then obviously it's easy to setEnabled()=true (I left some of the getters/setters out of this code for clarity).

My question is how to set the role when instantiating a UserProfileEntity to be saved in the database. My role_id foreign key should just take an integer and return the role from the Role table, but I'm not sure how to express this when instantiating. I have a ROLE_USER in the roles table with an id of 1, and I feel like this is pretty simple to instantiate but I can't find the answer I'm looking for.

UserImpl:

@Service
public class UserProfileServiceImpl implements UserProfileService{
@Autowired
private UserProfileDao userDao;

@Override
public UserProfileEntity findByUser(String username) {
    return userDao.findByUsername(username);
}

@Override
public List<UserProfileEntity> findAll() {
    List<UserProfileEntity> list = userDao.findAll();
    return list;
}

@Override
public UserProfileEntity save(UserProfileEntity persisted) {
    userDao.save(persisted);
    return null;
}

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    UserProfileEntity user = userDao.findByUsername(username);
    if (user == null) {
        throw new UsernameNotFoundException("User not found.");
    }

    return user;
}

}

You'll need some repository method to obtain user role by name:

RoleEntity roleEntity = roleEntityRepository.findByName("ROLE_USER");

Then set that RoleEntity to UserProfileEntity before persisting it:

UserProfileEntity userProfileEntity = new UserProfileEntity();
userProfileEntity.setRoleEntity(roleEntity);
userService.save(userProfileEntity);

What you also want is to leave your UserProfileEntity unextended. For Spring Security, you'll need UserDetailsService implementation:

@Service("userDetailsService")
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        UserProfileEntity userProfileEntity = userRepository.findByUsername(username);

        if (userProfileEntity == null) {
            throw new UsernameNotFoundException("Non existing user!");
        }

        return new org.springframework.security.core.userdetails.User(userProfileEntity.getUsername(),
                userProfileEntity.getPassword(),
                Arrays.asList(new SimpleGrantedAuthority(userByUsername.getRoleEntity().getName())));
    }

}

However, I see that your requirements are quite simple - one role per user. Therefore, your RoleEntity could simply be an enum with predefined roles:

public enum RoleEntity {
    ROLE_USER
}

And in UserProfileEntity you'd use it like this:

public class UserProfileEntity {
    @Enumerated(EnumType.STRING)
    private RoleEntity roleEntity;
}

To persist user with role:

UserProfileEntity userProfileEntity = new UserProfileEntity();
userProfileEntity.setRoleEntity(RoleEntity.USER);
userService.save(userProfileEntity);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM