当前位置: 首页 > news >正文

Spring Security | 集认证、授权、防攻击于一体的安全框架

一、Spring Security简介

Spring Security是一个Java框架,用于保护应用程序的安全性。它提供了一套全面的安全解决方案,包括身份验证、授权、防止攻击等功能。Spring Security基于过滤器链的概念,可以轻松地集成到任何基于Spring的应用程序中。它支持多种身份验证选项和授权策略,开发人员可以根据需要选择适合的方式。此外,Spring Security还提供了一些附加功能,如集成第三方身份验证提供商和单点登录,以及会话管理和密码编码等。总之,Spring Security是一个强大且易于使用的框架,可以帮助开发人员提高应用程序的安全性和可靠性。

1.核心定位

Spring 生态的安全框架,基于AOP 和 Servlet 过滤器链实现,提供 Web 请求和方法调用级的认证(是否能访问系统)授权(是否有权限操作),自包含部署无需额外配置文件。

2.技术选型

SSM 框架通常搭配 Shiro,Spring Boot/Spring Cloud 首选 Spring Security

3.基础使用

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>

引入spring-boot-starter-security依赖后,框架自动开启接口保护,默认生成用户名user,密码控制台随机生成,跳转默认登录页。

二、核心认证流程

Spring Security认证时序图:

1.自定义UserDetailService

@Service public class CustomUserDetailsService implements UserDetailsService { // 注入MyBatis的Mapper(替代之前的JPA Repository) @Autowired private UserMapper userMapper; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { // 1. 通过Mapper从数据库查询用户(含角色) SysUser sysUser = userMapper.selectUserByUsername(username); // 2. 用户不存在则抛出异常(Spring Security会捕获并处理) if (sysUser == null) { throw new UsernameNotFoundException("用户名不存在:" + username); } // 3. 转换为Spring Security的UserDetails对象 // 处理角色:拼接ROLE_前缀(Spring Security的权限命名规范) List<GrantedAuthority> authorities = sysUser.getRoles().stream() .map(role -> new SimpleGrantedAuthority("ROLE_" + role.getRoleName())) .collect(Collectors.toList()); // 构建UserDetails(核心:用户名、加密密码、权限列表) return User.withUsername(sysUser.getUsername()) .password(sysUser.getPassword()) // 数据库中已加密的密码 .authorities(authorities) // 用户权限 .accountExpired(false) // 账号未过期 .accountLocked(false) // 账号未锁定 .credentialsExpired(false) // 凭证未过期 .enabled(true) // 账号启用(已通过SQL的status=1过滤) .build(); } }
  • 对应图中DaoAuthenticationProvider调用loadUserByUsername的环节。

  • 你需要实现这个接口,告诉 Spring Security如何从你的数据源(数据库)加载用户信息,包括用户名、加密密码和权限列表。

2.重写配置类SecurityConfig

@Configuration @EnableWebSecurity public class SecurityConfig { private final UserDetailsService userDetailsService; private final PasswordEncoder passwordEncoder; // 构造注入 public SecurityConfig(UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) { this.userDetailsService = userDetailsService; this.passwordEncoder = passwordEncoder; } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); // 配置密码编辑器 } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth .requestMatchers("/login", "/static/**", "/public/**").permitAll() // 公开接口 .anyRequest().authenticated() // 其他请求需要认证 ) .formLogin(form -> form .loginPage("/login") // 自定义登录页面(可选) .loginProcessingUrl("/doLogin") // 处理登录请求的URL,对应图中的POST /login .usernameParameter("username") // 登录表单中用户名的参数名 .passwordParameter("password") // 登录表单中密码的参数名 .defaultSuccessUrl("/index", true) // 登录成功后的跳转页面 .failureUrl("/login?error") // 登录失败后的跳转页面 ) .logout(logout -> logout .logoutUrl("/logout") .logoutSuccessUrl("/login?logout") ) .csrf(csrf -> csrf.disable()); // 前后端分离时通常关闭CSRF保护 return http.build(); } // 配置AuthenticationManager使用自定义的UserDetailsService和PasswordEncoder @Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception { return config.getAuthenticationManager(); } }
  • 这是整个认证流程的总控台,对应图中的DaoAuthenticationProvider调用passwordEncoder.matches()、UsernamePasswordAuthenticationFilterAuthenticationManager

  1. Spring Security 要求密码必须加密存储,BCryptPasswordEncoder是推荐的实现,它会自动处理加盐和验证,防止彩虹表攻击。

  2. 定义哪些 URL 需要保护,哪些可以公开访问。

  3. 配置登录表单的参数和行为,让UsernamePasswordAuthenticationFilter知道从哪里获取用户名和密码。

  4. 配置登出逻辑。

  5. 构建AuthenticationManager,它会自动使用你提供的UserDetailsServicePasswordEncoder

三、核心授权流程

Spring Security授权时序图:

1.配置SecurityFilterChain(包含授权规则)

@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http // ========== 授权规则核心配置 ========== .authorizeHttpRequests(auth -> auth // 1. 公开接口:所有人可访问(无需授权) .requestMatchers("/", "/login", "/public/**").permitAll() // 2. 管理员接口:仅拥有ROLE_ADMIN权限的用户可访问 .requestMatchers("/admin/**").hasRole("ADMIN") // 3. 普通用户接口:拥有ROLE_USER或ROLE_ADMIN均可访问 .requestMatchers("/user/**").hasAnyRole("USER", "ADMIN") // 4. 精确URL权限:需要特定权限(非角色,自定义权限) .requestMatchers("/order/create").hasAuthority("ORDER_CREATE") // 5. 剩余所有请求:必须认证(登录后)才能访问 .anyRequest().authenticated() ) // 认证相关配置(复用之前的登录/登出) .formLogin(form -> form .loginPage("/login") .loginProcessingUrl("/doLogin") .permitAll() ) // 403异常处理(授权失败) .exceptionHandling(ex -> ex .accessDeniedPage("/403") // 授权失败跳转页面(前后端分离可换JSON处理器) // 前后端分离场景:自定义403返回JSON // .accessDeniedHandler(customAccessDeniedHandler()) ); return http.build(); }

在原有的认证逻辑基础上添加授权规则逻辑,这是授权最核心的配置,对应时序图中SecurityMetadataSource获取权限规则的环节。

2.方法级授权

在配置类SecurityConfig上加上@EnableMethodSecurity(prePostEnabled = true)注解,即开启PreAuthorize/PostAuthorize注解了。

具体应用如下:

@Service public class AdminService { // 仅允许ADMIN角色调用该方法 @PreAuthorize("hasRole('ADMIN')") public void deleteUser(Long userId) { // 业务逻辑:删除用户 } // 允许USER或ADMIN角色,且用户ID匹配(自定义EL表达式) @PreAuthorize("hasAnyRole('USER','ADMIN') and authentication.name == #username") public UserInfo getUserInfo(String username) { // 业务逻辑:查询用户信息 } // 方法执行后验证权限(很少用) @PostAuthorize("returnObject.username == authentication.name") public UserInfo getCurrentUserInfo() { // 业务逻辑:返回当前用户信息 } }
  • URL 级授权是 “粗粒度” 的(控制整个接口),方法级授权是 “细粒度” 的(控制单个业务方法);
  • @PreAuthorize在方法执行前验证权限,是最常用的方法级授权注解;
  • 支持 Spring EL 表达式,可直接引用方法参数、当前用户信息,实现灵活的权限判断。

注意:

  • 角色(Role):是一种特殊的权限,Spring Security 默认会给角色加ROLE_前缀(如hasRole("ADMIN")实际匹配ROLE_ADMIN);

  • 权限(Authority):更细粒度的权限(如ORDER_CREATEUSER_EDIT),无默认前缀,用hasAuthority()判断;

  • 建议:角色用于大分类(ADMIN/USER),权限用于具体操作(ORDER_CREATE/USER_EDIT),组合使用更灵活。

http://www.jsqmd.com/news/586788/

相关文章:

  • AdminBSB性能优化技巧:提升加载速度的10个实用方法
  • 知析智能AI助手系统开发全流程解析
  • GitHub Desktop中文汉化工具:轻松将官方客户端变成中文界面
  • Z-Image-Turbo-rinaiqiao-huiyewunv快速上手:5分钟完成模型初始化+首张写真生成
  • ai辅助开发:在快马平台上构建基于openclaw重启版本的智能爬虫系统
  • Windows安全防护终极指南:OpenArk免费Rootkit检测工具深度体验
  • AI辅助开发:对话快马AI模型,动态构建与优化qclaw官网
  • 专业级Backtrader量化交易回测平台:基于PyQt与finplot的完整可视化解决方案
  • 第二十一章 多部门协同:跨岗工单快流转,打破信息壁垒
  • Python-100-Days:从算法优化到架构设计的深度技术演进
  • ESP32防止函数被优化解决方案
  • 一键解锁桌面窗口管理终极方案:告别遮挡烦恼,专注核心任务
  • 【程序源代码】在线答题与网课学习小程序(含后台源码、小程序源码)
  • 我有3张1000元的携程任我行礼品卡,想1天内变现,哪个平台回收快? - 京顺回收
  • 基于用户行为的时间距离状态自适应算法(TDSA, Temporal Distance State Adaptation)
  • 网易云音乐刷播放终极指南:3步搞定个性化推荐
  • 实战指南:基于快马ai与ubuntu24.04从零部署高可用个人博客系统
  • 2025届毕业生推荐的六大降重复率平台推荐
  • 哈尔滨公务员考试笔试辅导选哪家,润雨公考口碑好吗 - 工业品网
  • 低查重AI教材编写指南:专业技巧与实用工具全分享
  • 总结断桥铝门窗零售定制厂家十大排名,珠三角靠谱的有哪些 - 工业设备
  • BilibiliDown:三步实现B站音频高效提取与批量处理全攻略
  • 第二十二章 自定义配置:贴合公司专属需求,不做一刀切
  • StructBERT在专利分析场景应用:技术方案语义相似度挖掘实战
  • 低查重AI教材编写秘籍大公开!高效工具助力教材快速生成!
  • 跨境协作破局:非侵入式翻译技术如何消除90%的语言障碍
  • 新手零基础入门mysql:用快马ai生成可运行的学生管理系统实战
  • 2026年5款降AI工具处理万方检测对比:谁家效果最稳定 - 还在做实验的师兄
  • 【程序源代码】开源商城小程序管理系统(含java版管理端,小程序源码)
  • 2026年口碑好的礼品供应链机构怎么选,仪万供应链是答案 - 工业品网