SpringSecurity框架原理浅谈之Authentication

我们来看一下Authentication(认证信息)的结构,它是一个接口,我们之前提到的 UsernamePasswordAuthenticationToken就是它的实现之一:

先看一下源码:

public interface Authentication extends Principal, Serializable { 
Collection<? extends GrantedAuthority> getAuthorities(); 
Object getCredentials(); 
Object getDetails(); 
Object getPrincipal(); 
boolean isAuthenticated();
void setAuthenticated(boolean var1) throws IllegalArgumentException;
}

再来看一下每个方法对应的意思:

最后看一下该接口的实现体系:

那Authentication是干什么的呢?

这里参考:Authentication详解_「已注销」的博客-CSDN博客_authentication.getprincipal()

(1). Authentication是spring security包中的接口,直接继承自Principal类,而Principal是位于java.security包中的。可以见得,Authentication在spring security中是最高级别的身份/认证的抽象。

(2).由这个顶级接口,我们可以得到用户拥有的权限信息列表,密码,用户细节信息,用户身份信息,认证信息。

在之前的浅谈AuthenticationManager文章中,我们知道了:当web表单提交用户名密码时,AuthenticationManager初始化委托AuthenticationProvider进行处理表单,AuthenticationProvider找到对应的DaoAuthenticationProvider进行认证处理。

认证成功后既得到一个 Authentication(UsernamePasswordAuthenticationToken实现),里面包含了身份信息(Principal)。这个身份 信息就是一个 Object ,大多数情况下它可以被强转为UserDetails对象。

所以我们从这里可以知道Authentication是用来封装用户的认证信息的!

接下来介绍几个常见的Authentication的实现类

这里引用:Spring Security:身份验证令牌Authentication介绍与Debug分析_spring访问令牌认证_ITKaven的博客-CSDN博客

UsernamePasswordAuthenticationToken

它是一种Authentication实现,继承AbstractAuthenticationToken抽象类,旨在简单地表示用户名和密码。principal和credentials属性应设置为通过其toString方法提供相应属性的Object,最简单的就是String类型。

public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationToken {

	private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;

	private final Object principal;
	private Object credentials;

	/**
	 * 任何希望创建UsernamePasswordAuthenticationToken实例的代码都可以安全地使用此构造函数
	 * 因为isAuthenticated()将返回false
	 */
	public UsernamePasswordAuthenticationToken(Object principal, Object credentials) {
		super(null);
		this.principal = principal;
		this.credentials = credentials;
		setAuthenticated(false);
	}

	/**
	 * 此构造函数只能由满足生成可信(即isAuthenticated() = true )身份验证令牌的AuthenticationManager或AuthenticationProvider实现使用
	 */
	public UsernamePasswordAuthenticationToken(Object principal, Object credentials,
			Collection<? extends GrantedAuthority> authorities) {
		super(authorities);
		this.principal = principal;
		this.credentials = credentials;
		super.setAuthenticated(true); // 必须使用super来设置
	}

    // 返回凭证(如密码)
	public Object getCredentials() {
		return this.credentials;
	}

    // 返回实体(如用户名)
	public Object getPrincipal() {
		return this.principal;
	}

    // 设置isAuthenticated属性,只能设置为false
	public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException {
	    // 无法将此令牌设置为受信任的令牌
	    // 需要使用有GrantedAuthority列表参数的构造函数
		if (isAuthenticated) {
			throw new IllegalArgumentException(
					"Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead");
		}

		super.setAuthenticated(false);
	}

    // 重写eraseCredentials方法
    // 将凭证直接设置为null
	@Override
	public void eraseCredentials() {
		super.eraseCredentials();
		credentials = null;
	}
}
RememberMeAuthenticationToken
它是一种Authentication实现,继承AbstractAuthenticationToken抽象类,表示需要记住的Authentication,需要记住的Authentication必须提供完全有效的Authentication ,包括适用的GrantedAuthority。

public class RememberMeAuthenticationToken extends AbstractAuthenticationToken {

	private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
	
	// 主体
	private final Object principal;
	// 识别此对象是否由授权客户生成的key的hashCode
	private final int keyHash;

	/**
	 * 构造函数
	 * 参数:
	 * key – 识别此对象是否由授权客户生成
	 * principal – 主体(通常是UserDetails)
	 * authorities — 授予主体的权限
	 */
	public RememberMeAuthenticationToken(String key, Object principal,
										Collection<? extends GrantedAuthority> authorities) {
		super(authorities);

		if ((key == null) || ("".equals(key)) || (principal == null)
				|| "".equals(principal)) {
			throw new IllegalArgumentException(
					"Cannot pass null or empty values to constructor");
		}

		this.keyHash = key.hashCode();
		this.principal = principal;
		setAuthenticated(true);
	}

	/**
	 * 帮助Jackson反序列化的私人构造函数
	 * 参数:
	 * keyHash – 上面给定key的hashCode
	 * principal – 主体(通常是UserDetails)
	 * authorities — 授予主体的权限
	 */
	private RememberMeAuthenticationToken(Integer keyHash, Object principal, Collection<? extends GrantedAuthority> authorities) {
		super(authorities);

		this.keyHash = keyHash;
		this.principal = principal;
		setAuthenticated(true);
	}

	/**
	 * 总是返回一个空String
	 */
	@Override
	public Object getCredentials() {
		return "";
	}

    // 返回keyHash 
	public int getKeyHash() {
		return this.keyHash;
	}

    // 返回主体
	@Override
	public Object getPrincipal() {
		return this.principal;
	}
}

PreAuthenticatedAuthenticationToken

它是一种Authentication实现,继承AbstractAuthenticationToken抽象类,用于预认证身份验证。有些情况下,希望使用Spring Security进行授权,但是在访问应用程序之前,用户已经被某个外部系统可靠地验证过了,将这种情况称为预认证场景,比如CSDN可以使用其他平台的账号进行登陆,如下图所示:

public class PreAuthenticatedAuthenticationToken extends AbstractAuthenticationToken {

	private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;

    // 主体
	private final Object principal;
	// 凭证
	private final Object credentials;

	/**
	 * 用于身份验证请求的构造函数
	 * isAuthenticated()将返回false 
	 */
	public PreAuthenticatedAuthenticationToken(Object aPrincipal, Object aCredentials) {
		super(null);
		this.principal = aPrincipal;
		this.credentials = aCredentials;
	}

	/**
	 * 用于身份验证响应的构造函数
	 * isAuthenticated()将返回true
	 */
	public PreAuthenticatedAuthenticationToken(Object aPrincipal, Object aCredentials,
			Collection<? extends GrantedAuthority> anAuthorities) {
		super(anAuthorities);
		this.principal = aPrincipal;
		this.credentials = aCredentials;
		setAuthenticated(true);
	}

	/**
	 * 返回凭证
	 */
	public Object getCredentials() {
		return this.credentials;
	}

	/**
	 * 返回主体
	 */
	public Object getPrincipal() {
		return this.principal;
	}
}

其余还有几种实现类解析,具体可去Spring Security:身份验证令牌Authentication介绍与Debug分析_spring访问令牌认证_ITKaven的博客-CSDN博客进行阅读

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr.huang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值