web-dev-qa-db-de.com

Fügen Sie Cookies hinzu, um die Anforderung 2 nachzurüsten

Ich muss Cookies mit Retrofit 2.0 hinzufügen. Wenn ich das richtig verstehe, sind Cookies - genauso wie Header. Diese Cookies müssen hinzugefügt werden:

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

dieses arbeiten mit Jsoup lib:

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

hier ist mein code mit nachrüstanforderung:

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

aber es funktioniert nicht ....... ich bekomme den Fehlercode 403, so dass keine Cookies in der Anfrage sind.

irgendeine Idee?

14
Stan Malcolm

Erstens: Cookie ist nicht dasselbe wie ein Header. Cookie ist ein spezieller HTTP-Header mit dem Namen Cookie , gefolgt von einer Liste der Schlüssel- und Wertepaare (durch ";" getrennt). So etwas wie:

Cookie: sessionid=sessionid; token=token

Da Sie nicht mehrere Cookie-Header in derselben Anfrage setzen können , können Sie nicht zwei @ Header Annotationen für separate Werte verwenden ( sessionid und token in Ihrer Stichprobe). Ich kann mir eine sehr hackige Problemumgehung vorstellen:

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

Sie ändern Ihre Methode, um SessionId und Token in einer Zeichenfolge zu senden. In diesem Fall sollten Sie die Cookie-Zeichenfolge also vorher manuell generieren. In Ihrem Fall sollte das sessionIdAndToken String-Objekt gleich "sessionid = here_goes_sessionid; token = here_goes_token" sein.

Die richtige Lösung ist das Setzen von Cookies durch Hinzufügen von OkHttp (that Diese Bibliothek wird von Retrofit verwendet, um zugrunde liegende http-Aufrufe anzufordern . Sie können die Lösung sehen oder benutzerdefinierte Header hier hinzufügen.

38

fügen Sie Folgendes in Interceptor hinzu, um Cookie-Header zu OKHTP-Anforderungsheadern hinzuzufügen:

request= request.newBuilder().addHeader("Cookie", sessionIdAndToken).build();

Ref: https://github.com/square/okhttp/wiki/Interceptors wie von @Alexander Mironov erwähnt

Vollständiger Beispielcode hier: Hoffe, es hilft dir

import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import Java.io.IOException;
import Java.util.List;


public class LoggingInterceptor implements Interceptor {

    private static final Logger logger = LoggerFactory.getLogger(LoggingInterceptor.class);
    @Override
    public Response intercept(Interceptor.Chain chain) throws IOException {
        Request request = chain.request();

        long t1 = System.nanoTime();
        request = processRequest(request);
        logger.info("Sending request with url:{} and connection status:{} and request headers:{}",
                request.url(), chain.connection(), request.headers());

        Response response = chain.proceed(request);
        long t2 = System.nanoTime();
        logger.info("Received response for url:{} and time taken:{} and response headers as:{}",
                response.request().url(), (t2 - t1) / 1e6d, response.headers());

        response = processResponse(response);
        return response;
    }
    //Add cookies for all subsequent requests
    private Request processRequest(Request request) {
        if(!request.url().toString().contains("/v1/authorize")) {
            final EmployeeSession session = getSession();
            StringBuilder etokenAndUId = new StringBuilder("etoken=");
            etokenAndUId.append(session.getEtoken()).append(";").append("uId=").append(session.getUId());
            logger.info("inside processRequest for all subsequent requests, sending cookies as etokenAndUId values:{}", etokenAndUId.toString());
            request= request.newBuilder().addHeader("Cookie", etokenAndUId.toString()).build();
        }
        return request;
    }

    //Extract cookies from login url
    private Response processResponse(Response response) {
        if(response.request().url().toString().contains("/v1/authorize")) {
            final List<String> cookieHeaders = response.headers("Set-Cookie");
            String etoken = "", uId = "";
            for (String cookieHeader : cookieHeaders) {
                if(cookieHeader.contains("etoken=")) {
                    etoken = cookieHeader.substring(7, cookieHeader.indexOf(';'));
                }
                else if(cookieHeader.contains("uId=")) {
                    uId = cookieHeader.substring(4, cookieHeader.indexOf(';'));
                }
            }
            logger.info("inside processResponse found cookies from login url response: etoken:{} and uid:{}", etoken, uId);
            setSession(etoken, uId, "c1");
            logger.info("current employee session:{}", getSession());
        }
        return response;
    }
 }    
2
Rajesh Mbm

Beispiel für einen API-Webdienst: Header hinzufügen 

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

wenn Sie sich beim System anmelden, speichern Sie Cookies in Ihrer lokalen Umgebung auf Response like

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

und in jedem Dienst müssen Sie autorisiert werden. Senden Sie Ihre Cookies, lassen Sie sich von sharepreference beraten und senden Sie sie mit Ihrem Webservice

  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

warum nicht die CookieJar-Option verwenden?

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