2016-04-27 6 views
0

Ich bin eine Xamarin Cross-Plattform-Mobile-App zu codieren. Der Server ist ein SpringMVC-Server, der JWT-Token zur Authentifizierung für jeden der Endpunkte/Webdienste verwendet. Also, im Grunde, wenn ich eine Anfrage an einen Webservice zum ersten Mal, bevor ich einen /authorize POST-Endpunkt treffen muss senden meine E-Mail-Adresse und Passwort, die Endpoint-Antwort wird in der "Cookie" Header ein Authenticaton Token, die als kommt. Sobald ich das Token bekommen habe, sende ich die Anfrage an den Endpunkt, sagen wir /feed. Aber mein Problem ist, dass ich nicht herausfinden kann, wie man den "Cookie" Header in C# HttpClient setzt. Ich habe alles versucht, aber die Endpoting reagiert nur mit dem Login-Bildschirm html anstatt der eigentlichen JSON-Antwort. Ich habe die gleichen Schritte in Postman und anderen REST-Clients versucht und es hat funktioniert. Es bedeutet also, dass ich etwas falsch mache. Hier ist mein Code:Authentifizierung von C# HttpClient gegen Spring Server JWT Tokens

public class RestService : IRestService 
{ 
    HttpClient client; 
    HttpClientHandler handler; 
    CookieContainer cookies; 
    string authToken; 

    public List<Feed> FeedItems { get; private set; } 

    public RestService() 
    { 
     cookies = new CookieContainer(); 
     handler = new HttpClientHandler(); 
     handler.UseCookies = true; //Otherwise It'll not use the cookies container!! 
     handler.CookieContainer = cookies; 
     client = new HttpClient(handler); 
     client.MaxResponseContentBufferSize = 256000; 
    } 

    public async Task<List<Role>> GetFeedDataAsync() 
    { 
     //Request credentials 
     //Credentials validation 
     var credentials = new HalliganCredential() 
     { 
      email = Constants.Username, 
      password = Constants.Password 
     }; 
     var jsonCredentials = JsonConvert.SerializeObject(credentials); 
     var jsonCredentialsContent = new StringContent(jsonCredentials, Encoding.UTF8, "application/json"); 
     var authorizeUri = new Uri(Constants.AuthorizeEndpoint); 
     var authorizeResponse = await client.PostAsync(authorizeUri, jsonCredentialsContent); 
     if (authorizeResponse.IsSuccessStatusCode) 
     { 
      //If authentication went OK 
      IEnumerable<Cookie> responseCookies = cookies.GetCookies(authorizeUri).Cast<Cookie>(); 
      foreach (Cookie cookie in responseCookies) 
      { 
       if (cookie.Name.Equals("AUTH-TOKEN")) 
       { 
        authToken = cookie.Value; 
       } 
      } 
     } 
     else 
     { 
      //Authentication failed throw error 
      throw new HttpRequestException("Authentication failed"); 
     } 


     FeedItems = new List<Feed>(); 

     //Making the GET request 
     var uri = new Uri(string.Format(Constants.FeedEnpoint, string.Empty)); 
     try 
     { 
      cookies.Add(uri, new Cookie("Cookie", string.Format("AUTH_TOKEN={0}", authToken))); 
      client.DefaultRequestHeaders.Add("Cookie", string.Format("AUTH_TOKEN={0}", authToken)); 
      handler.CookieContainer.Add(uri, new Cookie("Cookie", string.Format("AUTH_TOKEN={0}", authToken))); 

      var response = await client.GetAsync(uri); 
      response.EnsureSuccessStatusCode(); 
      //Credentials validation 
      if (response.IsSuccessStatusCode) 
      { 
       var content = await response.Content.ReadAsStringAsync(); 
       FeedItems = JsonConvert.DeserializeObject<List<Feed>>(content); 
      } 
     } 
     catch (Exception ex) 
     { 
      Debug.WriteLine(@"ERROR {0}", ex.Message); 
     } 


     return FeedItems; 
    } 
} 

Als ich die Leitung var content = await response.Content.ReadAsStringAsync(); die Antwort erreichen ist ein HTML-String anstelle der tatsächlichen JSON-Antwort.

Ich versuchte mit mehreren anderen Schlüsselwerte für den Header, obwohl "Cookie" derjenige ist, der auf Postman arbeitete.

Ich versuchte mit "Set-Cookie", "set-cookie", "Set-Cookie", die Überschrift als "AUTH_TOKEN" setzen. Ich habe all diese Convinces an verschiedenen Stellen ausprobiert, wie zum Beispiel in der cookieCookieContainer, in der handlerCookieContainer und in der client.DefaultRequestHeaders.

Ich habe versucht, die handler.UseCookies = true; //Otherwise It'll not use the cookies container!! Zeile ein- und auszuschalten.

Jede Hilfe ist willkommen!

UPDATE

Ich habe versucht, mit einem der vorgeschlagenen Lösungen, aber hat nicht funktioniert Ich habe versucht, entweder mit UseCookies in wahr und falsch.

  //Making the GET request 
     var baseAddress = new Uri("http://app.******.io"); 
     using (var handler = new HttpClientHandler { UseCookies = true }) 
     using (var client = new HttpClient(handler) { BaseAddress = baseAddress }) 
     { 
      var message = new HttpRequestMessage(HttpMethod.Get, "/api/v1/feed?api_key=sarasa"); 
      message.Headers.Add("Cookie", string.Format("AUTH_TOKEN={0}", authToken)); 
      message.Headers.Add("Cookie", string.Format("AUTH_TOKEN={0};", authToken)); 
      message.Headers.Add("Set-Cookie", string.Format("AUTH_TOKEN={0}", authToken)); 
      message.Headers.Add("AUTH_TOKEN", authToken); 
      var result = await client.SendAsync(message); 
      result.EnsureSuccessStatusCode(); 
      if (result.IsSuccessStatusCode) 
      { 
       var content = await result.Content.ReadAsStringAsync(); 
       FeedItems= JsonConvert.DeserializeObject<List<Feed>>(content); 
      } 
     } 
     return FeedItems; 

UPDATE

Ich habe versucht, mit der anderen Lösung gleichen Ergebnisse.

var baseAddress = new Uri("http://app.*****.io"); 
      var cookieContainer = new CookieContainer(); 
      using (var handler = new HttpClientHandler() { CookieContainer = cookieContainer }) 
      using (var client = new HttpClient(handler) { BaseAddress = baseAddress }) 
      { 
       cookieContainer.Add(baseAddress, new Cookie("Cookie", string.Format("AUTH_TOKEN={0}", authToken))); 
       cookieContainer.Add(baseAddress, new Cookie("Set-Cookie", string.Format("AUTH_TOKEN={0}", authToken))); 
       var result = client.GetAsync("/api/v1/roles?api_key=sarasa").Result; 
       result.EnsureSuccessStatusCode(); 
       if (result.IsSuccessStatusCode) 
       { 
        var content = await result.Content.ReadAsStringAsync(); 
        RolesItems = JsonConvert.DeserializeObject<List<Role>>(content); 
       } 
      } 

Gibt es eine Alternative zu HttpClient?

+1

Mögliche Duplikat von [ Wie setze ich einen Cookie auf HttpRequestMessage von HttpClient] (ht tp: //stackoverflow.com/questions/12373738/how-doi-i-set-a-cookie-on-httpclients-httprequestmessage) – SushiHangover

+0

Versuchen Sie: http://Stackoverflow.com/a/13287224/4984832 – SushiHangover

+0

@SushiHangover Siehe meine aktualisierte Frage.Ich habe diese Lösung ausprobiert und nicht funktioniert, ich werde es mit der anderen Lösung versuchen und sehen, ob es funktioniert ... – 4gus71n

Antwort

0

schließlich konnte ich den Cookie-Header-Parameter eingestellt, aber ich ändern HttpClient von HttpWebRequest

die Plätzchen bekommen

//Credentials validation 
      var credentials = new CompanyCredential() 
      { 
       Email = Constants.Username, 
       Password = Constants.Password 
      }; 
      var jsonCredentials = JsonConvert.SerializeObject(credentials); 
      var request = (HttpWebRequest) WebRequest.Create(new Uri(baseAddress, Constants.AuthorizeEndpoint)); 
      request.ContentType = "application/json"; 
      request.Method = "POST"; 
      var requestStream = request.GetRequestStreamAsync().Result; 
      var streamWriter = new StreamWriter(requestStream); 
      streamWriter.Write(jsonCredentials); 
      streamWriter.Flush(); 
      try 
      { 
       HttpWebResponse response = (HttpWebResponse) request.GetResponseAsync().Result; 
       if (response.StatusCode.Equals(HttpStatusCode.OK)) 
       { 
        authToken = response.Headers["Set-Cookie"]; 
        tokenExpireDate = DateTime.ParseExact(response.Headers["Expires"], "yyyy-MM-dd HH:mm:ss,fff", 
             System.Globalization.CultureInfo.InvariantCulture); 
       } 
       else 
       { 
        //Authentication failed throw error 
        throw new HttpRequestException("Authentication failed"); 
       } 
      } catch (Exception e) 
      { 
       Debug.WriteLine(string.Format("Warning: {0}", e.Message)); 
      } 

Einstellen der Plätzchen

var request = (HttpWebRequest)WebRequest.Create(new Uri(baseAddress, endpoint)); 
      SetHeaders(request); 
      if (string.IsNullOrEmpty(authToken)) 
      { 
       throw new AuthTokenNullException(); 
      } 
      request.Headers["Cookie"] = authToken; 
      request.Method = "GET"; 
      HttpWebResponse response = request.GetResponseAsync().Result as HttpWebResponse; 
      if (!response.StatusCode.Equals(HttpStatusCode.OK)) 
      { 
       throw new HttpRequestException(string.Format("Warning expected response as 200 and got {0}", Convert.ToString(response.StatusCode))); 
      } 
      var reader = new StreamReader(response.GetResponseStream()); 
      string stringResponse = reader.ReadToEnd(); 
      return JsonConvert.DeserializeObject<T>(stringResponse); 
Verwandte Themen