Eri*_*eim 1 python authentication csrf go
我想自动备份需要登录的网站的网页内容。我尝试通过模拟 POST 请求来登录。但我收到错误:
csrf token: CSRF attack detected
Run Code Online (Sandbox Code Playgroud)
以下是我使用的代码的一些摘录:
func postLoginForm(csrfToken string) {
values := make(url.Values)
values.Set("signin[username]", "myusername")
values.Set("signin[password]", "mypassword")
values.Set("signin[_csrf_token]", csrfToken)
resp, err := http.PostForm("https://spwebservicebm.reaktor.no/admin/nb", values)
dumpHTTPResponse(resp) // show response to STDOUT
}
Run Code Online (Sandbox Code Playgroud)
我通过获取登录页面并扫描名为 的隐藏输入字段来获取 csrf 令牌signin[_csrf_token]。执行此操作的代码的重要部分如下:
// Finds input field named signin[_csrf_token] and returns value as csrfToken
func handleNode(n *html.Node) (csrfToken string, found bool) {
if n.Type == html.ElementNode && n.Data == "input" {
m := make(map[string]string)
for _, attr := range n.Attr {
m[attr.Key] = attr.Val
}
if m["name"] == "signin[_csrf_token]" {
return m["value"], true
}
}
for c := n.FirstChild; c != nil; c = c.NextSibling {
if csrfToken, found = handleNode(c); found {
return
}
}
return "", false
}
Run Code Online (Sandbox Code Playgroud)
我不需要使用 Go,那只是因为我最熟悉它。使用 python 也可能是一个解决方案,但我对此没有任何运气。
问题是 Go 1.2 不会自动为其 HTTP 请求使用 cookie jar。第一个请求是从登录页面获取 CSRF 令牌。第二个请求是使用该 CSRF 令牌发布登录信息。但由于第二次请求的 HTTP 标头中没有附加任何会话 cookie,服务器不知道它是尝试登录的同一个程序。因此,服务器认为这是一次 CSRF 尝试(您从其他地方选择了 CSRF 令牌并尝试重用它)。
因此,为了获取登录页面并提取 CSRF 令牌,我们首先创建自己的客户端对象。否则我们就没有地方可以放置饼干罐了。http.PostForm确实允许访问 cookie jar:
client = &http.Client{}
Run Code Online (Sandbox Code Playgroud)
创建一个 cookie Jar,如来自 golang 的经过身份验证的 http 客户端请求中所述。这比官方的更容易设置和调试: http: //golang.org/pkg/net/http/cookiejar/ Cookie Jar
jar := &myjar{}
jar.jar = make(map[string] []*http.Cookie)
client.Jar = jar
resp, err := client.Get("https://spwebservicebm.reaktor.no/admin")
doc, err := html.Parse(resp.Body)
Run Code Online (Sandbox Code Playgroud)
然后,为了登录,我们重用带有附加 cookie jar 的客户端对象:
values := make(url.Values)
values.Set("signin[username]", "myusername")
values.Set("signin[password]", "mypassword")
values.Set("signin[_csrf_token]", csrfToken)
resp, err := client.PostForm("https://spwebservicebm.reaktor.no/admin/login", values)
Run Code Online (Sandbox Code Playgroud)
您会注意到,代码几乎与问题中的代码相同,只是我们使用client.PostForm代替http.PostForm。
感谢 dommage 和对来自 golang 的经过身份验证的 http 客户端请求的答复,让我走上了正轨。
| 归档时间: |
|
| 查看次数: |
3820 次 |
| 最近记录: |