Spring security 基本感知

流程

1.接收请求

1、HTTP基本身份验证请求通过过滤器链直到它到达BasicAuthenticationFilter。

2、HTTP摘要式身份验证请求通过过滤器链,直到它到达DigestAuthenticationFilter。

3、登录表单提交请求(登录表单身份验证请求)通过过滤器链直到它到达UsernamePasswordAuthenticationFilter。

4、x509身份验证请求通过过滤器链直到它到达X509AuthenticationFilter等...

2.根据用户凭据创建AuthenticationToken

相关的AuthenticationFilter收到身份验证请求,会从收到的请求中提取用户名和密码(大多数身份验证机制都需要用户名和密码)。 之后,它会根据提取的用户凭据创建一个Authentication对象。 如果提取的凭据是用户名和密码,则将使用提取/找到的用户名和密码创建UsernamePasswordAuthenticationToken。

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.security.core;

import java.io.Serializable;
import java.security.Principal;
import java.util.Collection;

public interface Authentication extends Principal, Serializable {

    Collection<? extends GrantedAuthority> getAuthorities();

    Object getCredentials();

    Object getDetails();

    Object getPrincipal();

    boolean isAuthenticated();

    void setAuthenticated(boolean var1) throws IllegalArgumentException;
}

3.创建的AuthenticationToken委派给AuthenticationManagager

它将用于调用AuthenticationManager的authenticate方法。 AuthenticationManager只是一个接口,实际的实现是ProviderManager。

public interface AuthenticationManager {
    // 核心
    Authentication authenticate(Authentication authentication)throws AuthenticationException;

}

ProviderManager有一个配置的AuthenticationProvider列表,应该用于验证用户请求。 ProviderManager将遍历每个提供的AuthenticationProvider,并尝试根据传递的Authentication Object对用户进行身份验证(例如: - UsernamePasswordAuthenticationToken)

4.尝试使用AuthenticationProvider列表进行身份验证

// 自定义验证器时需要实现
public interface AuthenticationProvider {
    // 验证规则
    Authentication authenticate(Authentication var1) throws AuthenticationException;
    // 支持的Authentication类型 
    boolean supports(Class<?> var1);
}

以下是框架附带的一些现有身份验证程序:

  • CasAuthenticationProvider
  • JaasAuthenticationProvider
  • DaoAuthenticationProvider
  • OpenIDAuthenticationProvider
  • RememberMeAuthenticationProvider
  • LdapAuthenticationProvider

5. 验证数据来源:UserDetailsService

public interface UserDetailsService {
    // 根据用户名获取用户信息,返回封装成UserDetail或实现返回
    UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;

}

6、7. UserDetails 接口和 User 实现?

UserDetailsService将根据用户名检索UserDetails(实际实现是User)。

public interface UserDetails extends Serializable {
    Collection<? extends GrantedAuthority> getAuthorities();

    String getPassword();

    String getUsername();

    boolean isAccountNonExpired();

    boolean isAccountNonLocked();

    boolean isCredentialsNonExpired();

    boolean isEnabled();
}

User实现:org.springframework.security.core.userdetails.User

8.返回Authentication 或者抛出 AuthenticationException?

如果用户成功通过身份验证,则将返回完全填充的Authentication对象。 否则将抛出AuthenticationException。

扫描二维码关注公众号,回复: 4301972 查看本文章

如果抛出任何AuthenticationException,那将由支持身份验证机制的已配置AuthenticationEntryPoint处理。

9.验证完成!

AuthenticationManager将获取的完全填充的Authentication对象返回到相关的Authentication 过滤器。

然后,相关的AuthenticationFilter会将获取的身份验证对象存储在SecurityContext中,以供将来过滤器使用。 (用于授权过滤器)

SecurityContextHolder.getContext().setAuthentication(authentication);

组件

SecurityContextHolder

SecurityContextHolder使用ThreadLocal来存储这些详细信息,这意味着安全上下文始终可用于同一执行线程中的方法,即使安全上下文未作为这些方法的参数显式传递

  • 配置:
    • SecurityContextHolder.MODE_GLOBAL策略:独立应用程序,全局共享用户信息
    • SecurityContextHolder.MODE_INHERITABLETHREADLOCAL:安全线程生成的线程也采用相同的安全标识
// 从SecurityContextHolder中获取用户身份信息
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();

if (principal instanceof UserDetails) {
    String username = ((UserDetails)principal).getUsername();
} else {
    String username = principal.toString();
}

UserDetailsService

数据来源:UserDetails loadUserByUsername(String username) throws UsernameNotFoundException; 校验实现:AuthenticationProvider

GrantedAuthority

Authentication提供的另一个重要方法是getAuthorities()。 此方法提供GrantedAuthority对象的数组。GrantedAuthority是授予主体的权限。 这些权限通常是“角色”,例如ROLE_ADMINISTRATOR或ROLE_HR_SUPERVISOR

猜你喜欢

转载自my.oschina.net/u/3847565/blog/2963709