Ведение сессии в Android (приложение остается аутентифицированным на стороне сервера) - PullRequest
32 голосов
/ 11 мая 2011

Я создаю приложение для входа в Android, в котором я нажимаю URL (с именем пользователя и паролем) до этой части, она работает нормально, но после этого всякий раз, когда я нажимаю URL (после аутентификации пользователя), он ничего не возвращает (то есть сообщение об ошибке, например, сначала войдите в систему). Однако он отлично работает в очень похожих приложениях для iphone и в браузере.

Я где-то понял, что это ошибка phpSessionId (то есть сеанс уничтожен для дальнейшего запроса), и если мы хотим, чтобы наше приложение Android оставалось аутентифицированным на стороне сервера, нам нужно получить этот идентификатор после первого подключения и затем отправить это в заголовках всех наших последующих запросов.

Но проблема в том, что я не могу получить sessionId из заголовка первого соединения и отправить его с дополнительным запросом вместе с заголовком.

Пожалуйста, дайте мне несколько кодов или ссылок, чтобы правильно выполнить задачу. Благодарю.

Ответы [ 5 ]

48 голосов
/ 19 мая 2011

Наконец-то я решил проблему обработки сессии в 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 .

3 голосов
/ 22 апреля 2014

Лучшая идея - поместить все функции, которые выполняет ваш сервер, в уникальный класс, который будет вызываться задачами, которые хотят подключиться. Я называю этот класс 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 для использования всегда одного и того же сеанса. :)

1 голос
/ 20 июля 2016

Вот еще одна реализация, использующая библиотеку 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/

Не забудьте инициализировать mRequestQueue в onCreate (), чтобы избежать непредвиденного исключения нулевого указателя

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

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

Надеюсь, эта помощь тоже ...!:)

1 голос
/ 02 мая 2015

Я писал об этом некоторое время назад на 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 голос
/ 25 ноября 2013

Моя проблема заключалась в том, что я вошел первым и сохранил возвращенный сеанс в настройках пользователя.После этого POST-вызов для установки записи сказал

«Ошибка, не удается аутентифицировать пользователя»

Поэтому я добавил post.setHeader("oAuth-Token", UserPreferences.ACCESS_TOKEN);, все выглядит так:

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

.,И это решило проблему.

...