Spring Security 认证流程

认证相关

核心类理解

1.GrantedAuthority:表示授予对象的权限,通过getAuthority获得String
2.UserDetailsService接口:表示加载用户信息的服务,通过loadUserByUsername(String username)方法加载返回UserDetails类
3.UserDetailsManager:是UserDetailsService的拓展,提供UserDetails的增删改等操作,实现类InMemoryUserDetailsManager(内存)和JdbcUserDetailsManager(持久层)
4.AuthenticationProvider:调用UserDetailService中的方法获得库中用户信息,验证传入的Authentication是否匹配库中信息
5.ProviderManager:继承AuthenticationManager,管理多个AuthenticationProvider,遍历调用其中服务提供者的support方法,满足则调用authenticate方法

UserDetails

提供核心用户信息

public interface UserDetails extends Serializable {
	// 返回授予用户的权限,不能为null
	Collection<? extends GrantedAuthority> getAuthorities();
	// 用户名密码
	String getPassword();
	String getUsername();
}

InMemoryUserDetailsManager

用于在内存中存放用户信息,并对用户信息进行校验等处理

public class InMemoryUserDetailsManager implements UserDetailsManager,
		UserDetailsPasswordService {
	// 存放当前内存中的用户信息
	private final Map<String, MutableUserDetails> users = new HashMap<>();
	private AuthenticationManager authenticationManager;
}		

AbstractAuthenticationProcessingFilter(认证入口)

用户认证的过滤器,用于处理基于浏览器交互的HTTP验证请求

1.将请求信息封装为Authentication,交付给AuthenticationManager验证
2.提供验证成功和失败的处理,失败清除SecurityContext调用对应失败处理器,成功添加令牌到SecurityContext并发布InteractiveAuthenticationSuccessEvent事件

public abstract class AbstractAuthenticationProcessingFilter extends GenericFilterBean
		implements ApplicationEventPublisherAware, MessageSourceAware {
	// 事件发布器,验证发布InteractiveAuthenticationSuccessEvent
	protected ApplicationEventPublisher eventPublisher;
	// 核心验证
	private AuthenticationManager authenticationManager;	
	// 匹配的请求
	private RequestMatcher requiresAuthenticationRequestMatcher;
	
	// 验证成功或失败的处理器
	private AuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
	private AuthenticationFailureHandler failureHandler = new SimpleUrlAuthenticationFailureHandler();
	
	// 记住我和Session实现
	private RememberMeServices rememberMeServices = new NullRememberMeServices();
	private SessionAuthenticationStrategy sessionStrategy = new NullAuthenticatedSessionStrategy();
}
// 核心过滤处理
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
			throws IOException, ServletException {

	HttpServletRequest request = (HttpServletRequest) req;
	HttpServletResponse response = (HttpServletResponse) res;
	// 如果请求不匹配则跳过
	if (!requiresAuthentication(request, response)) {
		chain.doFilter(request, response);

		return;
	}
	Authentication authResult;

	try {
		// 从请求中解析用户信息(Authentication),添加自定义detail信息,交给AuthenticationManager验证
		authResult = attemptAuthentication(request, response);
		if (authResult == null) {
			// 立即返回,因为子类指示它尚未完成
			return;
		}
		// Session处理
		sessionStrategy.onAuthentication(authResult, request, response);
	}
	···异常捕获,调用unsuccessfulAuthentication(request, response, failed)方法处理

	
	if (continueChainBeforeSuccessfulAuthentication) {
		chain.doFilter(request, response);
	}
	// 验证成功处理
	successfulAuthentication(request, response, chain, authResult);
}		

例子

public static void main(String... args) {
    // 输入的身份信息
    UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user", "pwd");
    // 提供验证服务
    DaoAuthenticationProvider daoProvider = new DaoAuthenticationProvider();
    // 创建内存获取用户信息的服务
    InMemoryUserDetailsManager memory = new InMemoryUserDetailsManager();
    // 在内存中存放一条用户信息,{noop}存放密码的加密方式,此处不加密
    memory.createUser(User.withUsername("user").password("{noop}pwd").roles("users","system").build());
    // 将查询用户信息服务放入验证服务中
    daoProvider.setUserDetailsService(memory);
    // 对所有提供的服务进行管理
    AuthenticationManager am = new ProviderManager(daoProvider);
    // 对输入的信息进行验证
    Authentication authenticate = am.authenticate(token);
    authenticate.getAuthorities().forEach((ag) -> System.out.println(ag.getAuthority()));
}
// 输出:ROLE_system ROLE_users

Spring中基础过滤器介绍

  1. OncePerRequestFilter:在一次请求中只执行一次过滤,通过设置request中Attribute属性完成
  2. CharacterEncodingFilter:为请求指定字符编码
  3. FormContentFilter:对于PUT DELETE PATCH的表单请求,将数据保存在request中
  4. RequestContextFilter:将请求和请求中的locale国际化处理放入RequestContextHolder和LocaleContextHolder中(线程特有)

默认加载的配置类及过滤器

if (!disableDefaults) {
	// @formatter:off
	http
		.csrf().and()
		.addFilter(new WebAsyncManagerIntegrationFilter())
		.exceptionHandling().and()
		.headers().and()
		.sessionManagement().and()
		.securityContext().and()
		.requestCache().and()
		.anonymous().and()
		.servletApi().and()
		.apply(new DefaultLoginPageConfigurer<>()).and()
		.logout();
	// @formatter:on
	ClassLoader classLoader = this.context.getClassLoader();
	List<AbstractHttpConfigurer> defaultHttpConfigurers =
			SpringFactoriesLoader.loadFactories(AbstractHttpConfigurer.class, classLoader);

	for (AbstractHttpConfigurer configurer : defaultHttpConfigurers) {
		http.apply(configurer);
	}
}
  1. http.csrf()方法添加CsrfConfigurer:预防跨站伪造攻击,按照请求方法匹配,默认忽略(GET、OPTION、TRACE和HEAD)请求
    CsrfTokenRepository:存放CsrfToken令牌的仓库
    CsrfFilter:跨站伪造攻击过滤器;1.获得csrf令牌(CsrfTokenRepository) 2.判断请求是否匹配 3.从请求头或参数中获取请求的令牌
  2. WebAsyncManagerIntegrationFilter过滤器:用于集成SecurityContext到Spring异步执行机制中的WebAsyncManager
  3. http.exceptionHandling()添加ExceptionHandlingConfigurer:向应用程序添加Spring安全相关异常的异常处理
    ExceptionTranslationFilter:对执行过滤过程中抛出的异常统一处理
  4. http.headers()添加HeadersConfigurer:将Security相关的头部添加到response中
    HeaderWriterFilter:过滤链执行完或下一个过滤器执行前添加头部
  5. http.sessionManagement()添加SessionManagementConfigurer:允许配置会话管理
    SessionManagementFilter:固定保护机制或检查多个并发登录
  6. http.securityContext()添加SecurityContextConfigurer:为每个请求持久化SecurityContext
    SecurityContextPersistenceFilter:1.从Session中获取SecurityContext不存在则创建一个新的 2.将SecurityContext交给SecurityContextHolder全局使用
  7. http.requestCache()添加RequestCacheConfigurer:为spring security添加请求缓存
    RequestCacheAwareFilter:如果缓存了一个请求并与当前请求匹配,则负责重新构建保存的请求。
  8. http.anonymous()添加AnonymousConfigurer:为HttpSecurity配置匿名身份验证
    AnonymousAuthenticationFilter:如果在SecurityContextHolder中没有Authentication则默认填充一个匿名的令牌
  9. http.servletApi()添加ServletApiConfigurer:对request进行封装
    SecurityContextHolderAwareRequestFilter:对request进行封装,使其能够访问Servlet api信息相关接口
  10. 添加DefaultLoginPageConfigurer:未指定登录页,则该筛选器将生成登录页。
    DefaultLoginPageGeneratingFilter:
    DefaultLogoutPageGeneratingFilter:
  11. http.logout()添加LogoutConfigurer:添加退出登陆支持
    LogoutFilter:退出登陆操作,处理Authentication

授权和登录配置

protected void configure(HttpSecurity http) throws Exception {
	http
		.authorizeRequests()
			.anyRequest().authenticated()
			.and()
		.formLogin().and()
		.httpBasic();
}

12.http.authorizeRequests()添加ExpressionUrlAuthorizationConfigurer:为多组RequestMatcher配置不同的权限属性
ExpressionInterceptUrlRegistry:url与权限的映射管理
FilterSecurityInterceptor:是一个方法级的权限过滤器
13.http.formLogin()添加FormLoginConfigurer:添加基于表单的身份验证
UsernamePasswordAuthenticationFilter:对/login的post方法进行身份认证
14.http.httpBasic()添加HttpBasicConfigurer:添加基于HTTP基本身份验证
BasicAuthenticationFilter:处理HTTP请求头中包含认证信息的情况

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值