spring security安全防御

前言

xss攻击(跨站脚本攻击):攻击者在页面里插入恶意脚本代码,用户浏览该页面时,脚本代码就会执行,达到攻击者的目的。原理就是:攻击者对含有漏洞的服务器注入恶意代码,引诱用户浏览受到攻击的服务器,并打开相关页面,执行恶意代码。
xss攻击方式:1、反射性攻击,脚本代码做为url参数提交给服务器,服务器解析执行后,将脚本代码返回给浏览器,最后浏览器解析执行攻击代码;2、存储性攻击,和发射性攻击的区别是,脚本代码存储在服务器,下次在请求时,不用再提交脚本代码。其中一个示例图以下所示:
图片描述css

CSRF攻击:跨站请求伪造攻击,CSRF是一种欺骗受害者提交恶意请求的攻击,并劫持受害者的身份和特权,并以受害者的身份访问未受权的信息和功能。序列图以下所示:
图片描述html

同步器Token

解决XSS攻击和CSRF攻击的一个推荐方法就是同步器Token,就是在post的请求中,增长一个token,每次请求到来,服务器都会验证请求中的token和服务器指望的值是否一致,若是不一致,服务器将请求视为非法的,整个过程的示例图以下所示:
图片描述ajax

在spring security中若是使用的是 @EnableWebMvcSecurity而不是@EnableWebSecurity,同步器Token是默认打开的,经过http().csrf().disable()能够关闭同步器token功能。spring security发现token无效后,会返回一个403的访问拒绝,不过能够经过配置AccessDeniedHandler类处理InvalidCsrfTokenException异常来定制行为。spring

spring security虽然默认是打开同步器token保护的,可是也提供了一个显示打开的行为即http().csrf(),同时须要在html的form表单中添加以“<input type="hidden"name="${_csrf.parameterName}" value="${_csrf.token}"/>”json

若是请求的是json或ajax请求,如何使用同步器token防御那?
json请求的话,咱们能够在header的元数据中添加token防御,代码以下所示:浏览器

<head>
<meta name="_csrf" content="${_csrf.token}"/>
<!-- default header name is X-CSRF-TOKEN -->
<meta name="_csrf_header" content="${_csrf.headerName}"/>
...
</head>

ajax请求的话,但是使用以下代码:缓存

$(function () {
var token = $("meta[name='_csrf']").attr("content");
var header = $("meta[name='_csrf_header']").attr("content");
$(document).ajaxSend(function(e, xhr, options) {
xhr.setRequestHeader(header, token);
});
});

Synchronizer Token的常见问题
1.超时
由于token是存储在httpsession中的,因此token存在超时的问题,一旦超时,则配置的accessDeniedHandler将接受一个异常,或者spring security直接拒绝访问;
2.登陆
为了防止伪造的登陆请求,在登陆的form中也须要添加token,而token又是存储在HttpSession中,也就是说一旦发现token属性,就会建立一个HttpSession,这和无状态架构模式可能会产生一些冲突;
3.注销
添加CSRF将更新LogoutFilter过滤器,使其只使用HTTP POST。这确保了注销须要一个CSRF令牌,而且恶意用户不能强制注销您的用户。也就是说,注销再也不是一个get请求,而是一个post请求;安全

spring security支持的安全response header

spring security 支持的response header 包括:Cache-Control,Content-type options,HTTP Strict Transport Security,X-Frame-Options,X-XSS-Protection 若是你使用的是WebSecurityConfigurerAdapter 配置方式,则这些头都是默认支持的,你能够经过调用 http.header().disable()关闭这些缺省的头。固然你也能够单独配置,可是若是你单独配置的话,只有你配置的头会起做用,其余的头都再也不默认支持了。下面分别来讨论一下这些响应header的含义;服务器

Cache-Control
若是不加任何控制,浏览器一般会缓存你的认证相关信息,这在必定程度上会形成你的信息泄露,所以在默认状况下,spring security会在响应头里加入缓存控制以下所示:session

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

固然你也能够经过 http.header().cacheControl()方法单独打开缓存控制,你也能够经过HttpServletResponse.setHeader(String,String)方法对特殊的响应作处理,从而确保css js 图片可以合适地被缓存,在spring mvc中,能够经过配置进行设置,下面的代码对全部的资源都增长了缓存:

@EnableWebMvc
public class WebMvcConfiguration
     extends WebMvcConfigurerAdapter {
        @Override
        public void addResourceHandlers(
        ResourceHandlerRegistry registry) {
        registry
        .addResourceHandler("/resources/**")
        .addResourceLocations("/resources/")
        .setCachePeriod(3_155_6926);
        }
// ...
}

Content-type Options

历史上不少不少浏览器都能能够经过对请求类型的content进行嗅探,猜想请求类型,从而提升用户体验,可是这会带来XSS攻击。例若有些站点容许用户向其提交有效的postScript脚本,并查看他。恶意用户可能提交一个有效的js文件,并使用它执行XSS攻击。spring security默认是禁止进行嗅探的。

HTTP Strict Transport Security
当你访问一个站点是,例如www.baidu.com,省略了https协议,潜在的你会受到中间人攻击,为了减小这种状况,就是告知浏览器,当你输入某个地址时,应该使用https协议。如何让浏览器该host是一个hsts站点那?其中一种方法就是,增长Strict-Transport-Security 到响应头中,以下例所示:

Strict-Transport-Security: max-age=31536000 ; includeSubDomains

上述例子告知浏览器,该站点在一年内访问都使用https协议,includeSubDomains说明该站点的子域名也使用https协议访问。

X-frame-optiont

X-Frame-Options HTTP 响应头是用来给浏览器指示容许一个页面能否在 <frame>, <iframe> 或者 <object> 中展示的标记。网站可使用此功能,来确保本身网站的内容没有被嵌到别人的网站中去,也从而避免了点击劫持 (clickjacking) 的攻击。
X-Frame-Options 有三个值: DENY 表示该页面不容许在 frame 中展现,即使是在相同域名的页面中嵌套也不容许。SAMEORIGIN 表示该页面能够在相同域名页面的 frame 中展现。ALLOW-FROM uri表示该页面能够在指定来源的 frame 中展现。
Spring security默认是使用DENY,即拒绝在frame中展现,从而避免点击劫持的攻击,固然你也能够进行单独设置或对X-Frame-Option设置特殊的值。

Customer Header

Spring Security有一些机制,能够方便地向应用程序添加更常见的安全头。可是,它还提供了容许添加自定义头的钩子。有时,您但愿将自定义安全头插入到您的应用程序中,而该特性并无被支持。例如,您可能但愿尽早支持内容安全策略,以确保资源只能从相同的源加载。因为对内容安全策略的支持尚未最终肯定,浏览器使用两个常见的扩展头之一来实现这个特性。这意味着咱们将须要注入两次策略。下面的代码片断中能够看到一个头的示例:

X-Content-Security-Policy: default-src 'self'
X-WebKit-CSP: default-src 'self'
@Override
protected void configure(HttpSecurity http) throws Exception {
        http.headers()
        .addHeaderWriter(
        new StaticHeadersWriter(
        "X-Content-Security-Policy",
        "default-src 'self'"))
        .addHeaderWriter(
        new StaticHeadersWriter(
        "X-WebKit-CSP",
        "default-src 'self'"));
}

当名称空间或Java配置不支持您想要的头部时,您能够建立一个自定义的HeadersWriter实例,甚至能够提供HeadersWriter的自定义实现。让咱们看一个使用XFrameOptionsHeaderWriter的自定义实例的示例。也许您但愿容许为相同的起源构建内容框架。将策略属性设置为SAMEORIGIN很容易支持这一点:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.headers()
    .addHeaderWriter(
    new XFrameOptionsHeaderWriter(
    XFrameOptionsMode.SAMEORIGIN));
}

有时,您可能只想为某些请求编写一个header。例如,您可能只想保护您的登陆页面。您可使用DelegatingRequestMatcherHeaderWriter类来这样作。

@Override
protected void configure(HttpSecurity http) throws Exception {
    DelegatingRequestMatcherHeaderWriter headerWriter =
    new DelegatingRequestMatcherHeaderWriter(
    new AntPathRequestMatcher("/login"),
    new XFrameOptionsHeaderWriter());
    http.headers()
    .addHeaderWriter(headerWriter);
}
相关文章
相关标签/搜索