Granted Authority Versus Role in Spring Security – 授予的权力与Spring安全中的作用

最后修改: 2017年 9月 24日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this quick article, we’ll explain the subtle but significant difference between a Role and a GrantedAuthority in Spring Security. For more detailed information on roles and authorities, see the article here.

在这篇简短的文章中,我们将解释Spring Security中RoleGrantedAuthority之间微妙而重要的区别。有关角色和权限的更多详细信息,请参阅文章这里

2. GrantedAuthority

2.获得授权

In Spring Security, we can think of each GrantedAuthority as an individual privilege. Examples could include READ_AUTHORITY, WRITE_PRIVILEGE, or even CAN_EXECUTE_AS_ROOT. The important thing to understand is that the name is arbitrary.

在Spring Security中,我们可以将每个GrantedAuthority视为一个单独的权限。例子包括READ_AUTHORITYWRITE_PRIVILEGE,甚至是CAN_EXECUTE_AS_ROOT。需要理解的是,名称是任意的

When using a GrantedAuthority directly, such as through the use of an expression like hasAuthority(‘READ_AUTHORITY’), we are restricting access in a fine-grained manner.

当直接使用GrantedAuthority时,例如通过使用类似hasAuthority(‘READ_AUTHORITY’)的表达式,我们正在以精细的方式限制访问

As you can probably gather, we can refer to the concept of authority by using privilege as well.

正如你可能知道的那样,我们也可以通过使用特权来指代权力的概念。

3. Role as Authority

3.作为权威的角色

Similarly, in Spring Security, we can think of each Role as a coarse-grained GrantedAuthority that is represented as a String and prefixed with “ROLE. When using a Role directly, such as through an expression like hasRole(“ADMIN”), we are restricting access in a coarse-grained manner.

同样,在 Spring Security 中,我们可以将每个Role 视为GrantedAuthority,它被表示为String并以”ROLE“作为前缀。当直接使用Role时,例如通过hasRole(“ADMIN”)这样的表达式,我们是以粗略的方式限制访问。

It is worth noting that the default “ROLE” prefix is configurable, but explaining how to do that is beyond the scope of this article.

值得注意的是,默认的”ROLE”前缀是可配置的,但解释如何做到这一点超出了本文的范围。

The core difference between these two is the semantics we attach to how we use the feature. For the framework, the difference is minimal – and it basically deals with these in exactly the same way.

这两者之间的核心区别在于我们对如何使用该功能所附加的语义。对于框架来说,区别很小–而且它基本上以完全相同的方式处理这些。

4. Role as Container

4.作为容器的作用

Now that we’ve seen how the framework uses the role concept, let’s also quickly discuss an alternative – and that is using roles as containers of authorities/privileges.

现在我们已经看到了框架是如何使用角色概念的,让我们也快速讨论一下另一种选择–那就是使用角色作为权限/特权的容器

This is a higher level approach to roles – making them a more business-facing concept rather than an implementation-centric one.

这是一种更高层次的角色方法–使其成为一个更面向业务的概念,而不是一个以实施为中心的概念。

The Spring Security framework doesn’t give any guidance in terms of how we should use the concept, so the choice is entirely implementation specific.

在我们应该如何使用这个概念方面,Spring Security框架并没有给出任何指导,所以这个选择完全是具体实施的。

5. Spring Security Configuration

5.Spring安全配置

We can demonstrate a fine-grained authorization requirement by restricting access to /protectedbyauthority to users with READ_AUTHORITY.

我们可以通过限制具有READ_AUTHORITY的用户访问/protectedbyauthority来证明细粒度的授权要求。

We can demonstrate a coarse-grained authorization requirement by restricting access to /protectedbyrole to users with ROLE_USER.

我们可以通过限制具有ROLE_USER的用户访问/protectedbyrole来证明一个粗粒度的授权要求。

Let’s configure such a scenario in our security configuration:

让我们在我们的安全配置中配置这样一个场景。

@Override
protected void configure(HttpSecurity http) throws Exception {
    // ...
    .antMatchers("/protectedbyrole").hasRole("USER")
    .antMatchers("/protectedbyauthority").hasAuthority("READ_PRIVILEGE")
    // ...
}

6. Simple Data Init

6.简单的数据启动

Now that we understand the core concepts better, let’s talk about creating some setup data when the application starts up.

现在我们更好地理解了核心概念,让我们谈谈在应用程序启动时创建一些设置数据的问题。

This is, of course, a very simple way of doing that, to hit the ground running with some preliminary test users during development – not the way you should handle data in production.

当然,这是一个非常简单的方法,在开发过程中用一些初步的测试用户来打基础–这不是你在生产中应该处理数据的方式。

We’re going to be listening for the context refresh event:

我们将监听上下文刷新事件。

@Override
@Transactional
public void onApplicationEvent(ContextRefreshedEvent event) {
    MyPrivilege readPrivilege
      = createPrivilegeIfNotFound("READ_PRIVILEGE");
    MyPrivilege writePrivilege
      = createPrivilegeIfNotFound("WRITE_PRIVILEGE"); 
}

The actual implementation here doesn’t really matter – and generally, depends on the persistence solution you’re using. The main point is – we’re persisting the authorities we’re using in the code.

这里的实际实现其实并不重要–一般来说,取决于你所使用的持久化解决方案。主要的一点是–我们正在持久化我们在代码中使用的权限。

7. UserDetailsService

7.UserDetailsService

Our implementation of UserDetailsService is where the authority mapping takes place. Once the user has authenticated, our getAuthorities() method populates and returns a UserDetails object:

我们对UserDetailsService的实现是权限映射发生的地方。一旦用户通过了认证,我们的getAuthorities()方法就会填充并返回一个UserDetails对象。

private Collection<? extends GrantedAuthority> getAuthorities(
  Collection<Role> roles) {
    List<GrantedAuthority> authorities
      = new ArrayList<>();
    for (Role role: roles) {
        authorities.add(new SimpleGrantedAuthority(role.getName()));
        role.getPrivileges().stream()
         .map(p -> new SimpleGrantedAuthority(p.getName()))
         .forEach(authorities::add);
    }
    
    return authorities;
}

8. Running and Testing the Example

8.运行和测试示例

We can execute the example RolesAuthoritiesApplication Java application, found in the GitHub project.

我们可以执行例子RolesAuthoritiesApplication Java应用程序,在GitHub项目中找到。

To see the role-based authorization in action, we need to:

为了看到基于角色的授权,我们需要:

  • Access http://localhost:8082/protectedbyrole
  • Authenticate as user@test.com (password is “user”)
  • Note successful authorization
  • Access http://localhost:8082/protectedbyauthority
  • Note unsuccessful authorization

To see authority-based authorization in action, we need to log out of the application and then:

为了看到基于权限的授权在运作,我们需要注销应用程序,然后:

  • Access http://localhost:8082/protectedbyauthority
  • Authenticate as admin@test.com / admin
  • Note successful authorization
  • Access http://localhsot:8082/protectedbyrole
  • Note unsuccessful authorization

9. Conclusion

9.结论

In this quick tutorial, we looked at the subtle but significant difference between a Role and a GrantedAuthority in Spring Security.

在这个快速教程中,我们研究了Spring Security中RoleGrantedAuthority之间微妙但重要的区别。