跳至主要內容

AnonymousAuthenticationFilter

Jin大约 6 分钟

AnonymousAuthenticationFilter

1、概述

AnonymousAuthenticationFilter 负责为未认证(即匿名)的用户提供一个身份认证对象。这个过滤器的作用是确保在用户尚未进行身份验证时,能够创建一个默认的匿名身份,并将其添加到 SecurityContext 中。它确保在认证流程尚未开始时,仍然能够为请求提供基本的匿名用户身份。

1.1、为什么需要 AnonymousAuthenticationFilter

Spring Security 的身份认证系统通常假设每个请求都会有一个已认证的 Authentication 对象(如通过 UsernamePasswordAuthenticationFilterOAuth2LoginAuthenticationFilter 获得)。但是,对于未经过身份验证的用户(即匿名用户),Spring Security 依然需要处理它们的身份。

AnonymousAuthenticationFilter 就是为这个目的存在的:它为所有未认证的用户提供一个默认的身份认证对象,确保系统能够处理匿名请求。

1.2、SecurityContextAuthentication 对象

Spring Security 通过 SecurityContext 存储当前请求的认证信息,SecurityContext 中通常保存一个 Authentication 对象。Authentication 代表当前用户的认证状态,包含了该用户的身份(principal)、凭证(credentials)以及权限(authorities)。

在匿名用户的情况下,Authentication 对象并不会携带有效的认证凭据,但 AnonymousAuthenticationFilter 会将一个 AnonymousAuthenticationToken 放入 SecurityContext 中,使得即使是未认证的请求,也有一个占位符身份。

2、工作原理

2.1、默认行为

  • 匿名身份认证对象:当请求没有有效的认证信息时,AnonymousAuthenticationFilter 会创建一个 AnonymousAuthenticationToken 实例。该实例将会包含:
    • principal: 默认值为 anonymousUser,也可以通过配置自定义。
    • credentials: 通常为空或无效。
    • authorities: 默认情况下为空或包含匿名角色(例如 ROLE_ANONYMOUS),可以通过配置进行修改。
  • 过滤器链中的执行顺序AnonymousAuthenticationFilter 在 Spring Security 的过滤器链中通常处于较早的位置,通常是在其他认证过滤器(如 UsernamePasswordAuthenticationFilter)之前运行。
  • SecurityContextAnonymousAuthenticationFilter 会将创建的匿名 Authentication 对象存放到 SecurityContextHolder 中,这样后续的过滤器或应用逻辑就能够获取到这个匿名身份,并决定是否需要进一步处理。

2.2、代码层面

AnonymousAuthenticationFilter 是一个继承自 AbstractAuthenticationProcessingFilter 的过滤器,其核心的认证处理逻辑是在 doFilter 方法中实现的。

public class AnonymousAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    private final String principal;
    private final Collection<? extends GrantedAuthority> authorities;

    public AnonymousAuthenticationFilter(String principal, Collection<? extends GrantedAuthority> authorities) {
        super("/**"); // 匹配所有路径
        this.principal = principal;
        this.authorities = authorities;
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        Authentication existingAuthentication = SecurityContextHolder.getContext().getAuthentication();
        
        // 如果当前请求没有身份认证信息且没有被禁用匿名认证
        if (existingAuthentication == null || existingAuthentication instanceof AnonymousAuthenticationToken) {
            Authentication token = new AnonymousAuthenticationToken(
                "anonymous", this.principal, this.authorities
            );
            SecurityContextHolder.getContext().setAuthentication(token);  // 将匿名身份放入 SecurityContext
        }
        return null;  // 不需要处理任何请求,交由后续的过滤器处理
    }
}

doFilter 方法中,AnonymousAuthenticationFilter 会检查当前的 SecurityContext 是否已存在认证信息。如果没有认证信息,且匿名认证没有被禁用,它会创建一个新的 AnonymousAuthenticationToken,并将其设置到 SecurityContext 中。

3、默认配置与自定义配置

3.1、默认配置

在 Spring Security 6.x 中,AnonymousAuthenticationFilter 是自动启用的,默认情况下,它的配置如下:

  • 匿名用户名"anonymousUser"
  • 权限ROLE_ANONYMOUS
  • 认证对象类型AnonymousAuthenticationToken

通过这些默认配置,Spring Security 能够为所有未认证的用户创建一个简单的匿名身份。

3.2、配置匿名身份

可以通过 Spring Security 的配置类来定制匿名认证的行为,例如更改匿名用户的 principal 名称,或者为匿名用户分配特定的角色。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/public/**").permitAll()  // 公共资源
                .anyRequest().authenticated()  // 其它请求需要认证
            .and()
            .anonymous()
                .principal("guest")  // 配置匿名用户的用户名为 "guest"
                .authorities(new SimpleGrantedAuthority("ROLE_GUEST"))  // 配置匿名用户的角色为 "ROLE_GUEST"
            .and()
            .formLogin();  // 使用表单登录认证

        return http.build();
    }
}

在上面的例子中,匿名用户的 principal 被配置为 "guest",并且角色为 ROLE_GUEST。这种配置允许你为匿名用户提供不同的身份信息。

3.3、禁用匿名认证

可以通过配置禁用匿名认证功能,这时系统将不会为未认证的用户创建匿名身份。

http
    .anonymous()
    .disable();  // 禁用匿名认证

禁用匿名认证后,未认证的用户访问受保护的资源时会被直接拒绝,除非他们提供有效的身份认证信息。

4、AnonymousAuthenticationToken 类解析

AnonymousAuthenticationToken 是 Spring Security 中专门用于表示匿名身份的 Authentication 实现类。它继承自 AbstractAuthenticationToken,包含了匿名用户的身份、权限以及认证状态。

public class AnonymousAuthenticationToken extends AbstractAuthenticationToken {
    private final Object principal;
    private final Object credentials;

    public AnonymousAuthenticationToken(Object principal, Object credentials, Collection<? extends GrantedAuthority> authorities) {
        super(authorities);
        this.principal = principal;
        this.credentials = credentials;
        setAuthenticated(true);  // 匿名身份始终被视为已认证
    }

    @Override
    public Object getCredentials() {
        return credentials;
    }

    @Override
    public Object getPrincipal() {
        return principal;
    }
}

4.1、AnonymousAuthenticationToken 的主要属性:

  • principal:匿名用户的身份标识,通常为字符串,如 "anonymousUser" 或自定义值。
  • credentials:匿名身份没有凭据,因此通常为 null 或空值。
  • authorities:匿名用户的权限,通常为空或包含 ROLE_ANONYMOUS,可以根据需求进行自定义。

5、在认证链中的作用与重要性

AnonymousAuthenticationFilter 是 Spring Security 认证流程中的一环,它的主要目的是在用户未认证的情况下为用户提供一个默认的匿名身份。这一身份是整个认证流程的基础,它可以帮助应用区分已认证用户和匿名用户。Spring Security 会在后续的过滤器链中根据这个身份判断是否需要执行认证,或者是否允许用户访问某些资源。

与其他过滤器的关系

  • UsernamePasswordAuthenticationFilter:处理基于用户名和密码的身份认证。
  • AnonymousAuthenticationFilter:在没有有效身份的请求中创建一个匿名身份,确保后续过滤器能够看到一个已认证的用户(虽然是匿名用户)。
  • AuthenticationManager:处理具体的认证过程,通常会在其他认证过滤器(如 UsernamePasswordAuthenticationFilter)中使用。

总结

AnonymousAuthenticationFilter 是 Spring Security 认证链中的一个重要部分,它为所有匿名用户提供一个默认的认证对象,确保未认证的请求能够被安全地处理。它的作用是为匿名用户提供一个身份占位符,使得系统能够识别和处理匿名请求。你可以通过配置类定制匿名认证的行为,甚至可以禁用匿名认证功能,取决于应用的具体需求。

贡献者: Jin