1. 应用场景
防止前端直接调用某些隐私接口造成数据泄露,可以采用后端调用接口的方式,这样避免前端传参导致的数据泄露问题。
2. 解决方案
使用类HttpWebRequest
,核心代码如下:
/// <summary>
/// 接口请求
/// </summary>
/// <param name="url">请求地址</param>
/// <returns></returns>
public static string GetToken(string url)
{
string result = "";//返回结果
HttpWebRequest request = null;
HttpWebResponse response = null;
Stream reqStream = null;
try
{
request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.ReadWriteTimeout = 5000;
//System.Net.WebProxy wp = new System.Net.WebProxy("127.0.0.1:5555", true);// 调试模式下,用于postman拦截测试参数问题
//request.Proxy = wp;
request.ProtocolVersion = HttpVersion.Version10;
request.KeepAlive = false;
request.ContentType = "application/x-www-form-urlencoded;charset=utf-8";
request.ServicePoint.Expect100Continue = false;
//添加Authorization到HTTP头
request.Headers.Add("Authorization", "Basic ****************");
Dictionary<string, string> parameters = new Dictionary<string, string>(); //参数列表
parameters.Add("paraName", "paraValue");
byte[] data = Encoding.UTF8.GetBytes(BuildQuery(parameters, "utf8")); //使用utf-8格式组装post参数
request.ContentLength = data.Length;
reqStream = request.GetRequestStream();
reqStream.Write(data, 0, data.Length);
reqStream.Close();
//获取服务端返回
response = (HttpWebResponse)request.GetResponse();
StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
result = sr.ReadToEnd().Trim();
sr.Close();
}
catch (Exception e)
{
LogManager.DefaultLogger.Error(e);
}
finally
{
//关闭连接和流
if (response != null)
{
response.Close();
}
if (request != null)
{
request.Abort();
}
}
return result;
}
//组装请求参数
private string BuildQuery(IDictionary<string, string> parameters, string encode)
{
StringBuilder postData = new StringBuilder();
bool hasParam = false;
IEnumerator<KeyValuePair<string, string>> dem = parameters.GetEnumerator();
while (dem.MoveNext())
{
string name = dem.Current.Key;
string value = dem.Current.Value;
// 忽略参数名或参数值为空的参数
if (!string.IsNullOrEmpty(name))
{
if (hasParam)
{
postData.Append("&");
}
postData.Append(name);
postData.Append("=");
if (encode == "gb2312")
{
postData.Append(HttpUtility.UrlEncode(value, Encoding.GetEncoding("gb2312")));
}
else if (encode == "utf8")
{
postData.Append(HttpUtility.UrlEncode(value, Encoding.UTF8));
}
else
{
postData.Append(value);
}
hasParam = true;
}
}
return postData.ToString();
}
3. 问题汇总
3.1 传参问题
接口请求时总是无法返回正确结果,使用同样的参数在Postman中返回结果正常,通过[设置代理](#3.2 设置代理)进行请求拦截,发现应该时参数传递时出现问题,应该进行encode
。参数处理参考如下代码:
Dictionary<string, string> parameters = new Dictionary<string, string>(); //参数列表
parameters.Add("paraName", "paraValue");
byte[] data = Encoding.UTF8.GetBytes(BuildQuery(parameters, "utf8")); //使用utf-8格式组装
request.ContentLength = data.Length;
reqStream = request.GetRequestStream();
reqStream.Write(data, 0, data.Length);
reqStream.Close();
//获取服务端返回
response = (HttpWebResponse)request.GetResponse();
//组装请求参数
private string BuildQuery(IDictionary<string, string> parameters, string encode)
{
StringBuilder postData = new StringBuilder();
bool hasParam = false;
IEnumerator<KeyValuePair<string, string>> dem = parameters.GetEnumerator();
while (dem.MoveNext())
{
string name = dem.Current.Key;
string value = dem.Current.Value;
// 忽略参数名或参数值为空的参数
if (!string.IsNullOrEmpty(name))
{
if (hasParam)
{
postData.Append("&");
}
postData.Append(name);
postData.Append("=");
if (encode == "gb2312")
{
postData.Append(HttpUtility.UrlEncode(value, Encoding.GetEncoding("gb2312")));
}
else if (encode == "utf8")
{
postData.Append(HttpUtility.UrlEncode(value, Encoding.UTF8));
}
else
{
postData.Append(value);
}
hasParam = true;
}
}
return postData.ToString();
}
3.2 设置代理
当我们想要查看接口请求的详细内容时,包括请求头与参数等,可以配合Postman设置代理,进行接口请求拦截。共两个步骤: