博客
关于我
Spring Security 架构与源码分析
阅读量:662 次
发布时间:2019-03-16

本文共 3427 字,大约阅读时间需要 11 分钟。

Spring Security 是一个强大的框架,用于实现认证和访问控制(授权)。它通过分离认证和授权两大部分,提供了灵活的配置和扩展,适用于各种复杂的安全需求。以下将从认证和授权两个方面详细阐述 Spring Security 的工作原理及其实现细节。

认证

认证的核心是通过 AuthenticationManager 来完成的。它是一个接口,主要提供了一个方法:authenticate(Authentication authentication)。这个方法的作用是接受一个 Authentication 实例,并根据其是否有效,返回一个 Authentication 对象或者抛出一个 AuthenticationException。

默认实现是 ProviderManager,它负责通过一系列 AuthenticationProvider 来完成认证。每个 AuthenticationProvider 都需要实现两个关键方法:authenticate(Authentication authentication) 和 supports(Class<?> authentication)。

  • authenticate 方法用于进行实际的认证,可能会调用 UserDetailsService 来获取用户信息,并通过 PasswordEncoder 来验证密码是否正确。
  • supports 方法用于检查该 Provider 是否能够支持某一种类型的 Authentication。

常见的 AuthenticationToken 实现

大多数应用程序会使用 UsernamePasswordAuthenticationToken,因为它可以处理用户名和密码的认证。以下是其代码结构:

public abstract class AbstractAuthenticationToken implements Authentication, CredentialsContainer {	...	public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationToken {		...	}

在实际应用中,认证过程遵循以下步骤:

  • 创建一个 UsernamePasswordAuthenticationToken,填充 username 和 password。
  • 调用 AuthenticationManager 的 authenticate 方法,执行认证。
  • 如果认证成功,AuthenticationManager 会返回一个 Authentication 对象,并将其存储在 SecurityContextHolder 中。
  • 如果认证失败,可能会抛出一个 AuthenticationException。
  • 用户信息和密码验证

    在认证过程中,UserDetailsService 负责获取用户信息。它通过 loadUserByUsername(String username) 方法返回一个 UserDetails 对象。默认实现是 DaoAuthenticationProvider,它通过数据库查询用户信息,并使用 PasswordEncoder 来验证密码的正确性。

    public interface UserDetailsService {	UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;}

    UserDetails 提供了用户的基本信息,如 username、password、roles 等。开发者可以根据需求自定义实现这个接口,扩展用户的属性。

    核心对象解析

    • SecurityContextHolder:用于存储和获取 SecurityContext,默认使用 ThreadLocal 达到线程安全。
    • SecurityContext:存储应用的 principal 信息,而 Authentication 对象代表凭证。
    • Authentication:通常由多个 Provider 组成,完成认证并返回一个 principal(用户信息)。

    授权与访问控制

    一旦认证成功,系统需要进行授权。Spring Security通过 AccessDecisionManager 来实现授权,默认使用 AffirmativeBased 框架,通过多个 AccessDecisionVoter 来做出决策。

    AccessDecisionVoter

    AccessDecisionVoter 负责对特定的资源进行访问判断。它通过 supports(ConfigAttribute attribute) 方法检查是否支持某个配置属性,vote 方法则进行投票。

    public abstract class AbstractAccessDecisionVoter implements AccessDecisionVoter {	...}

    Classics 的一个实现是 RoleVoter,它通过检查 Authentication 中的 GrantedAuthority,判断是否有访问某个资源的权限。例如:

    public class RoleVoter implements AccessDecisionVoter {	@Override	public boolean supports(ConfigAttribute attribute) {		// 检查 ConfigAttribute 是否以指定的前缀开始		return true;	}	@Override	public int vote(Authentication authentication, Object object, Collection
    attributes) { // 提取用户的权限,判断是否满足 ConfigAttribute 条件 return ACCESS_GRANTED; }}

    核心组件解析

    • AccessDecisionManager:默认使用 AffirmativeBased,通过多个 AccessDecisionVoter 来进行联合决策。
    • GrantedAuthority:表示一个权限,如 ROLE_ADMIN、ROLE_USER 等。
    • ConfigAttribute:资源访问所需的属性,如 path、method、roles 等。

    权限判断与访问控制

    • @PreAuthorize:可在控制器方法或其他逻辑中使用,用于前置检查权限。其底层通过 DefaultPermissionEvaluator 来解析权限。
    • @PostAuthorize:用于在方法执行后进行权限检查,适用于动态变化的权限情况。
    • 权限合成:通过合成安全元件(如 CombinedSecurityMetadataSource),从多个安全元件中获取权限信息,支持联合权限验证。

    实际应用中的配置与扩展

    在实际应用中,开发者可以通过配置来个性化认证和授权:

  • WebSecurityConfigurerAdapter:用于配置 WebSecurity,集成 Telnet、LDAP、数据库等认证方式。
  • PasswordEncoder:用于密码加密和验证,常用MD5PasswordEncoder。
  • UserDetailsService 和 DaoAuthenticationProvider:用于获取用户信息和验证密码,开发者可以自定义实现以支持不同的用户存储和检索方式。
  • PermissionEvaluator:用于定制权限判断逻辑,扩展 Spring Security 的默认权限评估机制。
  • 小结

    Spring Security通过清晰的分层结构和灵活的配置选项,提供了强大的认证和授权功能。从简单的 username-password 认证到复杂的基于角色的访问控制,框架都提供了良好的支持。通过正确配置和定制,开发者可以根据实际需求实现高效且安全的应用程序。

    参考资料

    转载地址:http://uysqz.baihongyu.com/

    你可能感兴趣的文章
    不编译只打包system或者vendor image命令
    查看>>
    【编程】C语言入门:1到 100 的所有整数中出现多少个数字9
    查看>>
    flink启动(二)
    查看>>
    pair的用法
    查看>>
    Flex 布局的自适应子项内容过长导致其被撑大问题
    查看>>
    PL/SQL 动态Sql拼接where条件
    查看>>
    Error:Cannot read packageName from AndroidManifest.xml
    查看>>
    【自学Flutter】4.1 Material Design字体图标的使用(icon)
    查看>>
    【换行符】什么时候用cin.get()吃掉输入流中的换行符
    查看>>
    广东外语外贸大学第三届网络安全大赛Writeup
    查看>>
    SpringBoot使用RedisTemplate简单操作Redis的五种数据类型
    查看>>
    Thymeleaf sec:authorize 标签不生效
    查看>>
    微信JS-SDK DEMO页面和示例代码
    查看>>
    测试tensorflow是否安装成功 出现 SyntaxError: invalid syntax的错误
    查看>>
    Flask--简介
    查看>>
    Frame--Api框架
    查看>>
    Boostrap技能点整理之【网格系统】
    查看>>
    javaWeb服务详解(含源代码,测试通过,注释) ——Emp的Dao层
    查看>>
    Git简单理解与使用
    查看>>
    echarts 基本图表开发小结
    查看>>