如何使用jQuery/JavaScript调用需OAuth认证的雅虎新天气API?
Hey there, the 401 error you're seeing happens because your current approach is passing OAuth parameters as URL query params—OAuth 1.0 requires these to be in the request headers, plus you're missing critical authentication components like a valid signature, nonce, timestamp, and the required Yahoo-App-Id header. Let's walk through the correct implementation step by step.
Key Requirements for Yahoo Weather API Calls
Yahoo's OAuth 1.0 authenticated requests need these elements in the request headers:
Yahoo-App-Id: Your unique app ID from Yahoo Developer PortalAuthorization: A properly formatted OAuth string containing:oauth_consumer_key: Your Consumer Keyoauth_signature_method: Must beHMAC-SHA1oauth_timestamp: Current Unix timestampoauth_nonce: A random unique string for each requestoauth_version:1.0oauth_signature: HMAC-SHA1 hash generated from request details and your Consumer Secret
Working Code Implementation
Here's a complete example using jQuery. We'll include helper functions to generate nonce, timestamp, and the required signature:
// Helper function to generate a random nonce string function generateNonce() { return Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15); } // Helper function to generate HMAC-SHA1 signature function generateSignature(url, params, consumerSecret) { // Sort params alphabetically (required for OAuth 1.0) const sortedParams = Object.keys(params).sort().map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`).join('&'); const baseString = `GET&${encodeURIComponent(url)}&${encodeURIComponent(sortedParams)}`; const signingKey = `${encodeURIComponent(consumerSecret)}&`; // No oauth_token, so append empty & // Use CryptoJS to generate HMAC-SHA1 (you'll need to include CryptoJS library) const signature = CryptoJS.HmacSHA1(baseString, signingKey); return CryptoJS.enc.Base64.stringify(signature); } // Your Yahoo API credentials const consumerKey = "YOUR_CONSUMER_KEY"; const consumerSecret = "YOUR_CONSUMER_SECRET"; const yahooAppId = "YOUR_APP_ID"; const apiUrl = "https://weather-ydn-yql.media.yahoo.com/forecastrss"; // Request parameters const params = { location: "sunnyvale,ca", format: "json", oauth_consumer_key: consumerKey, oauth_signature_method: "HMAC-SHA1", oauth_timestamp: Math.floor(Date.now() / 1000).toString(), oauth_nonce: generateNonce(), oauth_version: "1.0" }; // Generate the signature params.oauth_signature = generateSignature(apiUrl, params, consumerSecret); // Build the Authorization header string const authHeader = Object.keys(params) .filter(key => key.startsWith('oauth_')) .map(key => `${encodeURIComponent(key)}="${encodeURIComponent(params[key])}"`) .join(', '); // Make the API request with jQuery $.ajax({ url: apiUrl, method: "GET", data: { location: params.location, format: params.format }, headers: { "Yahoo-App-Id": yahooAppId, "Authorization": `OAuth ${authHeader}`, "cache-control": "no-cache" }, success: function(data) { console.log("Data Loaded:", data); }, error: function(xhr, status, error) { console.error("Request failed:", status, error); console.log("Response:", xhr.responseText); } });
Important Notes
- CryptoJS Dependency: The signature generation uses CryptoJS for HMAC-SHA1. You'll need to include the library in your project—you can add it via a CDN like:
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.1.1/crypto-js.min.js"></script> - Parameter Sorting: OAuth 1.0 requires sorting request parameters alphabetically when generating the base string—this is critical for the signature to be valid.
- Unique Nonce/Timestamp: Each request needs a unique nonce and current timestamp to prevent replay attacks. Never reuse these values.
- Headers vs Query Params: Only non-OAuth parameters (like
locationandformat) go in the query string; all OAuth-related values stay in theAuthorizationheader.
Why Your Original Code Failed
Your $.get call passed OAuth parameters as query params, which Yahoo's API doesn't accept for OAuth authentication. Additionally, you didn't generate a valid signature, include the Yahoo-App-Id header, or provide a nonce/timestamp—all required for a successful authenticated request.
内容的提问来源于stack exchange,提问作者user979331

