2012-03-21 20 views
6

Recientemente utilicé Mechanize para este tipo de cosas, pero quiero usar Typhoeus, que ya estoy usando en otros lugares. Quiero imitar el comportamiento de Mechanize, el problema es que me gustaría iniciar sesión en un sitio y realizar solicitudes como usuario conectado. He aquí la versión generalizada del guión:Iniciar sesión manualmente en el sitio web con Typheous

require 'rubygems' 
require 'typhoeus' 

GET_URL = 'http://localhost:3000' 
POST_URL = "http://localhost:3000/admins/sign_in" 
URL = "http://localhost:3000/dashboard" 
USERNAME_FIELD = 'admin[email]' 
PASSWORD_FIELD = 'admin[password]' 
USERNAME = "[email protected]" 
PASSWORD = "my_secret_password" 

def merge_cookies_into_cookie_jar(response)        
    if response.headers_hash['set-cookie'].instance_of? Array 
    response.headers_hash['set-cookie'].each do |cookie| 
     @cookie_jar << cookie.split('; ')[0] 
    end 
    elsif response.headers_hash['set-cookie'].instance_of? String 
    @cookie_jar << response.headers_hash['set-cookie'].split('; ')[0] 
    end   
end 

# initialize cookie jar 
@cookie_jar = [] 

# for server to establish me a session 
response = Typhoeus::Request.get(GET_URL, :follow_location => true) 
merge_cookies_into_cookie_jar(response)             

# like submiting a log in form 
response = Typhoeus::Request.post(POST_URL, 
            :params => { USERNAME_FIELD => USERNAME, PASSWORD_FIELD => PASSWORD }, 
            :headers => { 'Cookie' => @cookie_jar.join('; ') } 
           ) 
merge_cookies_into_cookie_jar(response)             

# the page I'd like to get in a first place, 
# but not working, redirects me back to login form with 401 Unauthorized :-(     
response = Typhoeus::Request.get(URL, 
            :follow_location => true, 
            :headers => { 'Cookie' => @cookie_jar.join('; ') } 
           ) 

La cookie se envía al servidor, pero por alguna razón no estoy inscrito he comprobado en dos sitios diferentes (que uno de ellos era de mi aplicación Rails. administración). ¿Alguna idea de qué estoy haciendo mal o quizás una solución mejor o más aplicable a este problema?

Respuesta

8

Aquí está el código que soy capaz de ejecutar correctamente.

Primero, su cookie jar es una matriz, y en mi código debe ser una matriz con reemplazo (o una hash). Cuando ejecuto el código en una aplicación real mía, la respuesta GET_URL devuelve una cookie de sesión, pero la respuesta POST_URL devuelve una cookie de sesión diferente.

# initialize cookie jar as a Hash 
@cookie_jar = {} 

Ajuste el análisis para que pueda obtener el nombre y de cada galleta valor:

def merge_cookies_into_cookie_jar(response) 
    x = response.headers_hash['set-cookie'] 
    case x 
    ... 
    when String 
    x.split('; ').each{|cookie| 
     key,value=cookie.split('=', 2) 
     @cookie_jar[key]=value 
    } 
    end 
end 

El tarro de galletas tiene que convertir en una cadena:

def cookie_jar_to_s 
    @cookie_jar.to_a.map{|key, val| "#{key}=#{val}"}.join("; ") 
end 

Por último, cambiar los encabezados de usar el nuevo cookie_jar_to_s:

:headers => { 'Cookie' => cookie_jar_to_s } 

Un bono sería hacer la masa de su propia clase, tal vez algo como esto:

class CookieJar < Hash 

    def to_s 
    self.to_a.map{|key, val| "#{key}=#{val}"}.join("; ") 
    end 

    def parse(*cookie_strings) 
    cookie_strings.each{|s| 
     s.split('; ').each{|cookie| 
     key,value=cookie.split('=', 2) 
     self.[key]=value 
     } 
    } 
    end 

end 
1

¿Están sus sitios utilizando la protección de falsificación de rieles?

Si es así, cuando obtiene la página de formulario, Rails está enviando un campo oculto que es un token de CSRF.

Se verá algo como esto en HTML:

<input type="hidden" name="csrf" value="abcdef"> 

Es necesario utilizar este valor oculto cuando usted envía su formulario:

:params => {"csrf" => "abcdef", USERNAME_FIELD => USERNAME, ... 

El campo oculto dice rieles que usted es la persona quién hizo la solicitud de la página del formulario, por lo que usted (y solo usted) puede publicar.

Éstos son mis notas sobre CSRF con enlaces a más información:

http://sixarm.com/about/rails-session-csrf-token-jquery-ajaxprefilter.html 

relacionada Stackoverflow CSRF Info:

http://stackoverflow.com/questions/941594/understand-rails-authenticity-token 
+0

Desactivar la protección CSRF en mi aplicación fue lo primero que he intentado. Sin embargo, el segundo sitio en el que lo probé es una aplicación PHP normal sin eso, así que creo que el problema no está ahí.Coloque el script arriba en el archivo, instale typhoeus con 'gem install typhoeus', cambie las constantes en la parte superior, intente si funciona para usted y hágamelo saber. Realmente aprecio tu interés. Gracias. – Kreeki

3

he fijado @ CookieJar de joelparkerhenderson (ya que no estaba trabajando aquí). Aquí el resultado:

class CookieJar < Hash 
    def to_s 
    self.map { |key, value| "#{key}=#{value}"}.join("; ") 
    end 

    def parse(cookie_strings) 
    cookie_strings.each { |s| 
     key, value = s.split('; ').first.split('=', 2) 
     self[key] = value 
    } 
    self 
    end 
end 

# Use like this: 
response = Typhoeus::Request.get("http://www.example.com") 
cookies = CookieJar.new.parse(response.headers_hash["Set-Cookie"]) 
Typhoeus::Request.get("http://www.example.com", headers: {Cookie: cookies.to_s}) 
Cuestiones relacionadas