web-dev-qa-db-fra.com

Ajout de cookies pour la mise à niveau 2 de la demande

Je dois ajouter des cookies avec Retrofit 2.0. Si je comprends bien, les cookies - les mêmes que les en-têtes. ces cookies doivent être ajoutés:

private HashMap<String, String> cookies = new HashMap();
cookies.put("sessionid", "sessionId");
cookies.put("token", "token");

celui-ci fonctionne avec Jsoup lib:

String json = Jsoup.connect(apiURL + "/link")
                    .cookies(cookies)
                    .ignoreHttpErrors(true)
                    .ignoreContentType(true)
                    .execute()
                    .body();

voici mon code avec demande de modification:

@GET("link")
Call<CbGet> getData(@Header("sessionid") String sessionId, @Header("token") String token);

mais cela ne fonctionne pas .... je reçois le code d'erreur 403, il n'y a donc pas de cookies dans la requête ...

une idée?

14
Stan Malcolm

Tout d'abord: le cookie n'est pas la même chose qu'un en-tête. Cookie est un en-tête HTTP spécial nommé Cookie suivi de la liste des paires de clés et de valeurs (séparées par ";"). Quelque chose comme:

Cookie: sessionid=sessionid; token=token

Puisque vous ne pouvez pas définir plusieurs en-têtes de cookie dans la même demande vous ne pouvez pas utiliser deux annotations @Header pour des valeurs distinctes (ID de session _ et jeton dans votre échantillon). Je peux penser à une solution de contournement très hacky:

@GET("link")
Call<CbGet> getData(@Header("Cookie") String sessionIdAndToken);

Vous modifiez votre méthode pour envoyer sessionId et le jeton dans une chaîne. Donc, dans ce cas, vous devez générer manuellement une chaîne de cookie au préalable. Dans votre cas, l'objet sessionIdAndToken String devrait être égal à "sessionid = here_goes_sessionid} _; token = here_goes_token"

La solution appropriée consiste à définir des cookies en ajoutant les propriétés de OkHttp (c'est-à-dire que Library Retrofit utilise pour passer des appels http sous-jacents) request interceptor . Vous pouvez voir la solution ou ajouter des en-têtes personnalisés ici .

35
Alexander Mironov

Exemple de service Web API: ajout d'en-tête 

@FormUrlEncoded
@POST("getDriverRoutes")
Call<Guzergah> getGuzergah(@Header("Cookie") String userCookie, @Field("driver_id") int driver_id);

lorsque vous vous connectez au système, sauvegardez les cookies dans votre section locale sur Response, comme

 public void onResponse(Response<Login> response, Retrofit retrofit) {
            hidepDialog();
            String cookie = response.headers().get("Set-Cookie");
            editor.putString("user_cookie", cookie.split(";")[0]);
            editor.commit();

et dans chaque service, vous devez être autorisé à envoyer vos cookies, accédez à sharepreference et envoyez-le avec votre service Web.

  String userCookie = shp.getString("user_cookie", ""); // here is cookies before send
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl("http://server.aracadabra.com:8080/").
                    addConverterFactory(GsonConverterFactory.create())
            .build();

    final APIService service = retrofit.create(APIService.class);

    final Call<SenMsgStatus> loginMCall = service.sendMessage(userCookie, type, route_id, user_id, passenger_id, passenger_status, text);
1
Sam

pourquoi ne pas utiliser l'option cookieJar?

new Retrofit.Builder()
    .baseUrl(BASE_URL)
    .client(
        new OkHttpClient().newBuilder()
            .cookieJar(new SessionCookieJar()).build())
    .build();

private static class SessionCookieJar implements CookieJar {

    private List<Cookie> cookies;

    @Override
    public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
        if (url.encodedPath().endsWith("login")) {
            this.cookies = new ArrayList<>(cookies);
        }
    }


    @Override
    public List<Cookie> loadForRequest(HttpUrl url) {
        if (!url.encodedPath().endsWith("login") && cookies != null) {
            return cookies;
        }
        return Collections.emptyList();
    }
}
0
Markus Schulz