为什么我从 API 调用中得到加密数据?
Why am I getting encrypted data back from an API call?
我正在尝试使用以下代码登录 rest api,尽管 fiddler 可以解码响应,但 WebClient 并未对其进行解码。我正在使用 class 扩展我在 SO 上找到的 WebClient,它允许我访问响应。也在下面。
using (WebClientWithResponse client = new WebClientWithResponse())
{
client.Headers.Add("cache-control", "no-cache");
client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
client.Headers.Add("Authorization", basicAuth);
client.Headers.Add("Accept", "application/json, text/json, text/x-json, text/javascript, application/xml, text/xml");
client.Headers.Add("User-Agent", "MyAppName/21.1.1");
client.Headers.Add("Host", "login.company.com");
client.Headers.Add("Accept-Encoding", "gzip, deflate");
using (StreamWriter sw = new StreamWriter(client.OpenWrite("https://login.companyapi.com/services/oauth2/token", "POST")))
{
sw.Write(loginContent);
}
//string response = Encoding.UTF8.GetString(client.Response);
string response = Encoding.UTF8.GetString(Decompress(client.Response));
File.WriteAllText(".\response.txt", response);
Console.WriteLine(response);
}
public class WebClientWithResponse : WebClient
{
// we will store the response here. We could store it elsewhere if needed.
// This presumes the response is not a huge array...
public byte[] Response { get; private set; }
protected override WebResponse GetWebResponse(WebRequest request)
{
var response = base.GetWebResponse(request);
var httpResponse = response as HttpWebResponse;
if (httpResponse != null)
{
using (var stream = httpResponse.GetResponseStream())
{
using (var ms = new MemoryStream())
{
stream.CopyTo(ms);
Response = ms.ToArray();
}
}
}
return response;
}
}
下面您可以看到 Fiddler 显示的内容(在我单击解码按钮后)以及我在我的应用程序中收到的内容。
这是 Notepad++ 在加载保存的响应文件时的样子。
� ]�Ks�@�K8�!@Ъ�>P@M�B��H@��ݕ����
�C�9~��3��JA�T�0��!�+����{�gȟu��^r����1��(YtU+���H��4JWs��";d�E�[]�4��������9o�,� �G�Ǘ@��뺧=j��0
�IT��Jd�0E](R���.Ir����͒�V</؝�(2�Jߏ��!�1��q�S=U�4� �턔'�R����"ײmϱ��,rF�I���T�Lp����t�لM�3�:��(�[g�:�x��}}*��p
我以前从未遇到过这个问题,我也想不通为什么。
编辑:根据 Marc Gravell
的要求添加响应 headers
HTTP/1.1 200 OK
Date: Fri, 16 Apr 2021 19:33:23 GMT
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache,must-revalidate,max-age=0,no-store,private
Set-Cookie: BrowserId=m6jRGp7qEeuWJ50fQL0HHA; domain=.company.com; path=/; expires=Sat, 16-Apr-2022 19:33:23 GMT; Max-Age=31536000
Expires: Thu, 01 Jan 1970 00:00:00 GMT
X-ReadOnlyMode: false
Content-Type: application/json;charset=UTF-8
Vary: Accept-Encoding
Content-Length: 368
EDIT2:Marc Gravell 告诉我它没有被解压。事实证明这是正确的。我添加了这个函数 found 来解压缩响应。
public static byte[] Decompress(byte[] data)
{
using (var compressedStream = new MemoryStream(data))
using (var zipStream = new GZipStream(compressedStream, CompressionMode.Decompress))
using (var resultStream = new MemoryStream())
{
zipStream.CopyTo(resultStream);
return resultStream.ToArray();
}
}
看起来您正在连接的服务器应用了 gzip 压缩,但未能包含 Content-Encoding
响应 header(它们本应包含),因此客户端无法知道数据已压缩,但不会自动为您解压缩。老实说,您应该将此作为协议故障报告给服务器所有者,但现在:您可以使用 GZipStream
手动解压缩数据。请注意,如果他们解决了这个问题,您可能需要再次调整您的代码。
我正在尝试使用以下代码登录 rest api,尽管 fiddler 可以解码响应,但 WebClient 并未对其进行解码。我正在使用 class 扩展我在 SO 上找到的 WebClient,它允许我访问响应。也在下面。
using (WebClientWithResponse client = new WebClientWithResponse())
{
client.Headers.Add("cache-control", "no-cache");
client.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
client.Headers.Add("Authorization", basicAuth);
client.Headers.Add("Accept", "application/json, text/json, text/x-json, text/javascript, application/xml, text/xml");
client.Headers.Add("User-Agent", "MyAppName/21.1.1");
client.Headers.Add("Host", "login.company.com");
client.Headers.Add("Accept-Encoding", "gzip, deflate");
using (StreamWriter sw = new StreamWriter(client.OpenWrite("https://login.companyapi.com/services/oauth2/token", "POST")))
{
sw.Write(loginContent);
}
//string response = Encoding.UTF8.GetString(client.Response);
string response = Encoding.UTF8.GetString(Decompress(client.Response));
File.WriteAllText(".\response.txt", response);
Console.WriteLine(response);
}
public class WebClientWithResponse : WebClient
{
// we will store the response here. We could store it elsewhere if needed.
// This presumes the response is not a huge array...
public byte[] Response { get; private set; }
protected override WebResponse GetWebResponse(WebRequest request)
{
var response = base.GetWebResponse(request);
var httpResponse = response as HttpWebResponse;
if (httpResponse != null)
{
using (var stream = httpResponse.GetResponseStream())
{
using (var ms = new MemoryStream())
{
stream.CopyTo(ms);
Response = ms.ToArray();
}
}
}
return response;
}
}
下面您可以看到 Fiddler 显示的内容(在我单击解码按钮后)以及我在我的应用程序中收到的内容。
这是 Notepad++ 在加载保存的响应文件时的样子。
� ]�Ks�@�K8�
!@Ъ�>P@M�B��H@��ݕ����
�C�9~��3��JA�T�0��!�+����{�gȟu��^r����1��(YtU+���H��4JWs��";d�E�[]�4��������9o�,� �G�Ǘ@��뺧=j��0 �IT��Jd�0E](R���.Ir����͒�V</؝�(2�Jߏ��!�1��q�S=U�4� �턔'�R����"ײmϱ��,rF�I���T�Lp����t�لM�3�:��(�[g�:�x��}}*��p
我以前从未遇到过这个问题,我也想不通为什么。
编辑:根据 Marc Gravell
的要求添加响应 headersHTTP/1.1 200 OK
Date: Fri, 16 Apr 2021 19:33:23 GMT
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache,must-revalidate,max-age=0,no-store,private
Set-Cookie: BrowserId=m6jRGp7qEeuWJ50fQL0HHA; domain=.company.com; path=/; expires=Sat, 16-Apr-2022 19:33:23 GMT; Max-Age=31536000
Expires: Thu, 01 Jan 1970 00:00:00 GMT
X-ReadOnlyMode: false
Content-Type: application/json;charset=UTF-8
Vary: Accept-Encoding
Content-Length: 368
EDIT2:Marc Gravell 告诉我它没有被解压。事实证明这是正确的。我添加了这个函数 found
public static byte[] Decompress(byte[] data)
{
using (var compressedStream = new MemoryStream(data))
using (var zipStream = new GZipStream(compressedStream, CompressionMode.Decompress))
using (var resultStream = new MemoryStream())
{
zipStream.CopyTo(resultStream);
return resultStream.ToArray();
}
}
看起来您正在连接的服务器应用了 gzip 压缩,但未能包含 Content-Encoding
响应 header(它们本应包含),因此客户端无法知道数据已压缩,但不会自动为您解压缩。老实说,您应该将此作为协议故障报告给服务器所有者,但现在:您可以使用 GZipStream
手动解压缩数据。请注意,如果他们解决了这个问题,您可能需要再次调整您的代码。