web-dev-qa-db-ja.com

Androidでのセッションの維持(アプリケーションはサーバー側で認証されたままです)

私はAndroidでログインアプリケーションを構築しています。ここで、(ユーザー名とパスワードで)URLにアクセスしています)その部分までは正常に動作しますが、その後URLにアクセスするたびに(ユーザーが認証済み)、何も返しません(つまり、最初にログインしてくださいなどのエラーメッセージ)。

私はどこかにそれがphpSessionIdのエラーである(すなわち、セッションはさらなる要求のために破棄されます)そして私たちがAndroidアプリケーションがサーバー側で認証されたままでいることを望むなら、私たちは後にそのIDをフェッチする必要があります最初の接続を作成し、それを後続のすべてのリクエストのヘッダーで送信します。

しかし、問題は、最初の接続のヘッダーからsessionIdを取得できず、ヘッダーと共に追加のリクエストで送信できないことです。

タスクを正しく完了するためのコードまたはリンクを教えてください。ありがとう。

32
Dinesh Sharma

最後に、Androidでのセッション処理の問題を解決しました。 Androidセッション自体を処理できないため(単純なブラウザーで可能)、明示的に処理する必要があります。 http接続のコードを少し変更しました。接続が確立されたときに、最初のアクティビティでDefaultHttpClientのインスタンスを作成しました。

public static DefaultHttpClient httpClient;

初めての接続で、次のことを行いました。

URL url=new URL(urlToHit);
LoginScreen.httpClient = new DefaultHttpClient(); //LoginScreen is the name of the current Activity

HttpPost httppost = new HttpPost(url.toString());
HttpResponse response = LoginScreen.httpClient.execute(httppost); 

xr.parse(new InputSource(url.openStream())); //SAX parsing

これで、すべての接続で同じhttpClientを使用しました。たとえば、次のアクティビティで:

URL url=new URL(urlToHit);

HttpPost httppost = new HttpPost(url.toString());
HttpResponse response = LoginScreen.httpClient.execute(httppost); 

// Log.v("response code",""+response.getStatusLine().getStatusCode());

// Get hold of the response entity
HttpEntity entity = response.getEntity();

InputStream instream = null;

if (entity != null) {
    instream = entity.getContent();
}
xr.parse(new InputSource(instream)); //SAX parsing

これがAndroidのセッションの問題の解決に役立つことを願っています。

48
Dinesh Sharma

最善のアイデアは、サーバーが実行するすべての関数を、接続したいタスクによって呼び出される一意のクラスに置くことです。このクラスをWebServiceManagerと呼びます。このクラスには、サーバーとまったく同じメソッドがあります。

あなたがユニークなセッションをしたいので:

private static WebServiceManager wsm = null;

public static WebServiceManager getInstance() {
    if (wsm == null) {
        wsm = new WebServiceManager();
    }
    return wsm;
}

private final HttpClient httpClient;

private WebServiceManager() {
    httpClient=new DefaultHttpClient();
}

次に、webServiceManagerのインスタンスのメソッドを呼び出して、常に同じセッションを使用します。 :)

3
Eliott Roynette

coderwall についてしばらく前に投稿しましたが、そのようなシナリオに最適な HttpRequestInterceptor および HttpResponseInterceptor クラスを使用しています。

次に例を示します。

public class HTTPClients {

private static DefaultHttpClient _defaultClient;
private static String session_id;
private static HTTPClients _me;
private HTTPClients() {

}
public static DefaultHttpClient getDefaultHttpClient(){
    if ( _defaultClient == null ) {
        _defaultClient = new DefaultHttpClient();
        _me = new HTTPClients();
        _defaultClient.addResponseInterceptor(_me.new SessionKeeper());
        _defaultClient.addRequestInterceptor(_me.new SessionAdder());
    }
    return _defaultClient;
}

private class SessionAdder implements HttpRequestInterceptor {

    @Override
    public void process(HttpRequest request, HttpContext context)
            throws HttpException, IOException {
        if ( session_id != null ) {
            request.setHeader("Cookie", session_id);
        }
    }

}

private class SessionKeeper implements HttpResponseInterceptor {

    @Override
    public void process(HttpResponse response, HttpContext context)
            throws HttpException, IOException {
        Header[] headers = response.getHeaders("Set-Cookie");
        if ( headers != null && headers.length == 1 ){
            session_id = headers[0].getValue();
        }
    }

}

}

1
Protostome

以下は、Volleyライブラリを使用した別の実装です... https://stackoverflow.com/a/36496607/3099185 からの非常に便利なヒント

    CustomRequest jsonObjReq = new CustomRequest(Request.Method.GET,
            url, null,  new Response.Listener<JSONObject>() {

        @Override
        public void onResponse(JSONObject response) {
                Log.d(TAG, response.toString());
        }
    }, new Response.ErrorListener(){

        @Override
        public void onErrorResponse(VolleyError error) {
            VolleyLog.d(TAG, "Error: " + error.getMessage());
            Toast.makeText(getApplicationContext(),
                    error.getMessage(), Toast.LENGTH_SHORT).show();
            // hide the progress dialog
        }
    });

カスタムリクエストクラス

import Android.util.Log;

import com.Android.volley.AuthFailureError;
import com.Android.volley.Response;
import com.Android.volley.toolbox.JsonObjectRequest;

import org.json.JSONObject;

import Java.util.HashMap;
import Java.util.Map;

public class CustomRequest extends JsonObjectRequest {
    private String session_id = "";

    public CustomRequest(int method, String url, JSONObject jsonRequest,
                                   Response.Listener listener, Response.ErrorListener errorListener) {
        super(method, url, jsonRequest, listener, errorListener);
    }

    public CustomRequest(int method, String url, JSONObject jsonRequest, String session_id,
                                   Response.Listener listener, Response.ErrorListener errorListener) {
        super(method, url, jsonRequest, listener, errorListener);
        this.session_id = session_id;
    }


    @Override
    public Map getHeaders() throws AuthFailureError {
        Map headers = new HashMap();
        Log.d(TAG, " -> session_id = " + session_id);
        if(!(session_id.equals(""))) {
            headers.put("Cookie", this.session_id);
        }
        return headers;
    }

}

シングルトンパターンを使用してボレーを実装する簡単な方法 http://arnab.ch/blog/2013/08/asynchronous-http-requests-in-Android-using-volley/

予期しないnullポインター例外を回避するために、onCreate()でmRequestQueueを初期化することを忘れないでください。

@Override
public void onCreate() {
    super.onCreate();

    // initialize the singleton
    sInstance = this;
        mRequestQueue = Volley.newRequestQueue(this);
}

このヘルプも願っています...! :)

1
Bhuro

私の問題は、最初にログインし、返されたセッションをuserpreferencesに保存することでした。その後、POST呼び出しでレコードを設定します

「エラー、ユーザーを認証できません」

だから私はpost.setHeader("oAuth-Token", UserPreferences.ACCESS_TOKEN);を追加しました。全体は次のようになります。

HttpPost post=new HttpPost(URL );  
post.setHeader("oAuth-Token", UserPreferences.ACCESS_TOKEN);    

。 。そしてそれは問題を解決しました。

1
Huzi