Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/264.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用.NET命令行应用程序发出的签名Google Maps API地理编码请求_C#_.net_Google Maps_Google Maps Api 3_Geocoding - Fatal编程技术网

C# 使用.NET命令行应用程序发出的签名Google Maps API地理编码请求

C# 使用.NET命令行应用程序发出的签名Google Maps API地理编码请求,c#,.net,google-maps,google-maps-api-3,geocoding,C#,.net,Google Maps,Google Maps Api 3,Geocoding,因此,我正在编写一个应用程序,在导入记录时缓存地理编码数据。当我使用未签名的请求时,它工作正常,但是当我尝试使用公司的clientid和签名时,我似乎无法找出问题所在。我总是得到403分 以下是我的URL生成器: private const string _googleUri = "http://maps.googleapis.com/maps/api/geocode/xml?address="; private const string _googleClientId = "X

因此,我正在编写一个应用程序,在导入记录时缓存地理编码数据。当我使用未签名的请求时,它工作正常,但是当我尝试使用公司的clientid和签名时,我似乎无法找出问题所在。我总是得到403分

以下是我的URL生成器:

    private const string _googleUri = "http://maps.googleapis.com/maps/api/geocode/xml?address=";
    private const string _googleClientId = "XXXXXXXX";
    private const string _googleSignature = "XXXXXXXXXXXXXXXXXXXXXXXX";

//RESOLVED
    private static String GetGeocodeUri(string address)
    {
        ASCIIEncoding encoding = new ASCIIEncoding();
        string url = String.Format("{0}{1}&client={2}&sensor=false"
                                   , _googleUri
                                   , HttpUtility.UrlEncode(address)
                                   , _googleClientId);

        // converting key to bytes will throw an exception, need to replace '-' and '_' characters first.
        string usablePrivateKey = _googleSignature.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;

    } 
节目如下:

public static AddressClass GetResponseAddress(string address)
    {
        AddressClass GoogleAddress = new AddressClass();
        XmlDocument doc = new XmlDocument();
        String myUri = GetGeocodeUri(address);

        try
        {
            doc.Load(myUri);
            XmlNode root = doc.DocumentElement;
            if (root.SelectSingleNode("/GeocodeResponse/status").InnerText == "OK")
            {
                GoogleAddress.Latitude = Double.Parse(root.SelectSingleNode("/GeocodeResponse/result/geometry/location/lat").InnerText);
                GoogleAddress.Longitude = Double.Parse(root.SelectSingleNode("/GeocodeResponse/result/geometry/location/lat").InnerText);

            }
         }
         catch (Exception ex)
         {
            Console.WriteLine("Exception <" + ex.Message + ">");

         }           

        return GoogleAddress;
    }
公共静态地址类GetResponseAddress(字符串地址)
{
AddressClass GoogleAddress=新的AddressClass();
XmlDocument doc=新的XmlDocument();
字符串myUri=GetGeocodeUri(地址);
尝试
{
文档加载(myUri);
XmlNode root=doc.DocumentElement;
if(root.SelectSingleNode(“/GeocodeResponse/status”).InnerText==“OK”)
{
GoogleAddress.Latitude=Double.Parse(root.SelectSingleNode(“/GeocodeResponse/result/geometry/location/lat”).InnerText);
GoogleAddress.Longitude=Double.Parse(root.SelectSingleNode(“/GeocodeResponse/result/geometry/location/lat”).InnerText);
}
}
捕获(例外情况除外)
{
控制台写入线(“例外”);
}           
返回地址;
}
现在,我对它不起作用的最初反应是,谷歌肯定错过了referer域,因为它们必须注册。所以我尝试了HttpWebRequest,并将referer设置为我的域,但仍然没有骰子

//Not needed, Just an alternate method
public static AddressClass GetResponseAddress(string address)
    {
        AddressClass GoogleAddress = new AddressClass();
        WebClient client = new WebClient();
        XmlDocument doc = new XmlDocument();
        Uri myUri = new Uri(GetGeocodeUri(address));
        HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(myUri);
        myRequest.Referer = "http://www.myDomain.com/";

        //I've even tried pretending to be Chrome
        //myRequest.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.75 Safari/535.7";

        try
        {
            doc.Load(myRequest.GetResponse().GetResponseStream());
            XmlNode root = doc.DocumentElement;
            if (root.SelectSingleNode("/GeocodeResponse/status").InnerText == "OK")
            {
                GoogleAddress.Latitude = Double.Parse(root.SelectSingleNode("/GeocodeResponse/result/geometry/location/lat").InnerText);
                GoogleAddress.Longitude = Double.Parse(root.SelectSingleNode("/GeocodeResponse/result/geometry/location/lat").InnerText);
            }
         }
         catch (Exception ex)
         {
              Console.WriteLine("Exception <" + ex.Message + ">");

         }

        return GoogleAddress;
    }
//不需要,只是一个替代方法
公共静态地址类GetResponseAddress(字符串地址)
{
AddressClass GoogleAddress=新的AddressClass();
WebClient客户端=新的WebClient();
XmlDocument doc=新的XmlDocument();
urimyuri=新Uri(GetGeocodeUri(地址));
HttpWebRequest myRequest=(HttpWebRequest)WebRequest.Create(myUri);
myRequest.Referer=”http://www.myDomain.com/";
//我甚至试着假装是Chrome
//myRequest.UserAgent=“Mozilla/5.0(Windows NT 6.1;WOW64)AppleWebKit/535.7(KHTML,比如Gecko)Chrome/16.0.912.75 Safari/535.7”;
尝试
{
doc.Load(myRequest.GetResponse().GetResponseStream());
XmlNode root=doc.DocumentElement;
if(root.SelectSingleNode(“/GeocodeResponse/status”).InnerText==“OK”)
{
GoogleAddress.Latitude=Double.Parse(root.SelectSingleNode(“/GeocodeResponse/result/geometry/location/lat”).InnerText);
GoogleAddress.Longitude=Double.Parse(root.SelectSingleNode(“/GeocodeResponse/result/geometry/location/lat”).InnerText);
}
}
捕获(例外情况除外)
{
控制台写入线(“例外”);
}
返回地址;
}

任何帮助都将不胜感激。

在将参数替换为查询字符串之前,您可能需要对参数进行正确的URL编码。如果您愿意导入System.Web程序集(而不使用客户端.NET配置文件),则可以使用,或者您可以包含或借用代码来执行此操作

address = HttpUtility.UrlEncode(address); // better than Replace(" ", "+");

return String.Format("{0}{1}&client={2}&sensor=false&signature={3}",
                 _googleUri, address,
                 HttpUtility.UrlEncode(_googleClientId),
                 HttpUtility.UrlEncode(_googleSignature));

我想他们会检查请求来自的Ip是否与签名注册的域匹配


您可以尝试从Web服务器发送请求吗?

URL编码有时是必要的(见下文),但还不够。你的问题是,事实上,你没有签署你的请求

您的
\u googleSignature
常量中的值不是签名,而是您的私钥,这是错误的。您的私有加密密钥本身不应成为任何请求的一部分

相反,您需要使用它为每个唯一的请求生成新的签名。请参阅文档,其中还包括以下示例:)

当使用您的Maps API for Business client id和您的私有加密密钥对Google Maps API Web服务的请求进行签名时,Referer标头和源IP地址完全不相关;)


URL编码仅在
address
参数上是必需的,作为的一部分。您不应该对签名进行URL编码,因为使用修改后的Base64作为URL已经是URL安全的。

我几乎可以肯定,这会违反相关api的服务条款。出现问题的原因是,它的设计目的不是在传统应用程序中仅作为web应用程序使用。不要忘记,除非你付钱给谷歌,否则没有交易限制。谷歌允许在报告大数据集之前进行缓存,只要操作正确。--(b)不预取、缓存或存储内容。您不得预取、缓存或存储任何内容,除非您可以存储:(i)为提高Maps API实现的性能而存储的内容数量有限,前提是您临时、安全且不允许在服务之外使用内容;和(ii)地图API文档特别允许您存储的任何内容标识符或密钥。@Ramhound还有,是的,不付费的查询限制为2500/天,如果付费的话,查询限制为100000/天。请用您当前的尝试更新您的问题。我在想,我只是希望让它独立于所使用的机器工作。谢谢,还没有机会实现它,但我想我错过了这样的东西。只是把它放进我的代码中,它就像一个符咒!谢谢为将来可能需要它的任何人发布上面的最终代码。这实际上是实现它的一个很好的例子,现在我已经修复了一个问题,其中密钥没有从谷歌的URLSafe编码中解码。这只是一个问题,如果您提供的密钥包含google更改为/或+的u或-。这使它们不再有效,因此在将其从Base64String传递到
之前,必须先撤消它。
const String gmeClientID = "gme-myClientId";
const String key = "myGoogleKey";

var urlRequest = String.Format("/maps/api/geocode/json?latlng={0},{1}&sensor=false&client={2}",Latitude,Longitude,gmeClientID);

HMACSHA1 myhmacsha1 = new HMACSHA1();
myhmacsha1.Key = Convert.FromBase64String(key); 
var hash = myhmacsha1.ComputeHash(Encoding.ASCII.GetBytes(urlRequest));

var url = String.Format("http://maps.googleapis.com{0}&signature={1}", urlRequest, Convert.ToBase64String(hash).Replace("+", "-").Replace("/", "_"));

var request = (HttpWebRequest)HttpWebRequest.Create(url);