• SpringSecurity系列——安全Http响应头day8-2(源于官网5.7.2版本)


    安全Http响应头

    安全 HTTP 响应标头 可用于提高 Web 应用程序的安全性

    默认的安全头

    Spring Security 提供了一 组默认的 Security HTTP Response Headers 来提供安全的默认值。 虽然这些标头中的每一个都被认为是最佳实践,但应注意并非所有客户端都使用标头,因此鼓励进行额外测试。
    您可以自定义特定的Header

    默认包含的安全头

    Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    Pragma: no-cache
    Expires: 0
    X-Content-Type-Options: nosniff
    Strict-Transport-Security: max-age=31536000 ; includeSubDomains
    X-Frame-Options: DENY
    X-XSS-Protection: 1; mode=block
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    自定义默认安全标头

    @EnableWebSecurity
    public class WebSecurityConfig {
    
    	@Bean
    	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    		http
    			// ...
    			.headers(headers -> headers
    				.frameOptions(frameOptions -> frameOptions
    					.sameOrigin()
    				)
    			);
    		return http.build();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    如果您不想添加默认值并希望明确控制应该使用的内容,则可以禁用默认值

    禁用默认安全头

    http.headers(headers -> headers.defaultsDisabled());
    
    • 1

    以这种方式会禁止默认的安全头,除非我们自己指出

    禁用所有安全头(完全无效)

    @EnableWebSecurity
    public class WebSecurityConfig {
    
    	@Bean
    	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    		http
    			// ...
    			.headers(headers -> headers.disable());
    		return http.build();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    缓存控制

    Spring Security 默认包含 Cache Control 标头。
    Spring Security 的默认设置是禁用缓存以保护用户的内容

    但是,如果您确实想要缓存特定的响应,您的应用程序可以选择性地调用 HttpServletResponse.setHeader(String,String) 来覆盖 Spring Security 设置的标头。 这对于确保正确缓存 CSS、JavaScript 和图像等内容很有用。

    默认的缓存控制响应头

    Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    Pragma: no-cache
    Expires: 0
    
    • 1
    • 2
    • 3

    禁用默认安全头开启缓存控制

    @EnableWebSecurity
    public class WebSecurityConfig {
    
    	@Bean
    	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    		http
    			// ...
    			.headers(headers -> headers
    				.defaultsDisabled()
    				.cacheControl(withDefaults())
    			);
    		return http.build();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    禁用缓存控制(cacheControl)

    @Configuration
    @EnableWebSecurity
    public class WebSecurityConfig {
    
    	@Bean
    	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    		http
    			// ...
    			.headers(headers -> headers
    				.cacheControl(cache -> cache.disable())
    			);
    		return http.build();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    内容类型(Content-Type)

    默认包含Content-Type

    当允许上传内容时,还应该做很多额外的事情(即只在不同的域中显示文档,确保设置 Content-Type 标头,清理文档等)。 但是,这些措施超出了 Spring Security 提供的范围。 同样重要的是要指出禁用内容嗅探时,您必须指定内容类型才能正常工作。

    内容嗅探的问题在于,这允许恶意用户使用多语言(即作为多种内容类型有效的文件)来执行 XSS 攻击。 例如,某些网站可能允许用户向网站提交有效的 postscript 文档并进行查看。 恶意用户可能会创建一个 也是有效 JavaScript 文件的 postscript 文档 并使用它执行 XSS 攻击

    Spring Security 默认通过向 HTTP 响应添加以下标头来禁用内容嗅探

    X-Content-Type-Options: nosniff
    
    • 1

    当然也是可以禁用的但是很不推荐你这样做

    禁用Content-Type

    @Configuration
    @EnableWebSecurity
    public class WebSecurityConfig {
    
    	@Bean
    	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    		http
    			// ...
    			.headers(headers -> headers
    				.contentTypeOptions(contentTypeOptions -> contentTypeOptions.disable())
    			);
    		return http.build();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    HSTS严格传输安全

    简单来说,对于需要高安全性的网站我们会使用Https协议,因为恶意用户可以拦截初始 HTTP 请求并操纵响应,https协议会大大提升安全性,降低中间人攻击行为

    根据 RFC6797 ,HSTS 标头仅注入到 HTTPS 响应中。 为了让浏览器确认标头,浏览器必须首先信任签署用于建立连接的 SSL 证书的 CA(而不仅仅是 SSL 证书)。

    Spring Security 默认提供 Strict Transport Security 标头。 但是,您可以显式自定义结果

    默认的标头

    指示浏览器将域视为 HSTS 主机一年

    Strict-Transport-Security: max-age=31536000 ; includeSubDomains ; preload
    
    • 1

    默认的严格的传输安全性

    @EnableWebSecurity
    public class WebSecurityConfig {
    
    	@Bean
    	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    		http
    			// ...
    			.headers(headers -> headers
    				.httpStrictTransportSecurity(hsts -> hsts
    					.includeSubDomains(true)
    					.preload(true)
    					.maxAgeInSeconds(31536000)
    				)
    			);
    		return http.build();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    X框架选项(X-Frame-Options)

    允许将您的网站添加到框架中可能是一个安全问题。 例如,使用巧妙的 CSS 样式可能会诱使用户点击他们不希望的内容。 例如,登录到其银行的用户可能会单击授予其他用户访问权限的按钮。 这种攻击被称为 Clickjacking

    处理点击劫持的另一种现代方法是使用 内容安全策略 (CSP)

    解决点击劫持的一种更现代的方法是使用 X-Frame-Options 标头。 默认情况下,Spring Security 使用以下标头禁用 iframe 内的渲染页面

    默认X-Frame-Options

    X-Frame-Options: DENY
    
    • 1

    设置为同源

    解释一下:如果两个页面,协议,域名,端口都一致,则为同源
    我们现在一般都是使用跨域(前后端分离

    @EnableWebSecurity
    public class WebSecurityConfig {
    
    	@Bean
    	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    		http
    			// ...
    			.headers(headers -> headers
    				.frameOptions(frameOptions -> frameOptions
    					.sameOrigin()
    				)
    			);
    		return http.build();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    X-XSS-保护

    一些浏览器内置了过滤 反射 XSS 攻击,例如Chrome,firefox,但我们为了安全还需要进行设置
    通常是默认启用,因此添加标头通常只是确保启用它并指示浏览器在检测到 XSS 攻击时该怎么做。 例如,过滤器可能会尝试以侵入性最小的方式更改内容以仍然呈现所有内容。 有时,这种类型的替换本身可能会成为 XSS 漏洞 。 相反,最好阻止内容而不是尝试修复它

    默认情况下,Spring Security 使用 指示浏览器阻止反射型 XSS 攻击。 但是,您可以更改此默认值。

    默认的X-XSS-Protection

    X-XSS-Protection: 1; mode=block
    
    • 1

    自定义X-XSS-Protection(关闭)

    以下配置指定 Spring Security 不应再指示浏览器阻止内容

    @EnableWebSecurity
    public class WebSecurityConfig {
    
    	@Bean
    	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    		http
    			// ...
    			.headers(headers -> headers
    				.xssProtection(xss -> xss
    					.block(false)
    				)
    			);
    		return http.build();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    内容安全策略 (CSP) (可作为XSS第一道防线)

    内容安全策略 (CSP) 是一种机制,Web 应用程序可以利用它来缓解内容注入漏洞,例如跨站点脚本 (XSS)。 CSP 是一种声明性策略,它为 Web 应用程序作者提供了一种工具来声明并最终通知客户端(用户代理)有关 Web 应用程序期望从中加载资源的源。

    内容安全策略并非旨在解决所有内容注入漏洞。 相反,可以利用 CSP 来帮助减少内容注入攻击造成的危害。 作为第一道防线,Web 应用程序作者应该验证他们的输入并编码他们的输出。

    Spring Security 默认不添加 Content Security Policy,因为没有应用程序的上下文就不可能知道合理的默认值。 Web 应用程序作者必须声明安全策略以强制执行和/或监控受保护资源

    启用CSP的标头

    1. Content-Security-Policy
    2. Content-Security-Policy-Report-Only

    内容安全策略示例

    Web 应用程序可以通过在响应中包含以下标头来声明它希望从特定的可信来源加载脚本

    Content-Security-Policy: script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/
    
    • 1

    尝试从其他源加载脚本,而不是在 script-src指令将被用户代理阻止。 此外,如果在安全策略中声明了 report-uri 指令,则用户代理将向声明的 URL 报告违规行为

    使用 report-uri 的内容安全策略

    如果 Web 应用程序违反了声明的安全策略,则以下响应标头将指示用户代理将违反报告发送到策略中指定的 URL report-uri指示

    Content-Security-Policy: script-src https://trustedscripts.example.com; report-uri /csp-report-endpoint/
    
    • 1

    违规报告 是标准 JSON 结构

    使用report-only的安全策略报告

    这 Content-Security-Policy-Report-Only标头为 Web 应用程序作者和管理员提供了监控安全策略的能力,而不是强制执行它们。 此标头通常在为站点试验和/或开发安全策略时使用

    给定以下响应标头,该策略声明可以从两个可能的来源之一加载脚本

    Content-Security-Policy-Report-Only: script-src 'self' https://trustedscripts.example.com; report-uri /csp-report-endpoint/
    
    • 1

    官方地址

    https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CSP

    常见用例

    一个网站管理者想要所有内容均来自站点的同一个源 (不包括其子域名)

    Content-Security-Policy: default-src 'self'
    
    • 1

    一个网站管理者允许内容来自信任的域名及其子域名 (域名不必须与 CSP 设置所在的域名相同)

    Content-Security-Policy: default-src 'self' *.trusted.com
    
    • 1

    启用CSP

    @EnableWebSecurity
    public class WebSecurityConfig {
    
    	@Bean
    	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    		http
    			// ...
    			.headers(headers -> headers
    				.contentSecurityPolicy(csp -> csp
    					.policyDirectives("script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/")
    				)
    			);
    		return http.build();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    启用 CSP report-only标头

    @EnableWebSecurity
    public class WebSecurityConfig {
    
    	@Bean
    	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    		http
    			// ...
    			.headers(headers -> headers
    				.contentSecurityPolicy(csp -> csp
    					.policyDirectives("script-src 'self' https://trustedscripts.example.com; object-src https://trustedplugins.example.com; report-uri /csp-report-endpoint/")
    					.reportOnly()
    				)
    			);
    		return http.build();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    清除站点数据 (建议结合使用)

    因为我们通常前后端分离的项目中采用前端进行一些简单的持久化处理,如吧图片,等信息存储再localStorage中,前端会进行一些处理,后端则负责自己的一些即可

    清除站点数据 是一种机制,当 HTTP 响应包含此标头时,可以通过该机制删除任何浏览器端数据(cookie、本地存储等)这是在注销时执行的一个很好的清理操作:

    Clear-Site-Data: "cache", "cookies", "storage", "executionContexts"
    
    • 1

    清理站点数据配置

    这里清除了cache和cookie

    @EnableWebSecurity
    public class WebSecurityConfig {
    
    	@Bean
    	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    		http
    			// ...
    			.logout((logout) -> logout
                    .addLogoutHandler(new HeaderWriterLogoutHandler(new ClearSiteDataHeaderWriter(CACHE, COOKIES)))
    			);
    		return http.build();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    跨域策略(请参照使用CORS)

    这里我就不介绍了,大家可以看官网,我推荐是使用SpringSecurity的CORS进行跨域配置,而不是使用跨域标头

    自定义Header

    当然我们也可以自定义一些Header,前后端分离里你需要与前后端约定好,这样

    自定义X-Custom-Security-Header

    以下配置将标头添加到响应中

    @EnableWebSecurity
    public class WebSecurityConfig {
    
    	@Bean
    	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    		http
    			// ...
    			.headers(headers -> headers
    				.addHeaderWriter(new StaticHeadersWriter("X-Custom-Security-Header","header-value"))
    			);
    		return http.build();
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  • 相关阅读:
    SQLMAP注入参数-其他参数介绍
    精密空调别再这样管理了,太麻烦啦!
    CE修改植物大战僵尸-关卡基址(小宇特详解)
    sass、scss、less区别
    ribbon负载均衡
    三项第一!天翼云通过DevSecOps能力成熟度评估认证
    【C语言】解题训练
    【培训课程专用】中断路由代码导读:当cpu运行在TEE来了一个Non secure Group1中断
    利用NVIDIA DALI读取视频帧
    一、关于回调函数在实例中的应用分析
  • 原文地址:https://blog.csdn.net/qq_51553982/article/details/126306581