Spring Security 自定义登陆页面报HTTP Status 403

来源:互联网 发布:矩阵半张量积等式的解 编辑:程序博客网 时间:2024/04/30 04:34

在表单中添加隐藏域

<input type="hidden"  name="${_csrf.parameterName}"   value="${_csrf.token}"/>

Spring Security默认启用CSRF 防御

官方原文:

18. Cross Site Request Forgery 跨站请求伪造(CSRF)

This section discusses Spring Security’s Cross Site Request Forgery (CSRF) support.
译:本节讨论Spring Security跨站点请求伪造(CSRF)支持。

18.1 CSRF Attacks 跨站请求伪造攻击

Before we discuss how Spring Security can protect applications from CSRF attacks, we will explain what a CSRF attack is. Let’s take a look at a concrete example to get a better understanding.

译:在我们讨论Spring Security怎么样保护应用远离CSRF攻击前,我们先解释什么是CSRF攻击。让我们看一个具体的例子,以获得更好的理解。

Assume that your bank’s website provides a form that allows transferring money from the currently logged in user to another bank account. For example, the HTTP request might look like:

译:假设您的银行的网站提供了一个表单,允许将当前登录的用户的资金转移到另一个银行帐户。例如,HTTP请求可能看起来像:

POST /transfer HTTP/1.1Host: bank.example.comCookie: JSESSIONID=randomid; Domain=bank.example.com; Secure; HttpOnlyContent-Type: application/x-www-form-urlencodedamount=100.00&routingNumber=1234&account=9876

Now pretend you authenticate to your bank’s website and then, without logging out, visit an evil website. The evil website contains an HTML page with the following form:

译:现在假装你通过认证到你的银行的网站,然后,没有退出,访问一个邪恶的网站。邪恶的网站包含以下形式的HTML页面:

<form action="https://bank.example.com/transfer" method="post"><input type="hidden"name="amount"value="100.00"/><input type="hidden"name="routingNumber"value="evilsRoutingNumber"/><input type="hidden"name="account"value="evilsAccountNumber"/><input type="submit"value="Win Money!"/></form>

You like to win money, so you click on the submit button. In the process, you have unintentionally transferred $100 to a malicious user. This happens because, while the evil website cannot see your cookies, the cookies associated with your bank are still sent along with the request.

译:你打算赢钱,因此你点击提交按钮。在这个过程中,你无意中转帐100美元给恶意用户。这是因为,虽然邪恶网站无法看到您的cookie,与您的银行相关联的cookie仍然与请求一起发送。

Worst yet, this whole process could have been automated using JavaScript. This means you didn’t even need to click on the button. So how do we protect ourselves from such attacks?

译:更糟糕的是,这个过程可以通过JavaScirpt自动执行。这意味着你不需要点击提交按钮。因此,怎么样才能保护我们自己远离这样的攻击?

18.2 Synchronizer Token Pattern

The issue is that the HTTP request from the bank’s website and the request from the evil website are exactly the same. This means there is no way to reject requests coming from the evil website and allow requests coming from the bank’s website. To protect against CSRF attacks we need to ensure there is something in the request that the evil site is unable to provide.

One solution is to use the Synchronizer Token Pattern. This solution is to ensure that each request requires, in addition to our session cookie, a randomly generated token as an HTTP parameter. When a request is submitted, the server must look up the expected value for the parameter and compare it against the actual value in the request. If the values do not match, the request should fail.

We can relax the expectations to only require the token for each HTTP request that updates state. This can be safely done since the same origin policy ensures the evil site cannot read the response. Additionally, we do not want to include the random token in HTTP GET as this can cause the tokens to be leaked.

Let’s take a look at how our example would change. Assume the randomly generated token is present in an HTTP parameter named _csrf. For example, the request to transfer money would look like this:

POST /transfer HTTP/1.1Host: bank.example.comCookie: JSESSIONID=randomid; Domain=bank.example.com; Secure; HttpOnlyContent-Type: application/x-www-form-urlencodedamount=100.00&routingNumber=1234&account=9876&_csrf=<secure-random>

You will notice that we added the _csrf parameter with a random value. Now the evil website will not be able to guess the correct value for the _csrf parameter (which must be explicitly provided on the evil website) and the transfer will fail when the server compares the actual token to the expected token.

18.3 When to use CSRF protection

When should you use CSRF protection? Our recommendation is to use CSRF protection for any request that could be processed by a browser by normal users. If you are only creating a service that is used by non-browser clients, you will likely want to disable CSRF protection.

18.3.1 CSRF protection and JSON

A common question is "do I need to protect JSON requests made by javascript?" The short answer is, it depends. However, you must be very careful as there are CSRF exploits that can impact JSON requests. For example, a malicious user can create a CSRF with JSON using the following form:

<form action="https://bank.example.com/transfer" method="post" enctype="text/plain"><input name='{"amount":100,"routingNumber":"evilsRoutingNumber","account":"evilsAccountNumber", "ignore_me":"' value='test"}' type='hidden'><input type="submit"value="Win Money!"/></form>

This will produce the following JSON structure

{ "amount": 100,"routingNumber": "evilsRoutingNumber","account": "evilsAccountNumber","ignore_me": "=test"}

If an application were not validating the Content-Type, then it would be exposed to this exploit. Depending on the setup, a Spring MVC application that validates the Content-Type could still be exploited by updating the URL suffix to end with ".json" as shown below:

<form action="https://bank.example.com/transfer.json" method="post" enctype="text/plain"><input name='{"amount":100,"routingNumber":"evilsRoutingNumber","account":"evilsAccountNumber", "ignore_me":"' value='test"}' type='hidden'><input type="submit"value="Win Money!"/></form>

18.3.2 CSRF and Stateless Browser Applications

What if my application is stateless? That doesn’t necessarily mean you are protected. In fact, if a user does not need to perform any actions in the web browser for a given request, they are likely still vulnerable to CSRF attacks.

For example, consider an application uses a custom cookie that contains all the state within it for authentication instead of the JSESSIONID. When the CSRF attack is made the custom cookie will be sent with the request in the same manner that the JSESSIONID cookie was sent in our previous example.

Users using basic authentication are also vulnerable to CSRF attacks since the browser will automatically include the username password in any requests in the same manner that the JSESSIONID cookie was sent in our previous example.

18.4 Using Spring Security CSRF Protection

So what are the steps necessary to use Spring Security’s to protect our site against CSRF attacks? The steps to using Spring Security’s CSRF protection are outlined below:

  • Use proper HTTP verbs
  • Configure CSRF Protection
  • Include the CSRF Token

18.4.1 Use proper HTTP verbs

The first step to protecting against CSRF attacks is to ensure your website uses proper HTTP verbs. Specifically, before Spring Security’s CSRF support can be of use, you need to be certain that your application is using PATCH, POST, PUT, and/or DELETE for anything that modifies state.

This is not a limitation of Spring Security’s support, but instead a general requirement for proper CSRF prevention. The reason is that including private information in an HTTP GET can cause the information to be leaked. See RFC 2616 Section 15.1.3 Encoding Sensitive Information in URI’s for general guidance on using POST instead of GET for sensitive information.

18.4.2 Configure CSRF Protection 配置CSRF保护

The next step is to include Spring Security’s CSRF protection within your application. Some frameworks handle invalid CSRF tokens by invaliding the user’s session, but this causes its own problems. Instead by default Spring Security’s CSRF protection will produce an HTTP 403 access denied. This can be customized by configuring the AccessDeniedHandler to process InvalidCsrfTokenException differently.

译:下一步是在应用程序中包含Spring Security的CSRF保护。 一些框架通过无效用户的会话来处理无效的CSRF令牌,但这会导致 自己的问题。 相反,默认情况下Spring Security的CSRF保护将导致HTTP 403访问被拒绝。 这可以通过配置AccessDeniedHandler以不同方式处理InvalidCsrfTokenException来定制。

As of Spring Security 4.0, CSRF protection is enabled by default with XML configuration. If you would like to disable CSRF protection, the corresponding XML configuration can be seen below.

译:自Spring Security 4.0后,CSRF保护默认启用。如果你想禁用CSRF保护,在配置文件中增加如下配置。

<http><!-- ... --><csrf disabled="true"/></http>

CSRF protection is enabled by default with Java Configuration. If you would like to disable CSRF, the corresponding Java configuration can be seen below. Refer to the Javadoc of csrf() for additional customizations in how CSRF protection is configured.

译:在Java Configuration 风格的配置中CSRF保护是默认启用的。如果你想禁用CSRF保护,在配置文件中增加如下配置。你也可以参考Javadoc文档添加自定义的CSRF保护配置。

@EnableWebSecuritypublic class WebSecurityConfig extendsWebSecurityConfigurerAdapter {@Overrideprotected void configure(HttpSecurity http) throws Exception {http.csrf().disable();}}

18.4.3 Include the CSRF Token 添加CSRF Token

Form Submissions

The last step is to ensure that you include the CSRF token in all PATCH, POST, PUT, and DELETE methods. One way to approach this is to use the _csrf request attribute to obtain the current CsrfToken . An example of doing this with a JSP is shown below:

译:最后一步是确保在PATCH, POST, PUT, and DELETE方法中添加了CSRF token 。通过添加_csrf请求参数来获取当前CsrfToken。例子如下

<c:url var="logoutUrl" value="/logout"/><form action="${logoutUrl}"method="post"><input type="submit"value="Log out" /><input type="hidden"name="${_csrf.parameterName}"value="${_csrf.token}"/></form>



延伸:
CSRF和XSS是两种网络攻击,为防御CSRF和XSS,需要添加隐藏域

0 0
原创粉丝点击