问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Spring Security架构和核心类详解

创作时间:
作者:
@小白创作中心

Spring Security架构和核心类详解

引用
CSDN
1.
https://m.blog.csdn.net/weixin_74412978/article/details/144724129

Spring Security是一个强大的安全框架,用于保护基于Spring的应用程序。它提供了认证、授权以及各种安全功能,如密码编码、会话管理等。本文将深入探讨Spring Security的核心架构和关键类,帮助开发者更好地理解和使用这个框架。

Spring Security框架概述

Spring Security通过一系列过滤器来实现安全功能。核心组件是DelegatingFilterProxy,它在Servlet生命周期和Spring Bean之间搭建了一座桥梁。下面是一个简单的配置示例:

@Bean
public FilterRegistrationBean<Filter> filterRegistrationBean() throws Exception {
    FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
    DelegatingFilterProxy delegatingFilterProxy = new DelegatingFilterProxy();
    delegatingFilterProxy.setTargetFilterLifecycle(true);
    delegatingFilterProxy.setBeanName("myFilter");
    filterRegistrationBean.setFilter(myFilter);
    filterRegistrationBean.addUrlPatterns("/*");
    return filterRegistrationBean;
}

在这个配置中,myFilter是Servlet的过滤器,而DelegatingFilterProxy是Spring提供的一个类,允许我们在Spring Bean中管理Servlet过滤器。

FilterChainProxy是一个Bean,被包装在DelegatingFilterProxy中。它类似于一个集合,每个元素是一个SecurityFilterChain。每个SecurityFilterChain内部又包含多个过滤器,如LogoutFilterUsernamePasswordAuthenticationFilter等。

你可以把SecurityFilterChain想象成一个班级,而FilterChainProxy则是一个学校。需要注意的是,SecurityFilterChain的匹配顺序非常重要,Spring Security会按照顺序执行匹配的第一个链。

认证核心代码

SecurityContextHolder

SecurityContextHolder用于存储用户身份认证完毕后的认证信息。默认使用ThreadLocal线程绑定方式存储信息。为了在请求结束时将信息保存到Session中,可以使用HttpSessionSecurityContextRepository

当需要在子线程中访问认证信息时,可以通过设置系统属性或使用DelegatingSecurityContextExecutorService来解决。

GrantedAuthority

GrantedAuthority实例表示授予用户的高级权限,如角色和范围。可以通过Authentication.getAuthorities()获取当前用户的所有权限集合。

AuthenticationManager

AuthenticationManager是认证的核心类,决定了Spring Security过滤器的执行流程。它传递的Authentication对象只包含用户名和密码,认证成功后会填充完整信息并返回,否则会抛出AuthenticationException异常。

ProviderManager

ProviderManager相当于一个集合,每个元素都是AuthenticationProvider类。这些认证提供者是最终执行认证的地方,每个提供者都是相互隔离的。如果轮询结束后没有一个提供者被执行,会抛出ProviderNotFoundException

AuthenticationProvider

AuthenticationProvider接口定义了认证的核心方法:

public interface AuthenticationProvider {
   Authentication authenticate(Authentication authentication) throws AuthenticationException;
   boolean supports(Class<?> authentication);
}

supports函数用于判断当前Authentication是否支持该提供者。例如,DaoAuthenticationProvider需要UsernamePasswordAuthenticationToken类型的认证。

UsernamePasswordAuthenticationFilter

UsernamePasswordAuthenticationFilter是Spring Security中常用的过滤器之一,主要用于处理基于用户名密码的认证请求。核心代码如下:

@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
      throws AuthenticationException {
   if (this.postOnly && !request.getMethod().equals("POST")) {
      throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
   }
   String username = obtainUsername(request);
   username = (username != null) ? username.trim() : "";
   String password = obtainPassword(request);
   password = (password != null) ? password : "";
   UsernamePasswordAuthenticationToken authRequest = UsernamePasswordAuthenticationToken.unauthenticated(username,
         password);
   // Allow subclasses to set the "details" property
   setDetails(request, authRequest);
   return this.getAuthenticationManager().authenticate(authRequest);
}

DaoAuthenticationProvider

DaoAuthenticationProvider提供了密码验证的具体实现:

@Override
protected void additionalAuthenticationChecks(UserDetails userDetails,
      UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
   if (authentication.getCredentials() == null) {
      throw new BadCredentialsException();
   }
   String presentedPassword = authentication.getCredentials().toString();
   if (!this.passwordEncoder.matches(presentedPassword, userDetails.getPassword(/**/))) {
      throw new BadCredentialsException(/**/);
   }
}

此外,它还提供了密码加密方法升级和防止旁道攻击的功能。

UserDetailsService

UserDetailsService用于从数据库或其他数据源加载用户信息。默认情况下,Spring Security将用户信息保存在内存中。如果需要从数据库中获取用户信息,可以重写这个接口:

UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;

PasswordEncoder

PasswordEncoder接口定义了密码加密和匹配的方法:

public interface PasswordEncoder {
   String encode(CharSequence rawPassword);
   boolean matches(CharSequence rawPassword, String encodedPassword);
   default boolean upgradeEncoding(String encodedPassword) {
      return false;
   }
}

Spring Security默认使用DelegatingPasswordEncoder,它可以支持多种加密算法。在实际项目中,通常会配置一个DelegatingPasswordEncoder

@Bean
public PasswordEncoder passwordEncoder() throws Exception {
    return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}

总结

Spring Security通过一系列过滤器和认证组件,提供了全面的安全保护功能。理解其核心架构和关键类的工作原理,对于开发安全的Spring应用程序至关重要。本文重点介绍了框架的整体架构和核心组件,后续将深入探讨登录成功后的处理流程、异常处理机制以及前后端分离场景下的应用。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号