How to enable or disable user in Spring Boot Security

Viewed 10130

I am using spring security for my spring boot app ,this is my user entity

@Document(collection = "users")
public class User {
    @Id
    private String id;

    private String username;


    private String isactive;
    private String type;
    private String date;

    private String registrarid;
    private String registrartype;

    public String getRegistrarid() {
        return registrarid;
    }
    public void setRegistrarid(String registrarid) {
        this.registrarid = registrarid;
    }
    public String getRegistrartype() {
        return registrartype;
    }
    public void setRegistrartype(String registrartype) {
        this.registrartype = registrartype;
    }
    public String getIsactive() {
        return isactive;
    }
    public void setIsactive(String isactive) {
        this.isactive = isactive;
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        long temp;
        temp = Double.doubleToLongBits(balance);
        result = prime * result + (int) (temp ^ (temp >>> 32));
        result = prime * result + ((date == null) ? 0 : date.hashCode());
        result = prime * result + (enabled ? 1231 : 1237);
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        result = prime * result + ((isactive == null) ? 0 : isactive.hashCode());
        result = prime * result + ((password == null) ? 0 : password.hashCode());
        result = prime * result + ((registrarid == null) ? 0 : registrarid.hashCode());
        result = prime * result + ((registrartype == null) ? 0 : registrartype.hashCode());
        result = prime * result + ((roles == null) ? 0 : roles.hashCode());
        result = prime * result + ((type == null) ? 0 : type.hashCode());
        result = prime * result + ((username == null) ? 0 : username.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        User other = (User) obj;
        if (Double.doubleToLongBits(balance) != Double.doubleToLongBits(other.balance))
            return false;
        if (date == null) {
            if (other.date != null)
                return false;
        } else if (!date.equals(other.date))
            return false;
        if (enabled != other.enabled)
            return false;
        if (id == null) {
            if (other.id != null)
                return false;
        } else if (!id.equals(other.id))
            return false;
        if (isactive == null) {
            if (other.isactive != null)
                return false;
        } else if (!isactive.equals(other.isactive))
            return false;
        if (password == null) {
            if (other.password != null)
                return false;
        } else if (!password.equals(other.password))
            return false;
        if (registrarid == null) {
            if (other.registrarid != null)
                return false;
        } else if (!registrarid.equals(other.registrarid))
            return false;
        if (registrartype == null) {
            if (other.registrartype != null)
                return false;
        } else if (!registrartype.equals(other.registrartype))
            return false;
        if (roles == null) {
            if (other.roles != null)
                return false;
        } else if (!roles.equals(other.roles))
            return false;
        if (type == null) {
            if (other.type != null)
                return false;
        } else if (!type.equals(other.type))
            return false;
        if (username == null) {
            if (other.username != null)
                return false;
        } else if (!username.equals(other.username))
            return false;
        return true;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getDate() {
        return date;
    }
    public void setDate(String date) {
        this.date = date;
    }

    private double balance;
    public double getBalance() {
        return balance;
    }
    public void setBalance(double balance) {
        this.balance = balance;
    }



    private boolean enabled=true;

    @DBRef
    private Set<Role> roles;


    private String password;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    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 + ", username=" + username + ", isactive=" + isactive + ", type=" + type + ", date="
                + date + ", registrarid=" + registrarid + ", registrartype=" + registrartype + ", balance=" + balance
                + ", enabled=" + enabled + ", roles=" + roles + ", password=" + password + "]";
    }




}

This is my CustomUser Details Service

@Service
public class CustomUserDetailsService implements UserDetailsService{
    @Autowired
    private UserServiceImpl userservice;

    @Autowired
    private RoleServiceImpl roleservice;



    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // TODO Auto-generated method stub
        User user=userservice.getUserByusername(username);

            if(user != null) {
                List<GrantedAuthority> authorities = getUserAuthority(user.getRoles());
                return buildUserForAuthentication(user, authorities);
            } 

            else {
                throw new UsernameNotFoundException("username not found");
            }

    }

    private List<GrantedAuthority> getUserAuthority(Set<Role> userRoles) {
        Set<GrantedAuthority> roles = new HashSet<>();
        userRoles.forEach((role) -> {
            roles.add(new SimpleGrantedAuthority(role.getRole()));
        });

        List<GrantedAuthority> grantedAuthorities = new ArrayList<>(roles);
        return grantedAuthorities;
    }

    private UserDetails buildUserForAuthentication(User user, List<GrantedAuthority> authorities) {
        return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), authorities);
    }

}

Currently Custom UserDetails ServiceChecks if username exists or not and then if not found throws exception ,I want to check if the user is enabled or not as well in that ,so that I can set isenabled false as well to deactivate the users.

3 Answers

Just Check for is enabled in loadByUsername method ,Further you can activate and deactivate accordingly.I hope it helps

@Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // TODO Auto-generated method stub
        User user=userservice.getUserByusername(username);

            if(user != null && user.isEnabled()) {//here you can check that
                List<GrantedAuthority> authorities = getUserAuthority(user.getRoles());
                return buildUserForAuthentication(user, authorities);
            } 

            else {
                throw new UsernameNotFoundException("username not found");
            }

    }

A better approach would be to implement your User entity with org.springframework.security.core.userdetails.UserDetails and override various methods like

@Override
public boolean isAccountNonExpired() {
    return true;
}

@Override
public boolean isAccountNonLocked() {
    return true;
}

@Override
public boolean isCredentialsNonExpired() {
    return true;
}

@Override
public boolean isEnabled() {
    if(this.isactive == null) return false;

    if(!this.isactive.equals("ACTIVE")) return false;

    return true;
}

Override other methods also as required. Spring Security will automatically give org.springframework.security.authentication.DisabledException: User is disabled exception based on isEnabled() result.

If you want to persist the enabled or locked status in the database then you would want to pass the getters for the locked and enabled fields from the User model instance to the UserDetailsImpl constructor.

Firstly, The authenticate function of the authenticationManager returns these exceptions:

  1. DisabledException, if an account is disabled
  2. LockedException, if an account is locked
  3. BadCredentialsException, if incorrect credentials are presented

You would want to do something along the lines of this:

try {

    Authentication authentication = authenticationManager.authenticate(
            new UsernamePasswordAuthenticationToken(authreq.getUsername(), authreq.getPassword()));
} catch (BadCredentialsException ex) {
    // do something
} catch (LockedException ex) {
    // do something
} catch (DisabledException ex) {
    // do something
}

And then in the UserDetailsImpl:

public UserDetailsImpl(Integer id, String username, String email, String password,
            Collection<? extends GrantedAuthority> authorities, boolean isEnabled) {
        this.id = id;
        this.username = username;
        this.email = email;
        this.password = password;
        this.authorities = authorities;
        this.isEnabled = isEnabled;
    }

    public static UserDetailsImpl build(User user) {
        List<GrantedAuthority> authorities = user.getRoles().stream()
                .map(role -> new SimpleGrantedAuthority(role.getName().name())).collect(Collectors.toList());

        return new UserDetailsImpl(user.getId(), user.getUsername(), user.getEmail(), user.getPassword(), authorities,
                user.isIsenabled());
    }

By the way, in order for this to work you must remove the if statement from the previous answer by @Shubh, instead just have this: return buildUserForAuthentication(user, authorities); I think this is pretty much what you are looking for.

Related