05-Spring Security 认证与授权机制源码解析

Spring Security 认证与授权机制源码解析

结合之前的IOCAOP事务管理, 这一篇讲讲Spring 的安全性,以下是小弟对Spring Security的一些理解,以及在真实面试中碰到的一些问题做了些整理,欢迎各位大佬一起观摩指点!!

一、Spring Security 简介

Spring Security 是 Spring 生态中专门用于安全控制的框架,主要用于 身份认证(Authentication)授权(Authorization)。它能够无缝集成到 Spring Boot,并提供了一套默认的安全策略,如表单登录、OAuth2 支持、密码加密、跨站请求伪造(CSRF)防护等。

Spring Security 的核心功能可以归纳为以下几点:

  • 认证(Authentication): 识别用户身份,如账号密码登录、Token 登录等。
  • 授权(Authorization): 确定用户是否有访问某些资源的权限,如基于角色(Role)或权限(Permission)控制访问。
  • 安全性防护(Security Protection): 防止 CSRF 攻击、XSS 攻击等常见安全漏洞。

二、Spring Security 认证流程(源码解析)

2.1 认证的核心组件

Spring Security 认证流程涉及多个核心组件,主要包括:

  • SecurityFilterChain 通过一组 过滤器(Filter) 进行身份认证和授权检查。
  • AuthenticationManager 认证管理器,负责验证用户身份。
  • AuthenticationProvider 认证提供者,支持不同的认证方式(如密码、OAuth2、JWT)。
  • UserDetailsService 用于加载用户信息的服务,可以从数据库或其他存储介质获取用户信息。
  • PasswordEncoder 密码加密器,确保密码存储安全。

2.2 认证流程解析

Spring Security 认证过程由 过滤器链 完成,主要流程如下:

  1. 用户发起请求 (通常是登录请求,如 /login)。
  2. UsernamePasswordAuthenticationFilter 拦截请求,提取用户名和密码。
  3. 交给 AuthenticationManager 认证 ,由 AuthenticationProvider 进行验证。
  4. 通过 UserDetailsService 加载用户信息,校验用户名和密码。
  5. 如果认证通过,生成 Authentication 对象并存入 SecurityContext,否则返回 401 未授权错误。
源码解析
java 复制代码
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) {
    String username = obtainUsername(request);
    String password = obtainPassword(request);
    UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);
    
    return this.getAuthenticationManager().authenticate(authRequest);
}

2.3 自定义用户认证

java 复制代码
@Service
public class CustomUserDetailsService implements UserDetailsService {
    @Autowired
    private UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userRepository.findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("用户不存在");
        }
        return new org.springframework.security.core.userdetails.User(
                user.getUsername(), user.getPassword(), getAuthorities(user));
    }

    private Collection<? extends GrantedAuthority> getAuthorities(User user) {
        return user.getRoles().stream()
                .map(role -> new SimpleGrantedAuthority(role.getName()))
                .collect(Collectors.toList());
    }
}

三、Spring Security 授权机制解析

3.1 授权核心组件

Spring Security 的授权机制依赖于以下核心组件:

  • AccessDecisionManager 负责决策当前用户是否可以访问某个资源。
  • SecurityContextHolder 维护当前用户的安全上下文信息。
  • GrantedAuthority 表示用户的权限(如 ROLE_ADMINROLE_USER)。
  • @PreAuthorize / @Secured 注解: 进行方法级别的权限控制。

3.2 基于角色的权限控制

java 复制代码
@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests((requests) -> requests
            .antMatchers("/admin/**").hasRole("ADMIN")
            .antMatchers("/user/**").hasRole("USER")
            .anyRequest().authenticated()
        ).formLogin(withDefaults());
        return http.build();
    }
}

3.3 方法级别的权限控制

java 复制代码
@Service
public class OrderService {
    
    @PreAuthorize("hasRole('ADMIN')")
    public void deleteOrder(Long orderId) {
        // 仅管理员可删除订单
    }
}

四、高频面试题

Q1:Spring Security 的认证流程是怎样的?

A1:Spring Security 的认证流程包括:UsernamePasswordAuthenticationFilter 拦截请求 → 交给 AuthenticationManager 认证 → AuthenticationProvider 验证用户名密码 → UserDetailsService 加载用户信息 → 认证成功存入 SecurityContext


Q2:Spring Security 如何进行授权?

A2:授权方式包括:

  1. 基于 URL 访问控制antMatchers
  2. 基于 方法注解@PreAuthorize / @Secured
  3. 自定义 AccessDecisionManager 进行更复杂的权限判断。

Q3:如何自定义用户认证?

A3:可以实现 UserDetailsService 接口,并在 loadUserByUsername 方法中从数据库查询用户信息,再返回 UserDetails 实例。


Q4:Spring Security 如何与 JWT 结合?

A4:可以通过 OncePerRequestFilter 解析 JWT 并手动创建 UsernamePasswordAuthenticationToken,然后存入 SecurityContextHolder,实现无状态认证。


五、总结

  • Spring Security 通过 过滤器链 实现身份认证和授权。
  • 认证流程涉及 AuthenticationManagerAuthenticationProviderUserDetailsService
  • 授权可以通过 URL 访问控制、方法注解、表达式等方式实现。
  • 在实际项目中,通常需要 自定义认证逻辑,如从数据库加载用户信息,或结合 JWT 进行无状态认证。

相关推荐
都叫我大帅哥1 小时前
Docker Swarm 部署方案
后端
都叫我大帅哥1 小时前
在Swarm中部署Nacos并配置外部MySQL
后端
熏鱼的小迷弟Liu2 小时前
【消息队列】RabbitMQ的基本架构?
面试·架构·rabbitmq
NAGNIP8 小时前
一文搞懂机器学习中的特征降维!
算法·面试
想摆烂的不会研究的研究生8 小时前
每日八股——Redis(1)
数据库·经验分享·redis·后端·缓存
NAGNIP8 小时前
一文搞懂机器学习中的特征构造!
算法·面试
毕设源码-郭学长8 小时前
【开题答辩全过程】以 基于SpringBoot技术的美妆销售系统为例,包含答辩的问题和答案
java·spring boot·后端
追逐时光者9 小时前
精选 10 款 .NET 开源免费、功能强大的 Windows 效率软件
后端·.net
追逐时光者9 小时前
一款开源、免费的 WPF 自定义控件集
后端·.net
S***q37710 小时前
Spring Boot管理用户数据
java·spring boot·后端