2016-04-27 162 views
0

我正在编写Xamarin跨平台移动应用程序。服务器是一个SpringMVC服务器,它使用JWT令牌对每个端点/ Web服务进行身份验证。所以基本上,当我第一次向webservice发出请求时,在我需要点击/authorize POST端点发送我的电子邮件和密码之前,端点响应将在"Cookie"标头中包含标识为"AUTH_TOKEN={MD5-String}"的authenticaton标记。一旦我得到令牌,我就会将请求发送给端点,比如说/feed。但我的问题是,我无法弄清楚在C#HttpClient中设置“Cookie”标头的方式。我尝试了一切,但是endpoing只是继续响应登录屏幕html而不是实际的JSON响应。我在Postman和其他REST客户端尝试了相同的步骤,它工作。所以这意味着我做错了什么。这里是我的代码:来自C#HttpClient的针对Spring服务器JWT令牌的身份验证

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

当我到达行var content = await response.Content.ReadAsStringAsync();的响应是一个HTML字符串,而不是实际的JSON响应。

我尝试了其他几个关键值的标题,虽然"Cookie"是一个邮政工作的人。

我试过"Set-Cookie","set-cookie","Set-Cookie",设置标题为"AUTH_TOKEN"。我在不同的地方尝试了所有这些试验,例如在cookieCookieContainerhandlerCookieContainerclient.DefaultRequestHeaders中添加它们。

我试着打开和关闭handler.UseCookies = true; //Otherwise It'll not use the cookies container!!行。

任何帮助将受到欢迎!

UPDATE

我试着用建议的解决方案之一,但没有工作,我想无论是在真假UseCookies。

  //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

我试图用另一种解决方案,同样的结果。

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

是否有替代品HttpClient

+1

的可能的复制[如何在HttpClient的HttpRequestMessage上设置cookie(ht tp://stackoverflow.com/questions/12373738/how-do-i-set-a-cookie-on-httpclients-httprequestmessage) – SushiHangover

+0

尝试:http://stackoverflow.com/a/13287224/4984832 – SushiHangover

+0

@SushiHangover请参阅我更新的问题。我尝试了这个解决方案并没有工作,我会尝试使用另一个解决方案,看看它是否可以工作... – 4gus71n

回答

0

我终于可以设置Cookie头参数,但我通过HttpWebRequest

改变HttpClient获取饼干

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

设置饼干

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); 
相关问题