

個人的な興味で、  
トークンを用いているホームページに  
ログインしてスクレイピングしてみたいと思って、  
書いてみたのですが、そもそもログインからしてうまく行きません。  
原因は何なのか出来る限り自分でも調べたのですが、よくわかりません。

以下コードですが、

値として、data[_Token][key]とdata[_Token][fields]はページを手動検索して取得。  
ほかは知っているので、４つの値をそれぞれ入力。といった感じです。  
値はクロームの機能で調べてみましたが、あってるのかはよくわかりません。

結果は、ログイン失敗ページにリダイレクトされた旨のHTML内容が返ってきます。

まだJAVA歴が数ヶ月しかなく、  
WEB関連部分は知識がかなり不足している状態なので、  
コードに致命的に間違っている部分があったかもしれません……。  
ご教示いただけると助かります。

[code]

    public static void main(String[] args) throws Exception {
    
    
        String USER_AGENT = "Mozilla/5.0";
        String url = "https://www.lancers.jp/user/login";
        String user = "https://www.lancers.jp/mypage";
        HttpGet get = new HttpGet(url);
        HttpPost post = new HttpPost(url);
    
        RequestConfig reqconf = RequestConfig.custom()
                .setCircularRedirectsAllowed(true)
                .setRedirectsEnabled(true)
                .build();
        List<Header> headers = new ArrayList<Header>();
        headers.add(new BasicHeader("User-Agent", USER_AGENT));
        headers.add(new BasicHeader("Accept-Charset","utf-8"));
        headers.add(new BasicHeader("Accept-Language","ja, en;q=0.8"));
        headers.add(new BasicHeader("Content-Type", "application/x-www-form-urlencoded"));
    
        CloseableHttpClient client = HttpClientBuilder.create()
                .setRedirectStrategy(new LaxRedirectStrategy())
                .setDefaultRequestConfig(reqconf)
                .setDefaultHeaders(headers)
                .build();
    
        CloseableHttpResponse loginpage = client.execute(get);
        String loginpageHTML = EntityUtils.toString(loginpage.getEntity(),"UTF-8");
        //JsoupとかでもTokenのみパースは無理ぽかったので、手動で検索‥
        Pattern p = Pattern.compile("(?is)value=\"(.+?)\""); 
        Matcher m = p.matcher(loginpageHTML);
        //トークンを探す。
        String[] TokenArray = new String[6];
    
        int i= 0;
        while (m.find()) {
            TokenArray[i]=m.group((1));
            i++;
        }
        //TokenArray[1]　TokenArray[5]
        //1はkey,5はfields. これをPOST送信に含めてみることにする。
    
        List<NameValuePair> params = new ArrayList<NameValuePair>();
        params.add(new BasicNameValuePair("data[_Token][key]",TokenArray[1]));
        params.add(new BasicNameValuePair("data[User][email]","自分のID"));
        params.add(new BasicNameValuePair("data[User][password]","自分のPASS"));
        params.add(new BasicNameValuePair("data[User][auto_login]","0"));
        params.add(new BasicNameValuePair("data[User][referer]","http://www.lancers.jp/"));
        params.add(new BasicNameValuePair("data[_Token][fields]",TokenArray[5]));
    
        post.setHeader("Connection", "keep-alive");
        post.setHeader("Referer", user);
        post.setHeader("Content-Type", "application/x-www-form-urlencoded");
    
        post.setEntity(new UrlEncodedFormEntity(params));
    
        String html="";
        CloseableHttpResponse response = client.execute(post);
    
        try{
        HttpEntity entity = response.getEntity();
        html=EntityUtils.toString(entity,"UTF-8");
        EntityUtils.consume(entity);
        }finally{
            response.close();
        }
    
        Document doc = Jsoup.parse(html);
        System.out.println(doc);
    
    
    }
    
[/code]

}


CC BY-SA 3.0
2015-06-19T03:08:45.633
11496
2015-07-22T02:01:54.373
10208
question
java
トークン方式にログインする方法とは？


ソースコードを確認しました。とりあえずは動いているようですね。  
こういうことをやるときはブラウザで一度ログインして、ブラウザの開発者モードからリクエストヘッダを眺めてみるといいです。ただ、サーバ側がAPIを提供しているわけではないと思うので、若干リバースエンジニアリングのようになってしまいます。サーバ側がそのようなAPIを公開しているWebサービスで練習したほうがよいのではないかと思います。あと、トークン方式という言葉は初めて聞いたのですが独自用語でしょうか。

# ログインの流れ

さて、ログから、ログインの流れは以下のようにすればよいとわかります。

[code]

    1. POST  https://www.lancers.jp/user/login
    
       *** Formを送信してクッキーCakeCookie[User]をもらう ***
    
       [送信するForm]
       data[_Token][key]:トークン
       data[User][email]:メールアドレス
       data[User][password]:パスワード
       data[User][auto_login]:よくわからん値
       data[User][referer]:リファラ
       submit:ログインする　（送信ボタンの値：おそらく任意）
       data[_Token][fields]: URLエンコードされたトークン
    
       [送信するクッキー]
       CakeCookie[LANCERS_C]
       CakeCookie[CLIENT]
       CakeCookie[arcmnd]
    
       [受信できるクッキー]
       CakeCookie[User]
    
    2. GET   http://www.lancers.jp/mypage
    
       *** CakeCookie[Users]をリクエストヘッダに含めてGET、mypageの場所を取得 ***
    
       [受信できるヘッダ]
       Location:https://www.lancers.jp/mypage?[0-9]{10}&
    
    3. GET   https://www.lancers.jp/mypage?[0-9]{10}&
    
       *** HTTPSでmypageにログイン ***
    
[/code]

# 1. POST /user/login

## リクエスト概要

[code]

    Remote Address:52.68.161.170:443
    Request URL:https://www.lancers.jp/user/login
    Request Method:POST
    Status Code:302 Found
    
[/code]

## リクエストヘッダ

[code]

    Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
    Accept-Encoding:gzip, deflate
    Accept-Language:ja,en-US;q=0.8,en;q=0.6
    Cache-Control:max-age=0
    Connection:keep-alive
    Content-Length:{*** POSTするコンテンツの長さ ***}
    Content-Type:application/x-www-form-urlencoded
    Cookie: {*** クッキーいろいろ ***}
    Host:www.lancers.jp
    Origin:https://www.lancers.jp
    Referer:https://www.lancers.jp/user/login?{*** ユーザの固有ID(数字) ***}&
    User-Agent: {*** ここはなんでもいい ***}
    
[/code]

## フォーム値

[code]

    _method:POST
    data[_Token][key]:token_token_token_token_token...
    data[User][email]:nanashi_no_gonbei@example.com
    data[User][password]:this_is_password
    data[User][auto_login]:0  // ログ上は0とも1とも設定されていて
    data[User][auto_login]:1  // あまり意味のないものと思われる
    data[User][referer]:http://www.lancers.jp/
    submit:ログインする
    data[_Token][fields]: {*** URLエンコードされたトークン ***}
    
[/code]

## レスポンスヘッダ

[code]

    Connection:keep-alive
    Content-Length:0
    Content-Type:text/html; charset=UTF-8
    Date:Mon, 22 Jun 2015 01:02:31 GMT
    Location:http://www.lancers.jp/mypage
    P3P:CP="NOI ADM DEV PSAi COM NAV OUR OTRo STP IND DEM"
    Server:Apache
    Set-Cookie:CakeCookie[User]     
    Set-Cookie:CakeCookie[LANCERS_C]
    Set-Cookie:CakeCookie[CLIENT]   
    Set-Cookie:CakeCookie[arcmnd]   
    
[/code]

# 2. GET /mypage

mypageの実際の場所をもらう。ブラウザの場合Locationが含まれていれば自動でリダイレクトされる気がする。

## レスポンスヘッダ

[code]

    Location:https://www.lancers.jp/mypage?[0-9]{10}&
    
[/code]

# 3. GET /mypage?[0-9]{10}&

HTTPSでリクエスト、これにて完了


CC BY-SA 3.0
2015-06-22T02:00:13.640
11595
2015-06-22T02:00:13.640
8918
11496
answer