Reputation: 189
I am trying to implement role based authorization on my rest apis. I have been able to successfully implement and run the project but there are some things that I am confused about.
CustomeUserDetailsService.java:
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional<UsersAuth> optionalUsers = usersAuthRepository.findByName(username);
optionalUsers
.orElseThrow(() -> new UsernameNotFoundException("Username not found"));
return optionalUsers
.map(CustomUserDetails::new).get();
}
CustomUserDeatils.java:
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return getRoles()
.stream()
.map(role -> new SimpleGrantedAuthority("ROLE_" + role.getRole()))
.collect(Collectors.toList());
}
I want to know what the above two code snippets are actually doing. can someone explain to me? I have searched alot but did not understand. Specially what is the use of Granted authority? I know for a fact that CustomUserDetailsService is taking a username and if it does not exist, it throws an exception. If anyone could elaborate in detail? It would help me alot.
Upvotes: 0
Views: 546
Reputation: 1979
In the simplest way to answer, when you try to login with username and password, spring security calls loadUserByUsername
with that username you provide. This method looks in the database if any user exists with the username. If doesnt throws exception. Otherwise returns the UserDetails object. Then spring security checks if the password of UserDetails object matched with the password you have provided. If doesnt throws exception. Otherwise provides you authentication token.
User can have role and this role can be used to permit/block apis for that user. For example in the database that user has role CUSTOMER
and some other users have role ADMIN
. Now you want certain api /abc
to be exposed only to the users with CUSTOMER
role. For this you have to do this
@PreAuthorize("hasAnyAuthority('CUSTOMER')")
@PostMapping(value = "/abc")
public ResponseEntity<Map<String, Integer>> create(@Valid @RequestBody DTO dto) {
...
The above api is accessible to only user with role CUSTOMER
Upvotes: 1
Reputation: 1751
Optional<UsersAuth> optionalUsers = usersAuthRepository.findByName(username);
It is looking for user by his name probably inside databse or other in-memory store.
optionalUsers
.orElseThrow(() -> new UsernameNotFoundException("Username not found"));
As you already know this line will throw exception if Optional
is empty in other words user do not exist.
return optionalUsers
.map(CustomUserDetails::new).get();
This line creates new object of CustomUserDeatils
class that implements UserDetails
interface and returns it. CustomUserDeatils
has constructor with UsersAuth
parameter.
return getRoles()
.stream()
.map(role -> new SimpleGrantedAuthority("ROLE_" + role.getRole()))
.collect(Collectors.toList());
This is simple mapping of probably Role
collection to SimpleGrantedAuthority
list. As I mentioned earlier CustomUserDeatils
class implements UserDetails. One of its method is Collection<? extends GrantedAuthority> getAuthorities()
which is used to get info about authorities granted to user. AuthenticationProvider
will use this info from UserDetailsService
to create Authentication
object. Spring Security will be checking if authenticated user has required roles etc using this mapped roles. SimpleGrantedAuthority
is just implementation of GrantedAuthority
. ROLE_
is default prefix used by RoleVoter
when you are checking for roles in your controller method e.g @Secured("ROLE_ADMIN")
Upvotes: 1