RestTemplate的JSON CSRF拦截器

时间:2015-08-15 21:57:18

标签: json spring-security csrf

我有一个小的Rest-Service应用程序(Java 8,Spring 4.1.6,Spring Security 5.0.1,Jetty 9.3),我正在使用Spring RestTemplate通过JSON访问一些服务。到目前为止,csfr已被禁用,现在我想启用它。

据了解,csfr有一个公共令牌(客户端随每个请求发送它,服务器将它存储在会话中),在服务器端进行比较。如果没有可用的令牌或令牌不同,则拒绝访问。

所以我认为通过使用拦截器进行这种令牌添加是个好主意。我也读过,在json中我必须将令牌作为头参数发送......但我做错了,登录失败了。

这是login-source:

import java.io.IOException;
import java.util.UUID;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpRequest;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;

public class MyCsfrInterceptor implements ClientHttpRequestInterceptor{

    public static final String CSRF_TOKEN_HEADER_NAME = "X-CSRF-TOKEN";
    public static final String csrfSessionToken = UUID.randomUUID().toString();

    private static Logger LOG = LoggerFactory.getLogger(MyCsfrInterceptor.class);

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        LOG.info("My interceptor called!");
        if (request.getMethod() == HttpMethod.DELETE ||
                request.getMethod() == HttpMethod.POST ||
                request.getMethod() == HttpMethod.PATCH ||
                request.getMethod() == HttpMethod.PUT){
            LOG.info("Setting csrf token...");
            request.getHeaders().add(CSRF_TOKEN_HEADER_NAME, csrfSessionToken);
        }
        return execution.execute(request, body);
    }

}

这里是拦截器的来源:

23:24:40.605 [main] DEBUG c.m.l.w.client.StatefulRestTemplate - Created POST request for "http://localhost:8080/login"
23:24:40.610 [main] DEBUG c.m.l.w.client.StatefulRestTemplate - Writing [{username=[user], password=[user]}] using [org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter@618b19ad]
23:24:40.615 [main] INFO  c.m.l.w.client.MyCsfrInterceptor - My interceptor called!
23:24:40.615 [main] INFO  c.m.l.w.client.MyCsfrInterceptor - Setting csrf token...
23:24:40.650 [main] DEBUG o.a.h.c.protocol.RequestAddCookies - CookieSpec selected: best-match
23:24:40.670 [main] DEBUG o.a.h.c.protocol.RequestAuthCache - Auth cache not set in the context
23:24:40.675 [main] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Connection request: [route: {}->http://localhost:8080][total kept alive: 0; route allocated: 0 of 2; total allocated: 0 of 20]
23:24:40.705 [main] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Connection leased: [id: 0][route: {}->http://localhost:8080][total kept alive: 0; route allocated: 1 of 2; total allocated: 1 of 20]
23:24:40.710 [main] DEBUG o.a.h.impl.execchain.MainClientExec - Opening connection {}->http://localhost:8080
23:24:40.715 [main] DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connecting to localhost/127.0.0.1:8080
23:24:40.715 [main] DEBUG o.a.h.i.c.HttpClientConnectionOperator - Connection established 127.0.0.1:54712<->127.0.0.1:8080
23:24:40.715 [main] DEBUG o.a.h.impl.execchain.MainClientExec - Executing request POST /login HTTP/1.1
23:24:40.715 [main] DEBUG o.a.h.impl.execchain.MainClientExec - Target auth state: UNCHALLENGED
23:24:40.720 [main] DEBUG o.a.h.impl.execchain.MainClientExec - Proxy auth state: UNCHALLENGED
23:24:40.720 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> POST /login HTTP/1.1
23:24:40.720 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> Content-Type: application/x-www-form-urlencoded
23:24:40.720 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> X-CSRF-TOKEN: 99ca8171-b8e0-4b95-8d06-3759a874c64b
23:24:40.720 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> Content-Length: 27
23:24:40.720 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> Host: localhost:8080
23:24:40.720 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> Connection: Keep-Alive
23:24:40.720 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> User-Agent: Apache-HttpClient/4.3.4 (java 1.5)
23:24:40.720 [main] DEBUG org.apache.http.headers - http-outgoing-0 >> Accept-Encoding: gzip,deflate
23:24:40.720 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "POST /login HTTP/1.1[\r][\n]"
23:24:40.720 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "Content-Type: application/x-www-form-urlencoded[\r][\n]"
23:24:40.720 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "X-CSRF-TOKEN: 99ca8171-b8e0-4b95-8d06-3759a874c64b[\r][\n]"
23:24:40.720 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "Content-Length: 27[\r][\n]"
23:24:40.720 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "Host: localhost:8080[\r][\n]"
23:24:40.720 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "Connection: Keep-Alive[\r][\n]"
23:24:40.720 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "User-Agent: Apache-HttpClient/4.3.4 (java 1.5)[\r][\n]"
23:24:40.720 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "Accept-Encoding: gzip,deflate[\r][\n]"
23:24:40.720 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "[\r][\n]"
23:24:40.720 [main] DEBUG org.apache.http.wire - http-outgoing-0 >> "username=user&password=user"
23:24:40.831 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "HTTP/1.1 403 Expected CSRF token not found. Has your session expired?[\r][\n]"
23:24:40.831 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "Date: Sat, 15 Aug 2015 21:24:40 GMT[\r][\n]"
23:24:40.831 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "Pragma: no-cache[\r][\n]"
23:24:40.831 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "X-XSS-Protection: 1; mode=block[\r][\n]"
23:24:40.831 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "X-Frame-Options: DENY[\r][\n]"
23:24:40.831 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "X-Content-Type-Options: nosniff[\r][\n]"
23:24:40.831 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "Set-Cookie: JSESSIONID=1bvmexep1lv9h1qja44hflx0wg;Path=/[\r][\n]"
23:24:40.831 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "Content-Type: text/html;charset=iso-8859-1[\r][\n]"
23:24:40.831 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "Cache-Control: must-revalidate,no-cache,no-store[\r][\n]"
23:24:40.831 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "Content-Length: 409[\r][\n]"
23:24:40.831 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "Server: Jetty(9.3.0.RC1)[\r][\n]"
23:24:40.831 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "[\r][\n]"
23:24:40.831 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "<html>[\n]"
23:24:40.831 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "<head>[\n]"
23:24:40.831 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "<meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>[\n]"
23:24:40.831 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "<title>Error 403 Expected CSRF token not found. Has your session expired?</title>[\n]"
23:24:40.831 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "</head>[\n]"
23:24:40.831 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "<body><h2>HTTP ERROR 403</h2>[\n]"
23:24:40.831 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "<p>Problem accessing /login. Reason:[\n]"
23:24:40.831 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "<pre>    Expected CSRF token not found. Has your session expired?</pre></p><hr><a href="http://eclipse.org/jetty">Powered by Jetty:// 9.3.0.RC1</a><hr/>[\n]"
23:24:40.831 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "[\n]"
23:24:40.831 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "</body>[\n]"
23:24:40.831 [main] DEBUG org.apache.http.wire - http-outgoing-0 << "</html>[\n]"
23:24:40.836 [main] DEBUG org.apache.http.headers - http-outgoing-0 << HTTP/1.1 403 Expected CSRF token not found. Has your session expired?
23:24:40.836 [main] DEBUG org.apache.http.headers - http-outgoing-0 << Date: Sat, 15 Aug 2015 21:24:40 GMT
23:24:40.836 [main] DEBUG org.apache.http.headers - http-outgoing-0 << Pragma: no-cache
23:24:40.836 [main] DEBUG org.apache.http.headers - http-outgoing-0 << X-XSS-Protection: 1; mode=block
23:24:40.836 [main] DEBUG org.apache.http.headers - http-outgoing-0 << X-Frame-Options: DENY
23:24:40.836 [main] DEBUG org.apache.http.headers - http-outgoing-0 << X-Content-Type-Options: nosniff
23:24:40.836 [main] DEBUG org.apache.http.headers - http-outgoing-0 << Set-Cookie: JSESSIONID=1bvmexep1lv9h1qja44hflx0wg;Path=/
23:24:40.836 [main] DEBUG org.apache.http.headers - http-outgoing-0 << Content-Type: text/html;charset=iso-8859-1
23:24:40.836 [main] DEBUG org.apache.http.headers - http-outgoing-0 << Cache-Control: must-revalidate,no-cache,no-store
23:24:40.836 [main] DEBUG org.apache.http.headers - http-outgoing-0 << Content-Length: 409
23:24:40.836 [main] DEBUG org.apache.http.headers - http-outgoing-0 << Server: Jetty(9.3.0.RC1)
23:24:40.846 [main] DEBUG o.a.h.impl.execchain.MainClientExec - Connection can be kept alive indefinitely
23:24:40.861 [main] DEBUG o.a.h.c.p.ResponseProcessCookies - Cookie accepted [JSESSIONID="1bvmexep1lv9h1qja44hflx0wg", version:0, domain:localhost, path:/, expiry:null]
23:24:40.861 [main] DEBUG c.m.l.w.client.StatefulRestTemplate - POST request for "http://localhost:8080/login" resulted in 403 (Expected CSRF token not found. Has your session expired?); invoking error handler
23:24:40.866 [main] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Connection [id: 0][route: {}->http://localhost:8080] can be kept alive indefinitely

以下是客户端的日志输出:

'" . isChecked(<params>) . "'

在spring security config中,我没有做任何csrf配置。

那有什么不对?我把标题设置错了吗?任何配置缺失?

致以最诚挚的问候,谢谢您的时间。

0 个答案:

没有答案