Spring Security 基础配置详解(附Demo)

news2024/10/18 21:05:07

目录

  • 前言
  • 1. 基本知识
  • 2. Demo
  • 3. 实战

前言

基本的Java知识推荐阅读:

  1. java框架 零基础从入门到精通的学习路线 附开源项目面经等(超全)
  2. 【Java项目】实战CRUD的功能整理(持续更新)

1. 基本知识

HttpSecurity 是 Spring Security 的核心类之一,负责配置基于 HTTP 的安全性,提供了用于定义安全规则、身份验证、授权、会话管理、跨站请求伪造(CSRF)保护等一系列功能的 API

HttpSecurity 主要知识点

功能方法说明
认证机制配置.authorizeRequests()用于定义请求的访问权限规则。例如,哪些 URL 需要认证,哪些允许匿名访问
禁用 CSRF 保护.csrf().disable()CSRF 是跨站请求伪造,默认启用。可以使用此方法禁用它
跨域资源共享(CORS).cors()允许配置跨域请求处理。通常用于解决跨域资源共享问题
表单登录.formLogin()使用表单认证方式,配置登录页面、登录处理 URL 等
HTTP Basic 认证.httpBasic()使用 HTTP Basic 认证方式,在每个请求的 Authorization 头中传递凭据
会话管理.sessionManagement()定义会话的管理方式,比如会话超时、是否创建新会话、并发会话控制等
记住我功能.rememberMe()允许用户通过“记住我”功能进行持久化登录
异常处理.exceptionHandling()配置访问被拒绝时的处理器或未登录时的处理行为
用户登出.logout()配置登出功能,包括登出 URL、清除 Cookie、登出成功后的跳转页面等
自定义过滤器.addFilter() / .addFilterBefore() / .addFilterAfter()添加自定义过滤器,可以在指定的过滤器链中插入额外的处理逻辑
禁用默认的头部配置.headers().disable()禁用默认的安全头部配置,例如 X-Content-Type-Options、X-Frame-Options 等
强制 HTTPS.requiresChannel()配置强制 HTTPS 的通道安全

基本的一个配置过程如下:

  1. 身份验证和授权:通过 .authorizeRequests() 设置每个 URL 的访问权限
  2. 会话管理:使用 .sessionManagement() 管理会话行为,包括并发会话和超时
  3. 异常处理:通过 .exceptionHandling() 定义未授权请求的处理逻辑
  4. 跨域配置:使用 .cors() 和 .csrf() 设置跨域和跨站请求伪造保护
  5. 自定义过滤器:通过 .addFilter() 方法插入自定义过滤器,以实现更多灵活的安全控制

2. Demo

给一个基本的Demo复杂场景示例:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            // 1. 禁用 CSRF 保护(根据需要禁用)
            .csrf().disable()
            
            // 2. 开启 CORS 支持
            .cors().and()
            
            // 3. 配置授权规则
            .authorizeRequests()
                // 允许静态资源和主页访问
                .antMatchers("/", "/home", "/css/**", "/js/**").permitAll()
                // 需要用户登录的请求
                .antMatchers("/user/**").authenticated()
                // 只允许 ADMIN 角色访问的请求
                .antMatchers("/admin/**").hasRole("ADMIN")
                // 所有其他请求需要认证
                .anyRequest().authenticated()
                
            // 4. 表单登录配置
            .and()
                .formLogin()
                    .loginPage("/login")               // 自定义登录页面
                    .loginProcessingUrl("/perform_login") // 登录表单提交 URL
                    .defaultSuccessUrl("/home", true)    // 登录成功后跳转的默认页面
                    .failureUrl("/login?error=true")    // 登录失败后跳转的页面
                    .permitAll()                        // 允许所有人访问登录页面
            
            // 5. 记住我功能
            .and()
                .rememberMe()
                    .key("uniqueAndSecret")             // rememberMe 的密钥
                    .tokenValiditySeconds(86400)        // token 有效期 1 天
            
            // 6. HTTP Basic 认证
            .and()
                .httpBasic()                             // 启用 HTTP Basic 验证
            
            // 7. 配置登出功能
            .and()
                .logout()
                    .logoutUrl("/perform_logout")        // 自定义登出 URL
                    .deleteCookies("JSESSIONID")         // 删除 session ID 的 cookie
                    .logoutSuccessUrl("/login?logout")   // 登出成功后跳转页面
                    .permitAll()
            
            // 8. 配置异常处理
            .and()
                .exceptionHandling()
                    .accessDeniedPage("/403")            // 无权限时跳转到 403 页面
            
            // 9. 会话管理
            .and()
                .sessionManagement()
                    .maximumSessions(1)                  // 限制最多 1 个并发会话
                    .maxSessionsPreventsLogin(true);     // 超过限制时不允许再次登录
    }
}

3. 实战

为更好的展示案例,以JimuReport报表为例

在这里插入图片描述

详细分析其代码含义:

@Configuration
@EnableWebSecurity // 启用 Spring Security 的Web安全功能
public class SpringSecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        // 禁用 CSRF 保护
        http.csrf().disable()
                .authorizeRequests() // 开始定义请求的授权规则
                // 允许所有人访问登录相关的请求
                .antMatchers("/login/**").permitAll()
                
                // 允许访问静态资源,放行相关路径
                .antMatchers("/jmreport/**/cdn/**", // CDN 资源
                        "/jmreport/desreport_/**/*.js", // JavaScript 文件
                        "/jmreport/desreport_/**/*.css", // CSS 文件
                        "/jmreport/desreport_/**/*.png") // PNG 图片
                .permitAll()
                
                // 允许访问无需登录的接口
                .antMatchers("/jmreport/excelQueryByTemplate", // 模板查询接口
                        "/jmreport/img/**", // 图片接口
                        "/jmreport/download/image", // 下载图片接口
                        "/jmreport/verificationToken", // 验证令牌接口
                        "/jmreport/link/queryByIds", // 查询链接的接口
                        "/jmreport/test/getUserMsg", // 获取用户信息接口
                        "/jmreport/test/getOrder", // 获取订单接口
                        "/jmreport/auto/export/download/**") // 导出下载接口
                .permitAll()
                
                // 允许访问分享页面相关接口
                .antMatchers("/jmreport/shareView/**", // 分享视图
                        "/jmreport/checkParam/**", // 检查参数
                        "/jmreport/share/verification", // 分享验证
                        "/jmreport/getQueryInfo", // 获取查询信息
                        "/jmreport/show", // 显示接口
                        "/jmreport/addViewCount/**") // 增加访问量接口
                .permitAll()
                
                // 允许访问 view 页面,使用自定义访问控制逻辑
                .antMatchers("/jmreport/view/**").access("@viewPageCustomAccess.check(request,authentication)")
                
                // 任何其他请求必须经过身份验证
                .anyRequest().authenticated()
                .and()
                
                // 配置表单登录
                .formLogin()
                .loginPage("/login/login.html") // 自定义登录页面
                .loginProcessingUrl("/login") // 登录请求处理的 URL
                .successHandler(new CustomLoginSuccessHandler()) // 登录成功处理器
                .permitAll() // 允许所有人访问登录页面
                .and()
                
                // 配置登出
                .logout()
                .invalidateHttpSession(true) // 登出时无效化 HTTP 会话
                .clearAuthentication(true) // 清除认证信息
                .permitAll(); // 允许所有人访问登出功能

        return http.build(); // 构建 SecurityFilterChain
    }
}

另外一个实战代码示例:

@Bean
protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
    // 开启跨域保护
    httpSecurity
            // 开启跨域资源共享(CORS)
            .cors().and()
            // 禁用 CSRF(因为不使用 Session 机制,使用 Token 验证)
            .csrf().disable()
            // 配置 Session 管理为无状态,因为基于 Token 机制,不需要会话
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
            // 关闭浏览器框架选项(防止点击劫持)
            .headers().frameOptions().disable().and()
            // 配置自定义的异常处理器
            .exceptionHandling()
            .authenticationEntryPoint(authenticationEntryPoint) // 处理未认证用户的访问异常
            .accessDeniedHandler(accessDeniedHandler); // 处理已认证用户的访问权限异常

    // 使用自定义的登录机制,不依赖 Spring Security 自带的登录逻辑
    // 登录暂时不使用 Spring Security 的扩展点,以减少复杂度和用户学习成本

    // 获取 @PermitAll 注解标注的 URL 列表,这些 URL 免登录
    Multimap<HttpMethod, String> permitAllUrls = getPermitAllUrlsFromAnnotations();
    
    // 配置请求权限
    httpSecurity
            // 定义授权规则
            .authorizeRequests()
            // ① 全局共享规则
            // 1.1 静态资源可以匿名访问
            .antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll()
            // 1.2 设置 @PermitAll 标注的接口无需认证
            .antMatchers(HttpMethod.GET, permitAllUrls.get(HttpMethod.GET).toArray(new String[0])).permitAll()
            .antMatchers(HttpMethod.POST, permitAllUrls.get(HttpMethod.POST).toArray(new String[0])).permitAll()
            .antMatchers(HttpMethod.PUT, permitAllUrls.get(HttpMethod.PUT).toArray(new String[0])).permitAll()
            .antMatchers(HttpMethod.DELETE, permitAllUrls.get(HttpMethod.DELETE).toArray(new String[0])).permitAll()
            // 1.3 基于配置文件中的 permit-all-urls,无需认证
            .antMatchers(securityProperties.getPermitAllUrls().toArray(new String[0])).permitAll()
            // 1.4 设置应用 API(如 `/app/api/**`),无需认证
            .antMatchers(buildAppApi("/**")).permitAll()
            // 1.5 验证码接口允许匿名访问
            .antMatchers("/captcha/get", "/captcha/check").permitAll()
            // ② 各个模块的自定义规则(通过 registry 定制)
            .and().authorizeRequests(registry -> 
                    authorizeRequestsCustomizers.forEach(customizer -> customizer.customize(registry)))
            // ③ 兜底规则,其他请求必须认证
            .authorizeRequests()
            .anyRequest().authenticated();

    // 在 UsernamePasswordAuthenticationFilter 前添加 Token 过滤器,用于 Token 验证
    httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
    
    // 返回配置好的 SecurityFilterChain
    return httpSecurity.build();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2218018.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【计算机网络 - 基础问题】每日 3 题(四十五)

✍个人博客&#xff1a;https://blog.csdn.net/Newin2020?typeblog &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/fYaBd &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞…

基于Spring Cloud的电商系统设计与实现——用户与商品模块的研究(上)

操作系统&#xff1a;Windows Java开发包&#xff1a;JDK1.8 项目管理工具&#xff1a;Maven3.6.0 项目开发工具&#xff1a;IntelliJIDEA 数据库&#xff1a;MySQL Spring Cloud版本&#xff1a;Finchley.SR2 Spring Boot版本&#xff1a;2.0.6.RELEASE 目录 用户模块—user-…

机器学习-RBF

径向基函数内核 – 机器学习 内核在将数据转换为更高维空间方面发挥着重要作用,使算法能够学习复杂的模式和关系。在众多的内核函数中,径向基函数(RBF)内核作为一种多功能且强大的工具脱颖而出。在本文中,我们深入探讨了RBF内核的复杂性,探讨了它的数学公式、直观理解、…

【分布式知识】MapReduce详细介绍

文章目录 MapReduce概述1. MapReduce编程模型Map阶段Reduce阶段 2. Shuffle和Sort阶段3. MapReduce作业的执行流程4. MapReduce的优化和特性5. MapReduce的配置和调优 MapReduce局限性相关文献 MapReduce概述 MapReduce是一个分布式计算框架&#xff0c;它允许用户编写可以在大…

使用串口中断接收时遇到的小问题(单字节接收,固定多字节接收,不定长字节接收)

单字节接收 在cubemx初始化串口1&#xff0c;打开串口中断 在usart。c文件中修改中断回调函数 //串口接收回调函数 void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if( huart &huart1)//判断中断源 { if(g_ucUsart1ReceiveData 0x01) { …

Java使用原生HttpURLConnection实现发送HTTP请求

1、HttpURLConnection 类的介绍 HttpURLConnection 是 Java 提供的原生标准的用于发送 HTTP 请求和接收 HTTP 响应的一个类&#xff0c;它位于 java.net 包下&#xff0c;并继承了 URLConnection 类。 HttpURLconnection 是基于 HTTP 协议的&#xff0c;支持 get&#xff0c;…

Flink有状态计算

前言 状态是什么&#xff1f;状态就是数据&#xff0c;准确点说&#xff0c;状态是指 Flink 作业计算时依赖的历史数据或中间数据。如果一个 Flink 作业计算依赖状态&#xff0c;那它就是有状态计算的作业&#xff0c;反之就是无状态计算的作业。 举个例子&#xff0c;服务端…

【高阶数据结构】揭开红黑树‘恶魔’的面具:深度解析底层逻辑

高阶数据结构相关知识点可以通过点击以下链接进行学习一起加油&#xff01;二叉搜索树AVL树 大家好&#xff0c;我是店小二&#xff0c;欢迎来到本篇内容&#xff01;今天我们将一起探索红黑树的工作原理及部分功能实现。红黑树的概念相对抽象&#xff0c;但只要我们一步步深入…

单链表算法题(二)(超详细版)

前言 : 通过算法题 &#xff0c; 学习解决问题的思路 &#xff0c; 再面对类似的算法题时 &#xff0c; 能快速定位解决方案 一 . 链表的回文结构 链表的回文结构 : 链表的回文结构_牛客题霸_牛客网 思路一 : 创建新链表 &#xff0c; 对原链表进行反转&#xff0c;结果存储在…

计算机毕业设计Python深度学习房价预测 房源可视化 房源爬虫 二手房可视化 二手房爬虫 递归决策树模型 机器学习 深度学习 大数据毕业设计

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 房地产是促进我国经济持续增…

Google play开发者账号被封,申诉就有机会,别不信

在谷歌上架&#xff0c;开发者账号被封对很多开发者来说已经是家常便饭了&#xff0c;虽说一直都有在流传申诉没有用。别灰心啊&#xff0c;申诉就有机会&#xff0c;不少开发者都申诉成功了。 尤其是用一个少一个、价值好几个w的老号&#xff0c;不申诉就认栽实在是太亏了&…

Bootstrap 弹出框(Popover)插件

弹出框&#xff08;Popover&#xff09;与工具提示&#xff08;Tooltip&#xff09;类似&#xff0c;提供了一个扩展的视图。如需激活弹出框&#xff0c;用户只需把鼠标悬停在元素上即可。弹出框的内容完全可使用 Bootstrap 数据 API&#xff08;Bootstrap Data API&#xff09…

Mysql底层原理详细剖析

1. 索引数据结构 索引是帮助mysql 是帮助数据排序 且高效获取数据的数据结构 索引的数据结构有&#xff1a; 二叉树红黑树hash表b树 1.1 二叉查找树 二叉查找树 如果要查找&#xff0c;通过二分查找的复杂度进行查找数据&#xff0c;确实优化了性能&#xff0c;减少了io的…

【中危】Oracle TNS Listener SID 可以被猜测

一、漏洞详情 Oracle 打补丁后&#xff0c;复测出一处中危漏洞&#xff1a;Oracle TNS Listener SID 可以被猜测。 可以通过暴力猜测的方法探测出Oracle TNS Listener SID&#xff0c;探测出的SID可以用于进一步探测Oracle 数据库的口令。 建议解决办法&#xff1a; 1. 不应该使…

机器学习—特性缩放

特性缩放的技术能使梯度下降运行得更快&#xff0c;让我们先来看看功能大小之间的关系&#xff0c;这就是该特性的数字和相关参数的大小&#xff0c;作为一个具体的例子&#xff0c;让我们用两个特征来预测房子的价格&#xff0c;X1代表一个房子的大小&#xff0c;X2代表两个卧…

python爬取themoviedb电影网站信息

python爬取themoviedb电影网站信息 一、寻找数据接口二、解析主页数据,获取详情页url三、向详情页url发送请求、获取并解析数据四、完整代码一、寻找数据接口 打开网站首页,F12打开开发者工具,刷新页面。 向下滑动页面,点击页面上的“Load More”图标。 寻找到数据接口,…

掘金2.计算位置 x 到 y 的最少步数(简单01)

public class Main {public static int solution(int xPosition, int yPosition) {int diff (yPosition - xPosition);// 计算差值if(diff < 0)diff * -1;int steps 0; // 初始化步数int begin 0;// 初始化当前位置int step 1;//初始化步长// 循环直到到达目标位置while…

DSVPN简介与应用

目录 简介 DSVPN 封装模式 Nomal&#xff08;动态&#xff09;方式建立DSVPN 一、配置缺省包过滤 二、划分区域&#xff08;以总部为例&#xff09; 三、配置IP地址&#xff08;以R1为例&#xff09; 四、配置DSVPN 简介 DSVPN DSVPN&#xff08;Dynamic Secure Vir…

一种3D打印跑车模型LED安全夜灯

我学习入门单片机及3Dmax的副产品&#xff0c;小玩意。MCU用8脚的就好&#xff0c;多脚功能复用&#xff0c;涉及长短按中断、ADC、掉电唤醒及LED切换控制&#xff0c;硬件的充放电监控及光控等等麻雀虽小五脏俱全。发使用指南不是广告&#xff0c;感觉这样才能毫无遗漏的说明其…

动态规划(1)斐波那契数列模型

动态规划算法流程&#xff1a; 1、状态表示&#xff1a; 指的是dp&#xff08;dynamic programming&#xff09;表里面的值所表示的含义 如何得出&#xff1a;1、题目要求 2、经验题目要求 3、分析问题的过程中发现重复子问题 2、状态转移方程 dp[i]等于什么 3、初始化 保证…