设置Ring-Anti-Forgery CSRF标头令牌 [英] Set Ring-Anti-Forgery CSRF header token

查看:299
本文介绍了设置Ring-Anti-Forgery CSRF标头令牌的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过设置X-CSRF来实施 Ring-Anti-Forgery 库-Token in the header。



因为我使用静态html文件,我发现内置的hiccup助手,设置形式的令牌,是无用的。 / p>

这是我第一次使用Clojure进行web开发,所以我猜测我完全错过了对有经验的人应该显而易见的东西。



README状态的指示:


中间件还会查找X-CSRF-Token中的令牌和
X-XSRF-Token头字段。此行为可以使用:read-token选项进一步定制




  (defn get-custom-token [request] 
(get-in request [:headersx-forgery-token]))

(def app
; handler
(wrap-anti-forgery {:read-token get-custom-token})
(wrap-session)))

我已将上述内容添加到 handler.clj ,但未成功。



strong> project.clj

 (defproject hooktale0.0.1
:descriptionHooktale iOS应用网站
:urlhttp://www.hooktale.com
:repositories {sonartype releaseshttps://oss.sonatype.org/content/repositories/releases/}
:source-paths [src / cljsrc / cljs]
:dependencies [[org.clojure / clojure1.5.1]
[org.clojure / clojurescript 0.0-2080]
[org.clojure / java.jdbc0.3.0-beta2]
[compojure1.1.6]
[com.mchange / c3p0 5-pre5]
[org.postgresql / postgresql9.3-1100-jdbc4]
[ring-anti-forgery0.3.0]]
:plugins [[lein- ring0.8.8]
[lein-cljsbuild1.0.1-SNAPSHOT]]
:ring {:handler hooktale.handler / app}
:profiles {:dev { plugins [[javax.servlet / servlet-api2.5]
[ring-mock0.1.5]]
:cljsbuild {:builds [{:source-paths [src / cljs ]
:compiler {:optimizations:advanced
:pretty-print false
:output-toresources / public / js / trout.js}}]}}})

handler.clj

 (ns hooktale.handler 
(:require [compojure.core:refer [defroutes GET POST]]
[compojure.handler:refer [site]]
[compojure.route:refer [resources not-found]]
[clojure.java.io:refer [resource]]
[ring.middleware.anti-forgery:refer:all]


[hooktale.controllers.prospect:refer [create-prospect]]))

$ b [令牌
(获取请求[:headersx-forgery-token]))

(defroutes app-routes
(GET/[] (资源public / index.html))
(POST/[email](create-prospect email))
(资源/)
Found))

(def app
( - >
(site app-routes)
(wrap-anti-forgery {:read-token get-custom-token})
(wrap-session)))

向页面发送请求会返回以下信息:



curl -I localhost:3000

  HTTP / 1.1 200 OK 
日期:Fri,06 Dec 2013 16:30:45 GMT
Set-Cookie:ring-session = 0b2a477f-9352-4fd8-a3c3-a6b6f8d9e063; Path = /
Content-Length:0
服务器:Jetty(7.6.8.v20121106)

-d'{:emailpiglet@aol.com}'localhost:3000

  ; h1>无效的防伪令牌< / h1> 

ring.middleware.anti-forgery中的函数,我认为这将允许我设置令牌

 (defn- default-request-token [request] 
(或( - > request form-params(get__anti-forgery-token))
( - > request:headers(getx-csrf-token))
( - > request:headers(getx-xsrf-token))))

如果我正确地读取它,它将检查表单中的令牌,如果没有,它将检查x-csrf-token,然后在头中的x-xsrf-token。



我似乎很难在标题中实际设置x-csrf-token或x-xsrf-token的值。



Curl responses



查看由环会话设置的Cookie:



curl -I localhost:3000

  HTTP / 1.1 200 OK 
日期: Fri,06 Dec 2013 19:52:22 GMT
Set-Cookie:ring-session = b02dd6f8-74b8-4ce0-a1d6-07251dadb9aa; Path = /
Content-Length:0
服务器:Jetty(7.6.8.v20121106)

设置X-CSRF-令牌:



curl -v --headerX-CSRF-Token:b02dd6f8-74b8-4ce0-a1d6-07251dadb9aa; Path = /-X POST -d' {:emailstarbuck@bsg.com}'localhost:3000

  *添加句柄: conn:0x7fd3ab004000 
*添加句柄:发送:0
*添加句柄:recv:0
* Curl_addHandleToPipeline:length:1
* - Conn 0(0x7fd3ab004000)send_pipe: recv_pipe:0
*关于连接()到本地端口3000(#0)
* Trying :: 1 ...
*连接到localhost(:: 1)端口3000 0)
> POST / HTTP / 1.1
> User-Agent:curl / 7.30.0
>主机:localhost:3000
>接受:* / *
> X-CSRF-Token:b02dd6f8-74b8-4ce0-a1d6-07251dadb9aa; Path = /
> content-length:27
> Content-Type:application / x-www-form-urlencoded
>
*上传完全发送:27个字节
< HTTP / 1.1 403禁止
<日期:Fri,06 Dec 2013 19:54:52 GMT
< Content-Type:text / html; charset = ISO-8859-1
< Content-Length:35
*服务器Jetty(7.6.8.v20121106)未列入黑名单
<服务器:Jetty(7.6.8.v20121106)
<
*连接#0到主机本地主机保持原样
< h1>无效的防伪令牌< / h1>


解决方案

我创建了一个存储库https://github.com/edbond/CSRF 与示例。自述描述了使用CSRF令牌发出POST请求所需的过程。



简而言之(对于API调用,curl):


  1. 从服务器获取CSRF令牌和会话cookie(服务器将在您的会话中存储CSRF令牌,由cookie标识)


  2. 发送X-CSRF-Token和cookie以及POST请求(服务器将比较CSRF令牌与由cookie标识的会话中存储的令牌)


cookie - > session - > CSRF-Token



对于HTML,表单POSTing应该足以包含(反伪造字段) 。注意,您也可以使用curl发送表单字段,而不是标题。



HTH


I'm attempting to implement the Ring-Anti-Forgery library via setting the X-CSRF-Token in the header.

Since I am using static html files I found the built-in hiccup helper, which sets the token in the form, to be useless.

This is my first stab at using Clojure for web development so I'm guessing that I am completely missing what should be obvious to someone with experience.

The instructions from the README state:

The middleware also looks for the token in the X-CSRF-Token and X-XSRF-Token header fields. This behavior can be customized further using the :read-token option:

(defn get-custom-token [request]
  (get-in request [:headers "x-forgery-token"]))

(def app
  (-> handler
      (wrap-anti-forgery {:read-token get-custom-token})
      (wrap-session)))

I have added the above to handler.clj without any success.

project.clj

(defproject hooktale "0.0.1"
  :description "Hooktale iOS App Website"
  :url "http://www.hooktale.com"
  :repositories {"sonartype releases" "https://oss.sonatype.org/content/repositories/releases/"}
  :source-paths ["src/clj" "src/cljs"]
  :dependencies [[org.clojure/clojure "1.5.1"]
                 [org.clojure/clojurescript "0.0-2080"]
                 [org.clojure/java.jdbc "0.3.0-beta2"]
                 [compojure "1.1.6"]
                 [com.mchange/c3p0 "0.9.5-pre5"]
                 [org.postgresql/postgresql "9.3-1100-jdbc4"]
                 [ring-anti-forgery "0.3.0"]]
  :plugins [[lein-ring "0.8.8"]
            [lein-cljsbuild "1.0.1-SNAPSHOT"]]
  :ring {:handler hooktale.handler/app}
  :profiles {:dev {:plugins [[javax.servlet/servlet-api "2.5"]
                             [ring-mock "0.1.5"]]
                   :cljsbuild {:builds [{:source-paths ["src/cljs"]
                                         :compiler {:optimizations :advanced
                                                    :pretty-print false
                                                    :output-to "resources/public/js/trout.js"}}]}}})

handler.clj

(ns hooktale.handler
  (:require [compojure.core :refer [defroutes GET POST]]
            [compojure.handler :refer [site]]
            [compojure.route :refer [resources not-found]]
            [clojure.java.io :refer [resource]]
            [ring.middleware.anti-forgery :refer :all]
            [ring.middleware.session :refer [wrap-session]]
            [hooktale.controllers.prospect :refer [create-prospect]]))

(defn get-custom-token [request]
  (get-in request [:headers "x-forgery-token"]))

(defroutes app-routes
  (GET "/" [] (resource "public/index.html"))
  (POST "/" [email] (create-prospect email))
  (resources "/")
  (not-found "Not Found"))

(def app
  (->
   (site app-routes)
   (wrap-anti-forgery {:read-token get-custom-token})
   (wrap-session)))

Sending a request to the page returns the following info:

curl -I localhost:3000

HTTP/1.1 200 OK
Date: Fri, 06 Dec 2013 16:30:45 GMT
Set-Cookie: ring-session=0b2a477f-9352-4fd8-a3c3-a6b6f8d9e063;Path=/
Content-Length: 0
Server: Jetty(7.6.8.v20121106)

curl -X POST -d '{:email "piglet@aol.com"}' localhost:3000

<h1>Invalid anti-forgery token</h1>

The function in ring.middleware.anti-forgery that I thought would allow me to set the token in the header without having to set the hidden token value inside the form field.

(defn- default-request-token [request]
  (or (-> request form-params (get "__anti-forgery-token"))
      (-> request :headers (get "x-csrf-token"))
      (-> request :headers (get "x-xsrf-token"))))

If I am reading it correctly, it will check for the token in the form, if not there it will check for the x-csrf-token then the x-xsrf-token in the header.

I seem to be having difficulty in actually setting the value of x-csrf-token or x-xsrf-token in the header.

Curl responses

View the Cookie set by ring-session:

curl -I localhost:3000

HTTP/1.1 200 OK
Date: Fri, 06 Dec 2013 19:52:22 GMT
Set-Cookie: ring-session=b02dd6f8-74b8-4ce0-a1d6-07251dadb9aa;Path=/
Content-Length: 0
Server: Jetty(7.6.8.v20121106)

Setting the X-CSRF-Token:

curl -v --header "X-CSRF-Token: b02dd6f8-74b8-4ce0-a1d6-07251dadb9aa;Path=/" -X POST -d '{:email "starbuck@bsg.com"}' localhost:3000

* Adding handle: conn: 0x7fd3ab004000
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x7fd3ab004000) send_pipe: 1, recv_pipe: 0
* About to connect() to localhost port 3000 (#0)
*   Trying ::1...
* Connected to localhost (::1) port 3000 (#0)
> POST / HTTP/1.1
> User-Agent: curl/7.30.0
> Host: localhost:3000
> Accept: */*
> X-CSRF-Token: b02dd6f8-74b8-4ce0-a1d6-07251dadb9aa;Path=/
> Content-Length: 27
> Content-Type: application/x-www-form-urlencoded
>
* upload completely sent off: 27 out of 27 bytes
< HTTP/1.1 403 Forbidden
< Date: Fri, 06 Dec 2013 19:54:52 GMT
< Content-Type: text/html;charset=ISO-8859-1
< Content-Length: 35
* Server Jetty(7.6.8.v20121106) is not blacklisted
< Server: Jetty(7.6.8.v20121106)
<
* Connection #0 to host localhost left intact
<h1>Invalid anti-forgery token</h1>

解决方案

I created a repository https://github.com/edbond/CSRF with example. Readme describes process needed to POST requests with CSRF token.

In short (for API calls, curl):

  1. Get CSRF Token and session cookie from server (server will store CSRF token inside your session which identified by cookie)

  2. Send X-CSRF-Token and cookie along with POST request (server will compare CSRF token with that stored inside your session identified by cookie)

cookie -> session -> CSRF-Token

For HTML, form POSTing it should be enough to include (anti-forgery-field) to forms. Note, you can also send form field instead of header using curl.

HTH

这篇关于设置Ring-Anti-Forgery CSRF标头令牌的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆