【问题标题】:403 forbidden. WebException was unhandled .NET403 禁止。 WebException 未处理 .NET
【发布时间】:2015-12-15 17:55:03
【问题描述】:

我编写了一个类来计算两个坐标之间的距离。但是一旦我运行该项目,它就会给出一个错误:

WebException 未处理。

System.Xml.dll 中出现“System.Net.WebException”类型的未处理异常

附加信息:远程服务器返回错误:(403) Forbidden。

我的代码是:

public Tuple<double, double> GetCoords(string Streetnumber, string Streetname, string Cityname, string Country)
{
    XmlDocument doc = new XmlDocument();
    string clientId = "///"; =
    string key = "//";
    string address = Streetnumber + "+" + Streetname + ",+" + Cityname + ",+" + Country;

    var urlRequest = "/maps/api/geocode/xml?address=" + address + "&client=" + clientId;
    System.Security.Cryptography.HMACSHA1 myhmacsha1 = new System.Security.Cryptography.HMACSHA1();
    myhmacsha1.Key = Convert.FromBase64String(key);
    var hash = myhmacsha1.ComputeHash(System.Text.Encoding.ASCII.GetBytes(urlRequest));
    string signature = Convert.ToBase64String(hash).Replace("+", "-").Replace("/", "_");
    WebRequest.DefaultWebProxy.Credentials = CredentialCache.DefaultNetworkCredentials;

    doc.Load("https://maps.googleapis.com/maps/api/geocode/xml?address=" + address + "&client=" + clientId + "&signature=" + signature);

    string longitude = doc.SelectSingleNode("//GeocodeResponse/result/geometry/location/lng").InnerText;
    double lng = LongitudePlace(longitude);
    string latitude = doc.SelectSingleNode("//GeocodeResponse/result/geometry/location/lat").InnerText;
    double lat = LatitudePlace(latitude);
    return Tuple.Create(lng, lat);
}

我还有一些其他的方法,但它们与这个问题无关。错误在:

doc.Load("https://maps.googleapis.com/maps/api/geocode/xml?address=" + address + "&client=" + clientId + "&signature=" + signature);

也许这很容易解决,但我尝试了很多东西。我的clientID 是正确的,如果我没记错的话,它也是 console.developer.google.com 上的密钥。

我尝试了“1600”、“Amphitheatre+Parkway”、“Mountain+View”、“CA”的测试地址。

如何解决错误?

【问题讨论】:

  • 可能是你的字符串构建。建议你使用 url encode 或类似的msdn.microsoft.com/en-us/library/…
  • 你把生成的字符串粘贴到浏览器了吗?
  • @RonBeyer 是的,我做到了,但没用。
  • 那么你生成字符串的方式有问题,和代码没有任何关系。我会查找 API 示例并找出您的请求字符串错误的地方。由于您收到 403,我将从密钥或您的客户端 ID 开始。
  • 您是否检查过 API 规范以确保您传递了正确的参数?当我仅使用地址测试 URL 时,它正常工作 (Try it)

标签: c# distance webrequest http-status-code-403


【解决方案1】:

您的签名似乎格式不正确。具体来说,它缺少 URL 的一部分。以下是使用 Google 提供的代码对 URL 进行签名的代码的编辑版本。代码可以找到here

代码

public Tuple<double, double> GetCoords(string streetNumber, string streetName, string cityName, string country)
{
    XmlDocument doc = new XmlDocument();
    string clientId = "gme-" + "///";
    string key = "//"; //Note this is NOT your API key, it's the Client Secret
    string address = streetNumber + "+" + streetName + ",+" + cityName + ",+" + country;

    WebRequest.DefaultWebProxy.Credentials = CredentialCache.DefaultNetworkCredentials;

    doc.Load(Sign("https://maps.googleapis.com/maps/api/geocode/xml?address=" + address + "&client=" + clientId, key));

    string longitude = doc.SelectSingleNode("//GeocodeResponse/result/geometry/location/lng").InnerText;
    double lng = LongitudePlace(longitude);
    string latitude = doc.SelectSingleNode("//GeocodeResponse/result/geometry/location/lat").InnerText;
    double lat = LatitudePlace(latitude);
    return Tuple.Create(lng, lat);
}

//From the Google
public static string Sign(string url, string keyString) 
{
    ASCIIEncoding encoding = new ASCIIEncoding();

    // converting key to bytes will throw an exception, need to replace '-' and '_' characters first.
    string usablePrivateKey = keyString.Replace("-", "+").Replace("_", "/");
    byte[] privateKeyBytes = Convert.FromBase64String(usablePrivateKey);

    Uri uri = new Uri(url);
    byte[] encodedPathAndQueryBytes = encoding.GetBytes(uri.LocalPath + uri.Query);

    // compute the hash
    HMACSHA1 algorithm = new HMACSHA1(privateKeyBytes);
    byte[] hash = algorithm.ComputeHash(encodedPathAndQueryBytes);

    // convert the bytes to string and make url-safe by replacing '+' and '/' characters
    string signature = Convert.ToBase64String(hash).Replace("+", "-").Replace("/", "_");

    // Add the signature to the existing URI.
    return uri.Scheme+"://"+uri.Host+uri.LocalPath + uri.Query +"&signature=" + signature;
}

【讨论】:

  • 仍然无法正常工作,在 doc.Load(Sign("maps.googleapis.com/maps/api/geocode/xml?address=" + address + "&client=" + clientId, key));
  • 您是否将gme- 放在您的客户ID 前?
  • @amura.csg 不,我的 clientid 以数字开头,以字母开头,以 .apps.googleusercontent.com 结尾
  • 当我测试一些代码时,我使用this 来查看我的签名是否正确。我注意到的一件事是,如果我从我的客户 ID 中留下 gme-,这将表明我的客户选项丢失了。您的 URL 应该类似于 https://maps.googleapis.com/maps/api/geocode/xml?address=&lt;address&gt;&amp;client=gme-numbers-stuff.apps.googleusercontent.com
  • 仍然无法正常工作.. 这很奇怪。第一次出现这样的问题,尝试修复后无法正常工作。
猜你喜欢
  • 2010-12-30
  • 1970-01-01
  • 2015-09-10
  • 1970-01-01
  • 2023-01-22
  • 1970-01-01
  • 1970-01-01
  • 2018-11-03
  • 2018-10-15
相关资源
最近更新 更多