web-dev-qa-db-fra.com

Maintenir la session en Android (l'application reste authentifiée côté serveur)

Je crée une application de connexion dans Android dans laquelle je frappe une URL (avec nom d'utilisateur et mot de passe) jusqu'à cette partie, cela fonctionne bien, mais après cela, chaque fois que je frappe une URL (une fois que l'utilisateur est authentifié), il ne renvoie rien (c.-à-d. un message d'erreur comme s'il vous plaît connectez-vous d'abord) .Cependant, cela fonctionne très bien dans l'application iphone très similaire et sur le navigateur.

Je suis arrivé quelque part que c'est l'erreur de phpSessionId (c'est-à-dire que la session est détruite pour une demande supplémentaire) et si nous voulons que notre application Android reste authentifiée côté serveur, nous devons récupérer cet identifiant après la première connexion, puis l'envoyer dans les en-têtes de toutes nos demandes ultérieures.

Mais le problème est que je ne peux pas obtenir le sessionId de l'en-tête de la première connexion et l'envoyer avec une demande supplémentaire avec l'en-tête.

Veuillez me donner quelques codes ou liens pour terminer la tâche correctement. Merci.

32
Dinesh Sharma

Enfin, j'ai résolu le problème de gestion des sessions sous Android. Android ne peut pas gérer la session elle-même (qu'un simple navigateur peut) donc nous devons la gérer explicitement. J'ai changé un peu le code pour la connexion http. J'ai créé une instance de DefaultHttpClient dans la première activité lorsque la connexion est établie.

public static DefaultHttpClient httpClient;

Pour la première connexion, j'ai fait ce qui suit:

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

Maintenant, pour toutes les autres connexions, j'ai utilisé la même chose httpClient Par exemple dans l'activité suivante:

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

J'espère que cela vous aidera aussi à résoudre problème de session dans Android.

48
Dinesh Sharma

La meilleure idée est de mettre toutes les fonctions de votre serveur sur une classe unique qui va être appelée par les tâches qui veulent se connecter. J'appelle cette classe WebServiceManager. Cette classe a exactement la même méthode que le serveur.

Comme vous voulez une session unique, faites:

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();
}

puis vous appelez la méthode de votre instance de webServiceManager pour utiliser toujours la même session. :)

3
Eliott Roynette

J'ai écrit un article à ce sujet il y a quelque temps sur coderwall Il utilise les classes HttpRequestInterceptor et HttpResponseInterceptor qui sont parfaites pour ce type de scénario.

Voici un exemple:

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

Voici une autre implémentation utilisant la bibliothèque Volley ... un conseil très utile de 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
        }
    });

Classe de demande personnalisée

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;
    }

}

Un moyen simple d'implémenter la volée en utilisant le modèle singleton http://arnab.ch/blog/2013/08/asynchronous-http-requests-in-Android-using-volley/

N'oubliez pas d'initialiser mRequestQueue dans onCreate () pour éviter une exception de pointeur null inattendue

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

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

J'espère que cette aide aussi ...! :)

1
Bhuro

Mon problème était que je me connectais d'abord et enregistrais la session retournée dans userpreferences. Après cela, l'appel POST pour établir un enregistrement dit

"Erreur, impossible d'authentifier l'utilisateur"

J'ai donc ajouté post.setHeader("oAuth-Token", UserPreferences.ACCESS_TOKEN); le tout ressemble à ceci.

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

. . et Il a résolu le problème.

1
Huzi