3

良い一日!

私のアプリは、クライアント側の Volley ライブラリで確立された単純な http クライアント サーバー通信を使用します。まず、承認リクエストを起動します。

public class AuthenticationRequest extends StringRequest {

    private static final String TAG = AuthenticationRequest.class.getSimpleName();

    private String login;
    private String password;

    public AuthenticationRequest(int method,
                                 String url,
                                 Response.Listener<String> listener,
                                 Response.ErrorListener errorListener) {
        super(method, url, listener, errorListener);
    }

    public void setLogin(String login) {
        this.login = login;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    protected Map<String, String> getParams() {
        HashMap<String, String> parameters = new HashMap<>();
        parameters.put("login", login);
        parameters.put("password", password);
        return parameters;
    }

    @Override
    protected Response<String> parseNetworkResponse(NetworkResponse response) {
        for (Map.Entry<String, String> entry : response.headers.entrySet()) {
            Log.d(TAG, entry.getKey() + " -- " + entry.getValue());
        }

        String sessionId = response.headers.get("Set-Cookie");
        return Response.success(sessionId, HttpHeaderParser.parseCacheHeaders(response));
    }
}

その直後に、現在のユーザーに関連付けられているデバイスのリストを要求します。現時点では、応答ヘッダーからのクッキーがあります。認証リクエストの完全なヘッダー応答出力:

  • キャッシュ制御 -- ストアなし、キャッシュなし、再検証が必要、チェック後 = 0、チェック前 = 0
  • 接続 -- キープアライブ
  • コンテンツの長さ -- 16
  • コンテンツ タイプ -- text/html; 文字セット=utf-8
  • 日付 -- 2015 年 9 月 18 日金曜日 06:15:57 GMT
  • 有効期限 -- 1981 年 11 月 19 日(木)08:52:00 GMT
  • プラグマ -- キャッシュなし
  • サーバー -- nginx
  • セット Cookie -- PHPSESSID=osurmkq1fmnj462c3hk76l1405; パス=/
  • X-Android-Received-Millis -- 1442553247146
  • X-Android-Sent-Millis -- 1442553247096
  • X-Powered-By -- PHP/5.3.27

Auth リクエストの onResponce コールバックで、Set-Cookie 値を sessionId として取得し、DeviceListRequest を起動します。

public class DeviceListRequest extends StringRequest {

    private static final String TAG = DeviceListRequest.class.getSimpleName();

    private String phpSessId;

    public DeviceListRequest(int method,
                             String url,
                             Response.Listener<String> listener,
                             Response.ErrorListener errorListener) {
        super(method, url, listener, errorListener);
    }

    public void setPhpSessId(String phpSessId) {
        this.phpSessId = phpSessId;
    }

    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        HashMap<String, String> headers = new HashMap<>();
        Log.d(TAG, phpSessId);
        headers.put("Cookie", phpSessId);
        return headers;
    }
}

ここで、sessionId をデバイス リスト リクエストのヘッダーに追加しましたが、応答として {"status":false,"error":"No authorization"} が表示されます。

デスクトップ PC の Chrome ブラウザで、期待どおりにデバイスのリストを受け取ります - 問題は Android にあります。

教えてください、私のコードの問題は何ですか? たぶん、ヘッダーの設定が間違っていますか???

リクエスト送信手順のコード:

public void authenticationRequest(String login, String password) {
        final AuthenticationRequest request = new AuthenticationRequest(Request.Method.GET,
                AUTHENTICATION_URL,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        Log.d(TAG, "Response: " + response);
                        phpSessId = response;
                        deviceListRequest(phpSessId);
                    }
                },
                this);

        request.setLogin(login);
        request.setPassword(password);

        requestQueue.add(request);
    }

    public void deviceListRequest(String phpSessId) {
        DeviceListRequest request = new DeviceListRequest(Request.Method.GET,
                DEVICE_LIST_URL,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        Log.d(TAG, "Response: " + response);
                    }
                },
                this);

        request.setPhpSessId(phpSessId);

        requestQueue.add(request);
    }
4

2 に答える 2

5

Android < 2.3 との互換性が必要ない場合は、アクティビティまたはアプリケーションの onCreate にこのコード行を追加するだけです。これにより、すべての httpURL 接続に対してデフォルトの cookieManager がアクティブになります。

CookieHandler.setDefault(new CookieManager());

この助けを願っています。

下位互換性がさらに必要な場合は、HttpClient にも Cookie 管理が必要です

編集:この後者の場合、この回答に従ってカスタム HttpClientStack を渡します: https://stackoverflow.com/a/21271347

于 2015-09-18T13:42:47.073 に答える
1

私が遭遇した Volley ヘッダー操作にも問題があります。Volley に含まれている HurlStack のソース コードを確認します。

Volley 内のヘッダーは Map 内に配置され、場合によっては (理由はまだわかりません)、Volley は同じキー (あなたの場合は Set-Cookie) のヘッダーを 1 つずつ収集します (最初はこの PHPSESSION になり、次に取得されますSet-Cookie のこのパス部分)。これはマップであるため、最初のものが上書きされ、必要なものが得られません。

私の提案は、HurlStack のソース コードを変更して、これらのヘッダーをリストまたは別のキー (Set-Cookie1、Set-Cookie2、..) で取得することです。

RetroFit も見てください。これは非常にうまく処理されます。唯一のことは、RetroFit ではリクエストをキャンセルする可能性がないことです。

お役に立てれば。

于 2015-09-18T14:12:22.153 に答える