2011-06 << 2011-07 >> 2011-08

2011-07-16 (土)

*[ruby] Rubyのnet/httpでGoogleにログイン

アプリケーションからログインする方法は

このあたり読めば分かる.

普段はgemのhttpclient使ってるのだけど,net/httpでやってみる.SSL証明書確認しないとか,Cookieの送信でホスト名しか見て無いとかは後で考える.

require 'uri'
require 'net/https'
Net::HTTP.version_1_2

class HTTPClient
    def initialize
        @cookies = {}
        @timeout = 60
    end
    attr_accessor :timeout, :cookies

    def formencode data
        return data.map{|k,v| k+'='+URI.encode(v.to_s)}.join('&')
    end

    def pre_proc uri,headers = nil
        headers = headers || {}
        if @cookies[uri.host]
            headers['Cookie'] = @cookies[uri.host].map{|k,v|k+'='+v}.join(';')
        end
        http = Net::HTTP.new(uri.host,uri.port)
        http.read_timeout = @timeout
        if uri.scheme == 'https'
            http.use_ssl = true
            http.verify_mode = OpenSSL::SSL::VERIFY_NONE
        end
        return http,headers
    end

    def post_proc uri,response
        if response['Set-Cookie']
            if ! @cookies[uri.host]
                @cookies[uri.host] = {}
            end
            response.get_fields('Set-Cookie').each{|str|
                k,v = (str.split(';'))[0].split('=')
                @cookies[uri.host][k] = v
            }
        end
        return response
    end

    def get url,headers = nil,&block
        uri = URI.parse(url)
        http,headers = pre_proc(uri)
        r = http.get(uri.request_uri,headers,&block)
        return post_proc(uri,r)
    end

    def post url,body,headers = nil,&block
        uri = URI.parse(url)
        headers = {'Content-type' => 'application/x-www-form-urlencoded'}
        http,headers = pre_proc(uri,headers)
        if body.kind_of? Hash
            body = formencode(body)
        end
        r = http.post(uri.request_uri,body,headers,&block)
        return post_proc(uri,r)
    end
end

account = {
    'accountType' => 'HOSTED_OR_GOOGLE',
    'Email' =>  'example@gmail.com',
    'Passwd' => 'hoge',
    'service' => 'ah', # GMAIL:mail GAE:ah CAL:cl PLUS:oz
    'source' => 'gaetest',
}

client = HTTPClient.new
r = client.post('https://www.google.com/accounts/ClientLogin',account)
if r.body =~ /Auth=([^\s]+)/
    r = client.get('https://example.appspot.com/_ah/login?continue=/&auth=' + $1)
end

Cookieセットされるので後は普通にアクセスするだけ.やっぱ,net/httpでやるのは無いな....ただ,gemsすら入ってない環境がたまにあるので,いざというときのために貼り付けておく.

2011-06 << 2011-07 >> 2011-08