Chciałbym Wam pokazać jak wykorzystać Rubiego do zalogowania się na stronie www.
Aby tego dokonać musimy przesłać żądanie oraz odebrać odpowiedź, wyodrębnić ciastko i korzystać z niego do surfowania po portalu (będąc już zalogowanym).
Za przykład portalu gdzie można się zalogować, posłuży nam MyBrute. Jest to miejsce gdzie hoduje się własnego "barbarzyńcę".
Zanim przystąpimy do właściwej części, dołączmy biblioteki których potrzebujemy oraz stwórzmy sobie własną klasę błędów:
require 'net/http' require 'uri' module Exceptions class InvalidNameOrPassword < StandardError; end end
Utworzymy sobie model o nazwie MyBrute który będzie odzwierciedlał naszego Brute'a:
class MyBrute # Tutaj pójdą metody publiczne private # A tutaj prywatne end
Pierwsze co powinniśmy móc zrobić, to stworzyć naszego wojownika. W tym celu dodamy metodę inicjalizującą, która utworzy nam obiekt Net::HTTP, zapamięta co trzeba i zaloguje w systemie.
def initialize(name, pass) @name = name @password = pass @request = Net::HTTP.new("#{name}.mybrute.com", 80) login! end
Wszystko byłoby fajnie, tylko gdzie jest metoda login!? Tutaj:
def login! resp, data = @request.post('/login', "pass=#{@password}") @cookie = get_cookie(resp) end
Logowanie jest bardzo proste, wysyłamy POSTem hasło a następnie odbieramy wyniki. W wynikach mamy ciastko z pomocą którego się będziemy identyfikować. Musimy je jednak wyciągnąć z naszej odpowiedzi. W tym celu skorzystamy z metody get_cookie, która wygląda tak:
def get_cookie(resp) begin resp.response['set-cookie'].split('; ')[0] rescue raise Exceptions::InvalidNameOrPassword end end
W przypadku ciastka (co dla portalu MyBrute jest równoznaczne z błędnym logowaniem) zwracamy wyjątek, z racji tego że nie jest to standardowe zachowanie w naszm modelu.
Od teraz jesteśmy zalogowani na naszego Brute'a i możemy np dołączyć do turnieju:
def join_tournament! @request.get2("/sub",{'Cookie' => @cookie}) end
Zasadniczo, całość operacji sprowadza się do przesyłania odpowiednich danych, za pomocą odpowiedniego typu żadania, autoryzując się przy okazji ciastkiem. Jeśli chodzi o toczenie walk, to tam jest jeszcze klucz identyfikacyjny potrzebny który jest generowany po stronie serwera. Nie chciało mi się tego rozgryzać ;) więc pozostawię to dla dociekliwych. Poniżej prezentuję jeszcze całość kodu oraz wykorzystanie:
require 'net/http' require 'uri' module Exceptions class InvalidNameOrPassword < StandardError; end end class MyBrute def initialize(name, pass) @name = name @password = pass @request = Net::HTTP.new("#{name}.mybrute.com", 80) login! end def join_tournament! @request.get2("/sub",{'Cookie' => @cookie}) end private def login! resp, data = @request.post('/login', "pass=#{@password}") @cookie = get_cookie(resp) end def get_cookie(resp) begin resp.response['set-cookie'].split('; ')[0] rescue raise Exceptions::InvalidNameOrPassword end end end
Wykorzystanie:
brute = MyBrute.new('login', 'haslo') brute.join_tournament!