OAuth 驗證

昨天搞 OAuth 搞了快半天,才總算正常用 OAuth 登入 plurk api ,然後作個隨筆
網路上找到的許多人都透過 OAuthBase 來連上去,所以我也先去抓 OAuthBase
可是我參數都傳了,他就能沒辦法正常取得 Token ,一直顯示 400 錯誤,我也搞不懂是啥錯誤
最後我找了許多的網頁,然後透過 小朱 的兩篇文章(1, 2)去實作一個 OAuth 的驗證,總算成功登入 Plurk 了,我也不知為啥他的可以, OAuthBase 不行

等實作完整個 Plurk API 後再來釋出吧

想不到才一年多左右沒碰, plurk api 就變到我完全不認識他了=口=!

因為只是隨筆,所以就不附程式碼之類的了!相關的 OAuth 驗證可以參考小朱的兩篇文章來實作(當然是你跟我一樣一直無法用 OAuthBase 的才需要這樣玩(抹汗~))
---
仔細研究了一下,如果透過小朱的文章來使用 OAuth 的話,我資料都得透過 Get 方式作傳遞,如果可以我還是希望能透過 POST 的方式,那似乎得改動 OAuthBase ,以下是 Google 的 OAuth 的驗證程式,留存作研究,看看有沒有辦法將原本的 OAuthBase 改成正常的版本

/* Copyright (c) 2011 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * 
*/

using System;
using System.Text;
using System.Globalization;
using System.Net;
using System.IO;
using System.Collections.Generic;

namespace Google.GData.Client {
    /// <summary>
    /// Provides a means to generate an OAuth signature suitable for use
    /// with Google OAuth requests.
    /// </summary>
    public class OAuthUtil {
        // Google OAuth endpoints
        private static String requestTokenUrl = "https://www.google.com/accounts/OAuthGetRequestToken";
        private static String userAuthorizationUrl = "https://www.google.com/accounts/OAuthAuthorizeToken";
        private static String accessTokenUrl = "https://www.google.com/accounts/OAuthGetAccessToken";

        /// <summary>
        /// Generates an OAuth header.
        /// </summary>
        /// <param name="uri">The URI of the request</param>
        /// <param name="consumerKey">The consumer key</param>
        /// <param name="consumerSecret">The consumer secret</param>
        /// <param name="httpMethod">The http method</param>
        /// <returns>The OAuth authorization header</returns>
        public static string GenerateHeader(Uri uri, String consumerKey, String consumerSecret, String httpMethod) {
            return GenerateHeader(uri, consumerKey, consumerSecret, string.Empty, string.Empty, httpMethod);
        }

        /// <summary>
        /// Generates an OAuth header.
        /// </summary>
        /// <param name="uri">The URI of the request</param>
        /// <param name="consumerKey">The consumer key</param>
        /// <param name="consumerSecret">The consumer secret</param>
        /// <param name="token">The OAuth token</param>
        /// <param name="tokenSecret">The OAuth token secret</param>
        /// <param name="httpMethod">The http method</param>
        /// <returns>The OAuth authorization header</returns>
        public static string GenerateHeader(Uri uri, String consumerKey, String consumerSecret, String token,
            String tokenSecret, String httpMethod) {
            OAuthParameters parameters = new OAuthParameters() { 
                ConsumerKey = consumerKey, ConsumerSecret = consumerSecret, Token = token, TokenSecret = tokenSecret, SignatureMethod = OAuthBase.HMACSHA1SignatureType 
            };
            return GenerateHeader(uri, httpMethod, parameters);
        }

        /// <summary>
        /// Generates an OAuth header.
        /// </summary>
        /// <param name="uri">The URI of the request</param>
        /// <param name="httpMethod">The http method</param>
        /// <param name="parameters">The OAuth parameters</param>
        /// <returns>The OAuth authorization header</returns>
        public static string GenerateHeader(Uri uri, string httpMethod, OAuthParameters parameters) {
            parameters.Timestamp = OAuthBase.GenerateTimeStamp();
            parameters.Nonce = OAuthBase.GenerateNonce();

            string signature = OAuthBase.GenerateSignature(uri, httpMethod, parameters);

            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("Authorization: OAuth {0}=\"{1}\",", OAuthBase.OAuthVersionKey, OAuthBase.OAuthVersion);
            sb.AppendFormat("{0}=\"{1}\",", OAuthBase.OAuthNonceKey, OAuthBase.EncodingPerRFC3986(parameters.Nonce));
            sb.AppendFormat("{0}=\"{1}\",", OAuthBase.OAuthTimestampKey, OAuthBase.EncodingPerRFC3986(parameters.Timestamp));
            sb.AppendFormat("{0}=\"{1}\",", OAuthBase.OAuthConsumerKeyKey, OAuthBase.EncodingPerRFC3986(parameters.ConsumerKey));
            if (parameters.BaseProperties.ContainsKey(OAuthBase.OAuthVerifierKey)) {
                sb.AppendFormat("{0}=\"{1}\",", OAuthBase.OAuthVerifierKey, OAuthBase.EncodingPerRFC3986(parameters.BaseProperties[OAuthBase.OAuthVerifierKey]));
            }
            if (!String.IsNullOrEmpty(parameters.Token)) {
                sb.AppendFormat("{0}=\"{1}\",", OAuthBase.OAuthTokenKey, OAuthBase.EncodingPerRFC3986(parameters.Token));
            }
            if (parameters.BaseProperties.ContainsKey(OAuthBase.OAuthCallbackKey)) {
                sb.AppendFormat("{0}=\"{1}\",", OAuthBase.OAuthCallbackKey, OAuthBase.EncodingPerRFC3986(parameters.BaseProperties[OAuthBase.OAuthCallbackKey]));
            }
            sb.AppendFormat("{0}=\"{1}\",", OAuthBase.OAuthSignatureMethodKey, OAuthBase.HMACSHA1SignatureType);
            sb.AppendFormat("{0}=\"{1}\"", OAuthBase.OAuthSignatureKey, OAuthBase.EncodingPerRFC3986(signature));

            return sb.ToString();
        }

        /// <summary>
        /// Contacts Google for a request token, first step of the OAuth authentication process.
        /// When successful, updates the OAuthParameter instance passed as parameter by setting
        /// Token and TokenSecret.
        /// </summary>
        /// <param name="parameters">The OAuth parameters</param>
        public static void GetUnauthorizedRequestToken(OAuthParameters parameters) {
            Uri requestUri = new Uri(string.Format("{0}?scope={1}", requestTokenUrl, OAuthBase.EncodingPerRFC3986(parameters.Scope)));

            // callback is only needed when getting the request token
            bool callbackExists = false;
            if (!string.IsNullOrEmpty(parameters.Callback)) {
                parameters.BaseProperties.Add(OAuthBase.OAuthCallbackKey, parameters.Callback);
                callbackExists = true;
            }

            string headers = GenerateHeader(requestUri, "GET", parameters);
            WebRequest request = WebRequest.Create(requestUri);
            request.Headers.Add(headers);

            WebResponse response = request.GetResponse();
            string result = "";
            if (response != null) {
                Stream responseStream = response.GetResponseStream();
                StreamReader reader = new StreamReader(responseStream);
                result = reader.ReadToEnd();
            }

            if (callbackExists) {
                parameters.BaseProperties.Remove(OAuthBase.OAuthCallbackKey);
            }

            // split results and update parameters
            SortedDictionary<string, string> responseValues = OAuthBase.GetQueryParameters(result);
            parameters.Token = responseValues[OAuthBase.OAuthTokenKey];
            parameters.TokenSecret = responseValues[OAuthBase.OAuthTokenSecretKey];
        }

        /// <summary>
        /// Generates the url which the user should visit in order to authenticate and
        /// authorize with the Service Provider.
        /// When successful, updates the OAuthParameter instance passed as parameter by setting
        /// Token and TokenSecret.
        /// </summary>
        /// <param name="parameters">The OAuth parameters</param>
        /// <returns>The full authorization url the user should visit</returns>
        public static string CreateUserAuthorizationUrl(OAuthParameters parameters) {
            StringBuilder sb = new StringBuilder();
            sb.Append(userAuthorizationUrl);
            sb.AppendFormat("?{0}={1}", OAuthBase.OAuthTokenKey, OAuthBase.EncodingPerRFC3986(parameters.Token));
            if (!string.IsNullOrEmpty(parameters.Callback)) {
                sb.AppendFormat("&{0}={1}", OAuthBase.OAuthCallbackKey, OAuthBase.EncodingPerRFC3986(parameters.Callback));
            }
            return sb.ToString();
        }

        /// <summary>
        /// Helper method which parses a querystring for the OAuth related parameters.
        /// It updates the OAuthParameter instance passed as parameter by setting
        /// Token, TokenSecret and Verifier (if present).
        /// </summary>
        /// <param name="parameters">The OAuth parameters</param>
        public static void UpdateOAuthParametersFromCallback(string queryString, OAuthParameters parameters) {
            //split results and update parameters
            SortedDictionary<string, string> responseValues = OAuthBase.GetQueryParameters(queryString);
            parameters.Token = responseValues[OAuthBase.OAuthTokenKey];
            if (responseValues.ContainsKey(OAuthBase.OAuthTokenSecretKey)) {
                parameters.TokenSecret = responseValues[OAuthBase.OAuthTokenSecretKey];
            }
            if (responseValues.ContainsKey(OAuthBase.OAuthVerifierKey)) {
                parameters.Verifier = responseValues[OAuthBase.OAuthVerifierKey];
            }
        }

        /// <summary>
        /// Exchanges the user-authorized request token for an access token.
        /// When successful, updates the OAuthParameter instance passed as parameter by setting
        /// Token and TokenSecret.
        /// </summary>
        /// <param name="parameters">The OAuth parameters</param>
        public static void GetAccessToken(OAuthParameters parameters) {
            Uri requestUri = new Uri(accessTokenUrl);

            string headers = GenerateHeader(requestUri, "GET", parameters);
            WebRequest request = WebRequest.Create(requestUri);
            request.Headers.Add(headers);

            WebResponse response = request.GetResponse();
            string result = "";
            if (response != null) {
                Stream responseStream = response.GetResponseStream();
                StreamReader reader = new StreamReader(responseStream);
                result = reader.ReadToEnd();
            }

            //split results and update parameters
            SortedDictionary<string, string> responseValues = OAuthBase.GetQueryParameters(result);
            parameters.Token = responseValues[OAuthBase.OAuthTokenKey];
            parameters.TokenSecret = responseValues[OAuthBase.OAuthTokenSecretKey];
        }
    }
}

留言

這個網誌中的熱門文章

DB 資料庫呈現復原中

Outlook 刪除大量重覆信件

[VB.Net] If vs IIf ,兩者的差異