英文:
Spring Security - Authrozation on rest apis
问题
我正在尝试在我的REST API上实现基于角色的授权。我已经成功地实现并运行了这个项目,但有一些事情让我感到困惑。
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());
}
我想知道上面两段代码实际在做什么。有人可以解释一下吗?我已经搜索了很多,但没有理解。特别是授予权限(Granted Authority)的用途是什么?我知道CustomUserDetailsService接受一个用户名,如果不存在,它会抛出异常。如果有人能详细解释一下,对我会非常有帮助。
英文:
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.
答案1
得分: 1
Optional<UsersAuth> optionalUsers = usersAuthRepository.findByName(username);
这行代码在数据库或其他内存存储中,通过用户名查找用户。
optionalUsers
.orElseThrow(() -> new UsernameNotFoundException("Username not found"));
正如你已经知道的,如果Optional
为空,也就是用户不存在,这行代码会抛出异常。
return optionalUsers
.map(CustomUserDetails::new).get();
这行代码创建了一个CustomUserDetails
类的新对象,该类实现了UserDetails
接口,并返回它。CustomUserDetails
类具有带有UsersAuth
参数的构造函数。
return getRoles()
.stream()
.map(role -> new SimpleGrantedAuthority("ROLE_" + role.getRole()))
.collect(Collectors.toList());
这是将可能的Role
集合映射到SimpleGrantedAuthority
列表的简单操作。如前所述,CustomUserDetails
类实现了UserDetails接口。其中一个方法是Collection<? extends GrantedAuthority> getAuthorities()
,用于获取分配给用户的权限信息。AuthenticationProvider
将使用UserDetailsService
中的此信息来创建Authentication
对象。Spring Security将使用这些映射的角色来检查经过身份验证的用户是否具有所需的角色,等等。SimpleGrantedAuthority
只是GrantedAuthority
的一种实现。ROLE_
是在控制器方法中检查角色时由RoleVoter
使用的默认前缀,例如@Secured("ROLE_ADMIN")
。
英文:
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")
答案2
得分: 1
以最简单的方式回答,当您尝试使用用户名和密码登录时,Spring Security 会调用 loadUserByUsername
方法,并使用您提供的用户名。此方法在数据库中查找是否存在具有该用户名的用户。如果不存在,则抛出异常。否则,返回 UserDetails 对象。然后,Spring Security 检查 UserDetails 对象的密码是否与您提供的密码匹配。如果不匹配,则抛出异常。否则,提供身份验证令牌。
用户可以具有角色,该角色可以用于允许/阻止该用户的API。例如,数据库中的用户具有角色 CUSTOMER
,而其他一些用户具有角色 ADMIN
。现在,您希望某些API /abc
仅对具有 CUSTOMER
角色的用户开放。为此,您必须执行以下操作:
@PreAuthorize("hasAnyAuthority('CUSTOMER')")
@PostMapping(value = "/abc")
public ResponseEntity<Map<String, Integer>> create(@Valid @RequestBody DTO dto) {
...
}
上述API只对具有角色 CUSTOMER
的用户可访问。
英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论