【问题标题】:Unauthorized Access Exception While Using Yahoo Weather API使用 Yahoo Weather API 时出现未经授权的访问异常
【发布时间】:2019-06-11 07:17:59
【问题描述】:

我已经按照 yahoo 在文档中提供的所有步骤完成了使用 oath 访问 yahoo 天气 API 的代码: 1) 创建雅虎帐户 2) 创建应用 3) 白名单应用 4) 使用 oath 访问 yahoo 天气 API 的 C# 代码

我在请求 API 时遇到未经授权的访问异常。 这是代码:

public class WeatherYdn
{
    public static void Main(string[] args)
    {
        const string appId = "YOUR-WHITELISTED-APPID";
        const string consumerKey = "YOUR-CONSUMER-KEY";
        const string consumerSecret = "YOUR-SECRET-KEY";
        const string url = "https://weather-ydn-yql.media.yahoo.com/forecastrss";

        string timestamp = StringHelper.GenerateTimeStamp();
        String oauthNonce = StringHelper.GenerateNonce();
        IList<string> parameters = new List<string>();
        parameters.Add("oauth_consumer_key=" + consumerKey);
        parameters.Add("oauth_nonce=" + oauthNonce);
        parameters.Add("oauth_signature_method=HMAC-SHA1");
        parameters.Add("oauth_timestamp=" + timestamp);
        parameters.Add("oauth_version=1.0");
        // Make sure value is encoded
            parameters.Add("location=" + HttpUtility.UrlEncode("pune,in", Encoding.UTF8));
            parameters.Add("format=json");
            ((List<string>) parameters).Sort();

            StringBuilder parametersList = new StringBuilder();
            for (int i = 0; i < parameters.Count; i++)
            {
                parametersList.Append(((i > 0) ? "&" : "") + parameters.ElementAt(i));
            }

            var signatureString = "GET&" +
                                  HttpUtility.UrlEncode(url,Encoding.UTF8) + "&" +
                                  HttpUtility.UrlEncode(parametersList.ToString(), Encoding.UTF8);
            string signature = null;
            try
            {
                string secretAccessKey = consumerSecret;
                byte[] secretKey = Encoding.UTF8.GetBytes(secretAccessKey);
                HMACSHA1 hmac = new HMACSHA1(secretKey);
                hmac.Initialize();
                byte[] bytes = Encoding.UTF8.GetBytes(signatureString);
                byte[] rawHmac = hmac.ComputeHash(bytes);
                signature = Convert.ToBase64String(rawHmac);
            }
            catch (Exception e)
            {
                Console.WriteLine("Unable to append signature");                
            }
            string authorizationLine = "OAuth " +
                                       "oauth_consumer_key=\"" + consumerKey + "\", " +
                                       "oauth_nonce=\"" + oauthNonce + "\", " +
                                       "oauth_timestamp=\"" + timestamp + "\", " +
                                       "oauth_signature_method=\"HMAC-SHA1\", " +
                                       "oauth_signature=\"" + signature + "\", " +
                                       "oauth_version=\"1.0\"";

            HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url + "?location=pune,in&format=json");
            request.Headers.Add("Authorization", authorizationLine);
            request.Headers.Add("Yahoo-App-Id", appId);
            request.ContentType = "application/json; charset=UTF-8";
            request.Accept = "application/json";
            HttpWebResponse response = (HttpWebResponse) request.GetResponse();
            Stream receiveStream = response.GetResponseStream();
            StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8);
            Console.WriteLine(readStream.ReadLine());
        }    
}

【问题讨论】:

标签: c# oauth yahoo-weather-api


【解决方案1】:

你在哪一行得到错误? GetResponse() 返回它? 我认为您使用的凭据 (appId,consumerKey,consumerSecret) 无效!

【讨论】:

  • 我已经检查了所有凭据,并且还联系了雅虎技术团队,根据他们的建议,我已经进行了所有更改。但是我的问题也没有得到解决。所以我在这里寻求帮助。
  • @TejashriSawashe 我也有类似的问题?怎么解决的?
  • 我得到了相同的响应 - 401 Unauthorized。将代码从 Java 转换为 VB.NET,看起来与您的非常相似。有没有运气找到解决方案?
  • 我认为您必须为此 Yahoo Weather API 使用其他库或其他语言。 developer.yahoo.com/weather/…
【解决方案2】:
public string appId = "Your app-id";
        public string consumerKey = "Your-consumer key";
        public string consumerSecret = "Your Consumer Secret key";

        // GET: api/Random
        [HttpGet("{CityName}")]
        public async Task<IActionResult> GetAsync([FromUri] string CityName)
        {




        string urlss = "https://weather-ydn-yql.media.yahoo.com/forecastrss?location=";
            string url = urlss + CityName+ "&format=json&u=c";
            JObject jresult;
            using (var client = new HttpClient())
            {
                try
                {

                    var webClient = new WebClient();
                    webClient.Headers.Add(AssembleOAuthHeader());
                    var d = webClient.DownloadString(url);
                    jresult = JObject.Parse(d);
                    var json_jsonstring = Newtonsoft.Json.JsonConvert.SerializeObject(jresult);
                    return Ok(json_jsonstring);

                }
                catch (HttpRequestException httpRequestException)
                {
                    return BadRequest($"Error getting weather from Yahoo Weather: {httpRequestException.Message}");
                }


            }


        }

        public string AssembleOAuthHeader()
        {
            return "Authorization: OAuth " +
                   "realm=\"yahooapis.com\"," +
                   "oauth_consumer_key=\"" + consumerKey + "\"," +
                   "oauth_nonce=\"" + Guid.NewGuid() + "\"," +
                   "oauth_signature_method=\"PLAINTEXT\"," +
                   "oauth_timestamp=\"" + ((DateTime.UtcNow.Ticks - new DateTime(1970, 1, 1).Ticks) / (1000 * 10000)) +
                   "\"," +
                   "oauth_version=\"1.0\"," +
                   "oauth_signature=\"" + consumerSecret + "%26\"," +
                   "oauth_callback=\"oob\"";

        }

【讨论】:

  • 请提供解释和答案:)
【解决方案3】:

对于 yahoo weather new 身份验证,您可以使用这个 python 库 yahoo-weather

【讨论】:

    【解决方案4】:

    我认为您的代码很好。问题在于雅虎端的 URL 解码执行不力。 Java URL Encode 使用大写进行编码,而 .net HTTPUtility.URLEncode 使用小写进行编码。我为一个字符串创建了一个扩展方法,它将以 Yahoo API 可以处理的方式纠正问题和 URL 编码。这样做之后一切都很好(我遇到了与你完全相同的问题)。

      <Extension>
        Public Function UppercaseURLEncode(ByVal sourceString As String) As String
    
            Dim temp As Char() = HttpUtility.UrlEncode(sourceString).ToCharArray()
    
            For i As Integer = 0 To temp.Length - 2
    
                If temp(i).ToString().Equals("%", StringComparison.OrdinalIgnoreCase) Then
    
                    temp(i + 1) = Char.ToUpper(temp(i + 1))
                    temp(i + 2) = Char.ToUpper(temp(i + 2))
    
                End If
    
            Next
    
            Return New String(temp)
    
        End Function
    

    【讨论】:

    • 您还需要在此行中将一个 & 符号附加到您的使用者密钥: string secretAccessKey = consumerSecret;所以应该是字符串secretAccessKey = consumerSecret + "&";
    【解决方案5】:
    //Here Is The Working Code :
    
    public class YWSample
    {
        const string cURL = "https://weather-ydn-yql.media.yahoo.com/forecastrss";
        const string cAppID = "Your-App-ID";
        const string cConsumerKey = "Your-Consumer-Key";
        const string cConsumerSecret = "Your-Consumer-Secret";
        const string cOAuthVersion = "1.0";
        const string cOAuthSignMethod = "HMAC-SHA1";
        const string cWeatherID = "woeid=727232";  // Amsterdam, The Netherlands
        const string cUnitID = "u=c";           // Metric units
        const string cFormat = "xml";
    
        //Code to get timestamp
        static string _get_timestamp()
        {
            var lTS = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
            return Convert.ToInt64(lTS.TotalSeconds).ToString();
        }  
    
        //Code to get nonce
        static string _get_nonce()
        {
            return Convert.ToBase64String(
             new ASCIIEncoding().GetBytes(
              DateTime.Now.Ticks.ToString()
             )
            );
        }  // end _get_nonce
    
        static string _get_auth()
        {
            var lNonce = _get_nonce();
            var lTimes = _get_timestamp();
            var lCKey = string.Concat(cConsumerSecret, "&");
            var lSign = $"format={cFormat}&" + $"oauth_consumer_key={cConsumerKey}&" + $"oauth_nonce={lNonce}&" +
                           $"oauth_signature_method={cOAuthSignMethod}&" + $"oauth_timestamp={lTimes}&" +
                           $"oauth_version={cOAuthVersion}&" + $"{cUnitID}&{cWeatherID}";
    
            lSign = string.Concat(
             "GET&", Uri.EscapeDataString(cURL), "&", Uri.EscapeDataString(lSign)
            );
    
            using (var lHasher = new HMACSHA1(Encoding.ASCII.GetBytes(lCKey)))
            {
                lSign = Convert.ToBase64String(
                 lHasher.ComputeHash(Encoding.ASCII.GetBytes(lSign))
                );
            }  // end using
    
            return "OAuth " +
                   "oauth_consumer_key=\"" + cConsumerKey + "\", " +
                   "oauth_nonce=\"" + lNonce + "\", " +
                   "oauth_timestamp=\"" + lTimes + "\", " +
                   "oauth_signature_method=\"" + cOAuthSignMethod + "\", " +
                   "oauth_signature=\"" + lSign + "\", " +
                   "oauth_version=\"" + cOAuthVersion + "\"";
    
        }  // end _get_auth
    
        public static void Main(string[] args)
        {
            const string lURL = cURL + "?" + cWeatherID + "&" + cUnitID + "&format=" + cFormat;
    
            var lClt = new WebClient();
    
            lClt.Headers.Set("Content-Type", "application/" + cFormat);
            lClt.Headers.Add("Yahoo-App-Id", cAppID);
            lClt.Headers.Add("Authorization", _get_auth());
    
            Console.WriteLine("Downloading Yahoo weather report . . .");
    
            var lDataBuffer = lClt.DownloadData(lURL);
    
            var lOut = Encoding.ASCII.GetString(lDataBuffer);
    
            Console.WriteLine(lOut);
    
            Console.Write("Press any key to continue . . . ");
            Console.ReadKey(true);
        }//end of Main
    
    }  // end YWSample 
    

    【讨论】:

      猜你喜欢
      • 2014-07-01
      • 2016-12-14
      • 2018-08-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多