我正在尝试在我的其余 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();
}
CustomUserDetils.java:
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return getRoles()
.stream()
.map(role -> new SimpleGrantedAuthority("ROLE_" + role.getRole()))
.collect(Collectors.toList());
}
我想知道上面两个代码片段实际上是做什么的。有人可以向我解释一下吗?我搜索了很多但不明白。特别是授予权限有什么用?我知道 CustomUserDetailsService 正在获取用户名,如果它不存在,则会抛出异常。如果有人能详细说一下吗?这对我有很大帮助。
Optional<UsersAuth> optionalUsers = usersAuthRepository.findByName(username);
它可能正在数据库或其他内存存储中按用户名查找用户。
optionalUsers
.orElseThrow(() -> new UsernameNotFoundException("Username not found"));
正如您所知,如果
Optional
为空(换句话说用户不存在),此行将引发异常。
return optionalUsers
.map(CustomUserDetails::new).get();
此行创建
CustomUserDeatils
类的新对象,该类实现 UserDetails
接口并返回它。 CustomUserDeatils
具有带有 UsersAuth
参数的构造函数。
return getRoles()
.stream()
.map(role -> new SimpleGrantedAuthority("ROLE_" + role.getRole()))
.collect(Collectors.toList());
这是可能的
Role
集合到 SimpleGrantedAuthority
列表的简单映射。正如我之前提到的,CustomUserDeatils
类实现了UserDetails。它的方法之一是 Collection<? extends GrantedAuthority> getAuthorities()
,用于获取有关授予用户的权限的信息。 AuthenticationProvider
将使用 UserDetailsService
中的信息来创建 Authentication
对象。 Spring Security 将使用此映射角色检查经过身份验证的用户是否具有所需的角色等。 SimpleGrantedAuthority
只是 GrantedAuthority
的实现。 ROLE_
是 RoleVoter
在检查控制器方法中的角色时使用的默认前缀,例如 @Secured("ROLE_ADMIN")
以最简单的方式回答,当您尝试使用用户名和密码登录时,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