在之前的博客中,已经介绍了Spring Security的用户UserDetails、用户服务UserDetailsService和密码编码器PasswordEncoder,它们都是用于验证用户的身份,而GrantedAuthority则表示用户验证通过后被授予的权限(可能授予多种权限),本篇博客介绍GrantedAuthority接口及其实现类。

应用的依赖:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.kaven</groupId>
    <artifactId>security</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.1.RELEASE</version>
    </parent>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>
</project>

启动类:

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class);
    }
}

GrantedAuthority

GrantedAuthority接口源码:

package org.springframework.security.core;

import java.io.Serializable;

import org.springframework.security.access.AccessDecisionManager;

/**
 * 表示授予Authentication对象(需要进行验证或通过验证的用户封装)的权限
 */
public interface GrantedAuthority extends Serializable {

	/**
	 * 获取权限
	 */
	String getAuthority();
}

GrantedAuthority接口及其实现类,如下图所示:
在这里插入图片描述

SimpleGrantedAuthority

GrantedAuthority的基本具体实现,存储授予Authentication对象的权限的String表示形式。

SimpleGrantedAuthority类源码:

public final class SimpleGrantedAuthority implements GrantedAuthority {

	private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;

    // 授予Authentication对象的权限
	private final String role;

	public SimpleGrantedAuthority(String role) {
		Assert.hasText(role, "A granted authority textual representation is required");
		this.role = role;
	}

	@Override
	public String getAuthority() {
		return role;
	}

    // 只会比较role属性是否equals
	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}

		if (obj instanceof SimpleGrantedAuthority) {
			return role.equals(((SimpleGrantedAuthority) obj).role);
		}

		return false;
	}

	@Override
	public int hashCode() {
		return this.role.hashCode();
	}

	@Override
	public String toString() {
		return this.role;
	}
}

增加配置文件:

spring:
  security:
    user:
      name: kaven
      password: itkaven
      roles:
        - USER
        - ADMIN

Debug启动应用,Spring Security在应用启动时会创建配置文件中定义的用户,首先会创建用户服务(InMemoryUserDetailsManagerbean
在这里插入图片描述
通过用户服务创建用户,并且授予权限(通过创建SimpleGrantedAuthority实例)。
在这里插入图片描述
可见,SimpleGrantedAuthority是默认的授权实现(特殊场景除外),它只存储权限,是一种简易的授权实现。

JaasGrantedAuthority

JaasGrantedAuthority类源码:

/**
 * 除了分配的角色,还持有授权人(AuthorityGranter)的主体(Principal),用作授予此权限的理由
 */
public final class JaasGrantedAuthority implements GrantedAuthority {

	private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;

	private final String role;
	// 授权人的主体
	private final Principal principal;

	public JaasGrantedAuthority(String role, Principal principal) {
		Assert.notNull(role, "role cannot be null");
		Assert.notNull(principal, "principal cannot be null");
		this.role = role;
		this.principal = principal;
	}

	public Principal getPrincipal() {
		return principal;
	}

	@Override
	public String getAuthority() {
		return role;
	}

	@Override
	public int hashCode() {
		int result = this.principal.hashCode();
		result = 31 * result + this.role.hashCode();
		return result;
	}

    // 判断role属性和principal属性是否都equals
	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}

		if (obj instanceof JaasGrantedAuthority) {
			JaasGrantedAuthority jga = (JaasGrantedAuthority) obj;
			return this.role.equals(jga.role) && this.principal.equals(jga.principal);
		}

		return false;
	}

	@Override
	public String toString() {
		return "Jaas Authority [" + role + "," + principal + "]";
	}
}

AuthorityGranter接口源码:

/**
 * AuthorityGranter接口用于将给定的主体映射到角色名称集合
 */
public interface AuthorityGranter {
	/**
	 * 根据主体映射到角色名称集合
	 */
	Set<String> grant(Principal principal);
}

在这里插入图片描述
JaasGrantedAuthority是一种用于Java 验证和授权服务(Java Authentication and Authorization Service,简称JAAS)场景下的授权实现,感兴趣可自行了解JAAS

SwitchUserGrantedAuthority

SwitchUserGrantedAuthority类源码:

/**
 * SwitchUserFilter使用的自定义GrantedAuthority
 * 存储原始用户的Authentication对象,以便从退出用户切换时使用。
 */
public final class SwitchUserGrantedAuthority implements GrantedAuthority {

	private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
	
	private final String role;
	// 存储原始用户的Authentication对象
	private final Authentication source;

	public SwitchUserGrantedAuthority(String role, Authentication source) {
		Assert.notNull(role, "role cannot be null");
		Assert.notNull(source, "source cannot be null");
		this.role = role;
		this.source = source;
	}

	/**
	 * 返回与成功的用户切换关联的原始用户
	 */
	public Authentication getSource() {
		return source;
	}

	@Override
	public String getAuthority() {
		return role;
	}

	@Override
	public int hashCode() {
		int result = this.role.hashCode();
		result = 31 * result + this.source.hashCode();
		return result;
	}

    // 判断role属性和source属性是否都equals
	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}

		if (obj instanceof SwitchUserGrantedAuthority) {
			SwitchUserGrantedAuthority swa = (SwitchUserGrantedAuthority) obj;
			return this.role.equals(swa.role) && this.source.equals(swa.source);
		}

		return false;
	}

	@Override
	public String toString() {
		return "Switch User Authority [" + role + "," + source + "]";
	}
}

该授权实现类似于Linux系统下用户之间的切换授权(使用su命令的权限),如下所示在Linux系统中添加kaven用户,然后从root用户切换到kaven用户(root用户有这个权限)。

root@48556522ad65:~# adduser kaven
Adding user `kaven' ...
Adding new group `kaven' (1000) ...
Adding new user `kaven' (1000) with group `kaven' ...
Creating home directory `/home/kaven' ...
Copying files from `/etc/skel' ...
New password: 
Retype new password: 
passwd: password updated successfully
Changing the user information for kaven
Enter the new value, or press ENTER for the default
	Full Name []: 
	Room Number []: 
	Work Phone []: 
	Home Phone []: 
	Other []: 
Is the information correct? [Y/n] Y
root@48556522ad65:~# su kaven
kaven@48556522ad65:/root$

SwitchUserGrantedAuthoritySwitchUserFilter使用的自定义GrantedAuthoritySwitchUserFilter(用户切换处理过滤器)负责用户上下文切换,对于Spring Security管理的web应用程序,此过滤器类似于su命令,此功能的一个常见例子是能够允许更高权限的用户(如ROLE_ADMIN)切换到普通用户(如ROLE_USER)。Spring Security的过滤器以及如何将自定义的过滤器集成到Spring Security中,博主以后会进行介绍,这里只是了解即可。
在这里插入图片描述

所以,SwitchUserGrantedAuthority是一种用于用户切换场景下的授权实现,不仅存储了权限,还存储了原始用户的Authentication对象,即source属性,方便用户切换的退出。

kaven@48556522ad65:/root$ exit
exit
root@48556522ad65:~# exit
logout
Connection closing...Socket close.

Connection closed by foreign host.

Disconnected from remote host(predict) at 13:40:23.

Type `help' to learn how to use Xshell prompt.
[C:\~]$ 

Spring Security的授权GrantedAuthority介绍就到这里,如果博主有说错的地方或者大家有不同的见解,欢迎大家评论补充。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐