Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Cookies 使用Golang登录到私有站点并获取信息_Cookies_Go_Cookiejar - Fatal编程技术网

Cookies 使用Golang登录到私有站点并获取信息

Cookies 使用Golang登录到私有站点并获取信息,cookies,go,cookiejar,Cookies,Go,Cookiejar,我尝试使用golang登录网站的一个私人区域并获取一些信息,但我似乎没有完全正确。 我设法获取登录页面以获取csrf令牌,然后我将csrf令牌和登录信息一起发布到登录页面,然后我就可以正常登录了。如果我在这一点停止,我可以看到我被重定向的页面。但是,从这一点开始的任何后续调用都会将我重定向回登录 代码 package main import ( "github.com/PuerkitoBio/goquery" "io" _ "io/ioutil" "log"

我尝试使用golang登录网站的一个私人区域并获取一些信息,但我似乎没有完全正确。 我设法获取登录页面以获取csrf令牌,然后我将csrf令牌和登录信息一起发布到登录页面,然后我就可以正常登录了。如果我在这一点停止,我可以看到我被重定向的页面。但是,从这一点开始的任何后续调用都会将我重定向回登录

代码

package main

import (
    "github.com/PuerkitoBio/goquery"
    "io"
    _ "io/ioutil"
    "log"
    "net/http"
    "net/url"
    _ "strings"
    "sync"
)

type Jar struct {
    sync.Mutex
    cookies map[string][]*http.Cookie
}

func NewJar() *Jar {
    jar := new(Jar)
    jar.cookies = make(map[string][]*http.Cookie)
    return jar
}

func (jar *Jar) SetCookies(u *url.URL, cookies []*http.Cookie) {
    jar.Lock()
    jar.cookies[u.Host] = cookies
    jar.Unlock()
}

func (jar *Jar) Cookies(u *url.URL) []*http.Cookie {
    return jar.cookies[u.Host]
}

func NewJarClient() *http.Client {
    return &http.Client{
        Jar: NewJar(),
    }
}

func fetch(w http.ResponseWriter, r *http.Request) {

    // create the client
    client := NewJarClient()

    // get the csrf token
    req, _ := http.NewRequest("GET", "http://www.domain.com/login", nil)
    resp, err := client.Do(req)
    if err != nil {
        log.Fatal(err)
    }

    doc, err := goquery.NewDocumentFromResponse(resp)
    if err != nil {
        log.Fatal(err)
    }

    csrfToken := ""
    if val, ok := doc.Find(`head meta[name="csrf-token-value"]`).Attr("content"); ok {
        csrfToken = val
    }

    // post on the login form.
    resp, _ = client.PostForm("http://www.domain.com/login", url.Values{
        "UserLogin[email]":    {"the email"},
        "UserLogin[password]": {"the password"},
        "csrf_token":          {csrfToken},
    })

    doc, err = goquery.NewDocumentFromResponse(resp)
    if err != nil {
        log.Fatal(err)
    }

    // if i stop here then i can see just fine the dashboard where i am redirected after login.
    // but if i continue and request a 3rd page, then i get the login page again,
    // sign that i lose the cookies and i am redirected back

    // html, _ := doc.Html()
    // io.WriteString(w, html)
    // return

    // from this point on, any request will give me the login page once again.
    // i am not sure why since the cookies should be set and sent on all requests
    req, _ = http.NewRequest("GET", "http://www.domain.com/dashboard", nil)
    resp, err = client.Do(req)
    if err != nil {
        log.Fatal(err)
    }

    doc, err = goquery.NewDocumentFromResponse(resp)
    if err != nil {
        log.Fatal(err)
    }

    html, _ := doc.Html()
    io.WriteString(w, html)
}

func main() {
    http.HandleFunc("/", fetch)
    http.ListenAndServe("127.0.0.1:49721", nil)
}

知道我这里缺少什么吗?

好的,问题是cookie jar实现,更具体地说是SetCookies函数,它现在是:

func (jar *Jar) SetCookies(u *url.URL, cookies []*http.Cookie) {
    jar.Lock()
    jar.cookies[u.Host] = cookies
    jar.Unlock()
}
这是错误的,因为新的cookie不会被添加到现有的cookie中,它们只会被添加为新的cookie,而会丢弃旧的cookie

这样做的正确方法似乎是:

func (jar *Jar) SetCookies(u *url.URL, cookies []*http.Cookie) {
    jar.Lock()
    if _, ok := jar.cookies[u.Host]; ok {
        for _, c := range cookies {
            jar.cookies[u.Host] = append(jar.cookies[u.Host], c)
        }
    } else {
        jar.cookies[u.Host] = cookies
    }
    jar.Unlock()
}

您的
CookieJar
实现在我看来很不错。您确定
client.PostForm
成功吗?您忽略了那里的错误/没有检查状态代码,因此我认为可以安全地假设此代码之外的某些内容可能导致失败,例如无效凭据。@evanmcdonnal-是的,PostForm很好,没有错误。