Spring Security – REST API 的授权

huangapple go评论72阅读模式
英文:

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&lt;UsersAuth&gt; optionalUsers = usersAuthRepository.findByName(username);

    optionalUsers
            .orElseThrow(() -&gt; new UsernameNotFoundException(&quot;Username not found&quot;));
    return optionalUsers
            .map(CustomUserDetails::new).get();
}

CustomUserDeatils.java:

 @Override
public Collection&lt;? extends GrantedAuthority&gt; getAuthorities() {

    return getRoles()
            .stream()
            .map(role -&gt; new SimpleGrantedAuthority(&quot;ROLE_&quot; + 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&lt;UsersAuth&gt; optionalUsers = usersAuthRepository.findByName(username);

It is looking for user by his name probably inside databse or other in-memory store.

optionalUsers
            .orElseThrow(() -&gt; new UsernameNotFoundException(&quot;Username not found&quot;));

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 -&gt; new SimpleGrantedAuthority(&quot;ROLE_&quot; + 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&lt;? extends GrantedAuthority&gt; 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(&quot;ROLE_ADMIN&quot;)

答案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(&quot;hasAnyAuthority(&#39;CUSTOMER&#39;)&quot;)
@PostMapping(value = &quot;/abc&quot;)
  public ResponseEntity&lt;Map&lt;String, Integer&gt;&gt; create(@Valid @RequestBody DTO dto) {
  ...

The above api is accessible to only user with role CUSTOMER

huangapple
  • 本文由 发表于 2020年8月5日 17:50:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/63262620.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定