HTTP POST/GET クッキー認証によるWebサイトへのログイン (Android, Java)


今回はAndroid環境(Java)で、Webサイトへのクッキー認証ログイン処理を実装してみました。
以前C#によるWEBサイトへのログイン方法(ベーシック認証、クッキー認証)に記載した
.NET環境(C#)でのクッキー認証のAndroid版です。




例として、ニコニコ動画へログインするクライアントアプリを作成しました。
ログインに必要なパラメタは、ニコニコ動画ログインフォームのHTMLから、
next_url, mail, passwordであることがわかります。
(詳しくはC#によるWEBサイトへのログイン方法(ベーシック認証、クッキー認証)のエントリをご確認ください。)

HTTP POSTアクセスにより取得したCookieをGETアクセスで使用しているので、
マイページのHTMLが取得できます。

javaは始めたばかりですので、変な箇所があればコメントでお知らせください。

package com.loftkun;

import java.util.List;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.CookieStore;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.cookie.Cookie;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

public class http extends Activity {
	private CookieStore _cookieStore;
	private EditText editText1;
	
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    	
        editText1 = (EditText)findViewById(R.id.editText1);
        editText1.setHorizontallyScrolling(true);
        editText1.setVerticalScrollBarEnabled(true);
        editText1.setTextSize(12.0f);

        
        Button button1 = (Button)findViewById(R.id.button1);
        button1.setOnClickListener(new View.OnClickListener() {
			
			public void onClick(View v) {
				String url  = "";
				String mail = "your_mail_address@hoge.jp";//メールアドレス
				String pass = "your_password";//パスワード
				String result="";
				
				//ログイン
				url = "https://secure.nicovideo.jp/secure/login?site=nicolive";
				result = doPost(url, "next_url=&mail=" + mail + "&password=" + pass);
				System.out.println(result);
				
				//以降は取得したクッキーを使用したGETアクセスでOK
				//例として、マイページをHTTP GETアクセスで取得
				url = "http://www.nicovideo.jp/my";
				result = doGet(url);
				System.out.println(result);
				
				//EditTextに表示
				editText1 = (EditText)findViewById(R.id.editText1);
				editText1.setText(result);
			}
		});
    }
    
    //HTTP POST
    public String doPost( String url, String params )
    {
        try
        {            
            HttpPost method = new HttpPost( url );
            
            DefaultHttpClient client = new DefaultHttpClient();
            
            // POST データの設定
            StringEntity paramEntity = new StringEntity( params );
            paramEntity.setChunked( false );
            paramEntity.setContentType( "application/x-www-form-urlencoded" );
            
            method.setEntity( paramEntity );
            
            HttpResponse response = client.execute( method );
            int status = response.getStatusLine().getStatusCode();
            if ( status != HttpStatus.SC_OK )
            {
                throw new Exception( "" );
            }
            //クッキーを保持(GET時に使う)
            _cookieStore = client.getCookieStore();
            
            //クッキー内容の取得デモ(単にクッキーの中身をデバグ表示するだけ)
            {
	            List<Cookie> clist = _cookieStore.getCookies();
	            Cookie cookie = clist.get(0);
	            System.out.println("クッキー name value " + cookie.getName() + " " + cookie.getValue());
            }
            
            //POST結果を取得
            String html = EntityUtils.toString( response.getEntity(), "UTF-8" ); 
            return html;
        }
        catch ( Exception e )
        {
            return null;
        }
    }

    //HTTP GET
    public String doGet( String url )
    {
        try
        {
            HttpGet method = new HttpGet( url );

            DefaultHttpClient client = new DefaultHttpClient();
            //保持しておいたクッキーを設定
            client.setCookieStore(_cookieStore);

            // ヘッダを設定する
            method.setHeader( "Connection", "Keep-Alive" );
            
            HttpResponse response = client.execute( method );
            int status = response.getStatusLine().getStatusCode();
            if ( status != HttpStatus.SC_OK )
            {
                throw new Exception( "" );
            }
            
            //GET結果を取得
            String html = EntityUtils.toString( response.getEntity(), "UTF-8" ); 
            return html;
        }
        catch ( Exception e )
        {
            return null;
        }
    }
}

 

3件のコメント

  1. responseから得られるStatusCodeが認証失敗時にも200が返ってきてしまうのは仕様でしょうか?(返ってくるPOSTの結果は異なっているが、status codeが同じになってしまう。)また、POST先は記事に記載されているURLと同様の物を使わせていただいてます。
    ですので、現状認証の成功の分岐を得られた結果の文字列の違いから決定しています。

  2. ロフトくん

    >kawausoさん
    こんにちは。認証に失敗した場合は失敗バージョンのHTMLを
    受信(HTTPステータスとしては正常受信)しているためと思います。

    ご指摘のように、ログインできたかどうかの判定にはHTML内の解析が必要かなと思います。

    doPost()戻り値内に、
    ・”入力したメールアドレスまたはパスワードが間違っています”
    という記載があれば認証失敗と判定
    (これはニコニコの仕様(文言)が変わると判定できなくなる)
    または
    ・ニコニコTOPではなく、ログイン画面(ログインフォームの存在するHTML)であれば認証失敗と判定

    といった判定になるかと思います。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です