2016-05-04 5 views
0

Я пытаюсь использовать golang для входа в частную зону веб-сайта и вытаскивать некоторую информацию, но я не совсем понимаю, что это правильно. Мне удается получить страницу входа в систему, чтобы получить токен csrf, а затем я помещаю токен csrf вместе с информацией для входа на страницу входа в систему, и я просто вхожу в систему. Если я остановлюсь на этом этапе, я могу увидеть страницу, на которой я перенаправлен. Однако любые последующие вызовы с этого момента перенаправят меня обратно в систему.Используйте Golang для входа на приватный сайт и вытащите информацию

Код

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) 
} 

Любая идея, что я здесь отсутствует?

+0

Ваш 'Реализация CookieJar' выглядит хорошо для меня. Вы уверены, что 'client.PostForm' удалось? Вы игнорируете ошибку там/не проверяете код состояния, поэтому я считаю безопасным предположить, что что-то вне этого кода могло привести к сбою, например, к недопустимым учетным данным. – evanmcdonnal

+0

@evanmcdonnal - Да, PostForm в порядке, никаких ошибок нет. – Twisted1919

ответ

2

Ok, вопрос реализации куков, более конкретно функция SetCookies, которая прямо сейчас:

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

И это неправильно, потому что новые печенья вместо того, чтобы быть добавлены к уже существующим, они будут просто добавляться как новые, отбрасывающие старые.

Кажется, правильный способ сделать это:

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() 
}