最近由於公司的需求特別多,而且還不是一個項目的需求,幾個數據庫幾個VS來回切換。難免搞混搞亂,忘記。於是自己用WPF做了一個小工具:AgileToDo,一個待辦列表。本來使用sqlce來做本地的存儲。但是在這個雲時代,搞本地存儲顯然不能拿出手。於是我決定給它集成有道雲筆記,使用有道雲筆記的的OPEN API來實現雲端的存儲。http://note.youdao.com/open/apidoc.html
有道雲筆記的API使用OAuth的方式對第三方應用進行授權。OAuth的介紹就不多說了,說的人也挺多了,自己查資料吧。要使用它的API,我們需要授權。本來想完全有自己去實現一下這個過程的,不過看了授權的整個過程發現還是很復雜的,不花點時間估計還真搞不出來。於是用nuget搜一下發現了DotNetOpenAuth,而且這個類庫的排名是很靠前的,想必是個神器。這里簡單說一下DotNetOpenAuth,據我簡單了解,DotNetOpenAuth主要是分了2部分的功能。一部分類庫是作為消費者,訪問第三方OAUTH服務,請求授權,比如我現在要做的事,訪問有道雲筆記的OAUTH服務。還有一部分類庫是用做服務方,實現OAUTH服務提供方的功能,可以使你的用戶系統支持OAUTH,供第三方消費者來使用。要深入了解的請直接去下載源碼,而且里面包含了很多sample,有web的有desktop的,訪問google,twitter的例子等等等。我的代碼當然也是參考了這些sample。
經過一晚上的折騰,終於用.NET實現了有道雲筆記的授權。廢話不多說,上代碼吧。
1.添加DotNetOpenAuth的引用
2.YDAuthBaseInfo類
/// <summary> /// OAUTH授權所需的一些基礎信息 /// </summary> public class YDAuthBaseInfo { public static readonly string OwnerId = ""; public static readonly string ConsumerName = ""; public static readonly string ConsumerKey = "";//開發者申請的KEY public static readonly string ConsumerSecret = "";//開發者申請的Secret public static readonly string BaseUrl = "http://sandbox.note.youdao.com";//測試沙箱基礎url public static readonly ServiceProviderDescription ServiceDescription = null;//OAUTH服務提供方信息 static YDAuthBaseInfo() { OwnerId = "kklldog"; ConsumerName = "AgileToDo"; ConsumerKey = "xxxx"; ConsumerSecret = "xxxx"; ServiceDescription = new ServiceProviderDescription { RequestTokenEndpoint = new MessageReceivingEndpoint(YDAuthBaseInfo.BaseUrl + "/oauth/request_token", HttpDeliveryMethods.AuthorizationHeaderRequest | HttpDeliveryMethods.GetRequest), UserAuthorizationEndpoint = new MessageReceivingEndpoint(YDAuthBaseInfo.BaseUrl + "/oauth/authorize", HttpDeliveryMethods.AuthorizationHeaderRequest | HttpDeliveryMethods.GetRequest), AccessTokenEndpoint = new MessageReceivingEndpoint(YDAuthBaseInfo.BaseUrl + "/oauth/access_token", HttpDeliveryMethods.AuthorizationHeaderRequest | HttpDeliveryMethods.GetRequest), TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() }, }; } }
3.YDTokenManager 類
/// <summary> /// TokenManager 令牌管理 /// </summary> public class YDTokenManager : IConsumerTokenManager { private Dictionary<string, string> _tokensAndSecrets = new Dictionary<string, string>(); private TokenType _tokenType; /// <summary> /// Initializes a new instance of the <see cref="YDTokenManager"/> class. /// </summary> /// <param name="consumerKey">The consumer key.</param> /// <param name="consumerSecret">The consumer secret.</param> public YDTokenManager(string consumerKey, string consumerSecret) { if (string.IsNullOrEmpty(consumerKey)) { throw new ArgumentNullException("consumerKey"); } this.ConsumerKey = consumerKey; this.ConsumerSecret = consumerSecret; } /// <summary> /// Gets the consumer key. /// </summary> /// <value>The consumer key.</value> public string ConsumerKey { get; private set; } /// <summary> /// Gets the consumer secret. /// </summary> /// <value>The consumer secret.</value> public string ConsumerSecret { get; private set; } #region ITokenManager Members public string GetTokenSecret(string token) { return this._tokensAndSecrets[token]; } public void StoreNewRequestToken(UnauthorizedTokenRequest request, ITokenSecretContainingMessage response) { this._tokensAndSecrets[response.Token] = response.TokenSecret; _tokenType = TokenType.RequestToken; } public void ExpireRequestTokenAndStoreNewAccessToken(string consumerKey, string requestToken, string accessToken, string accessTokenSecret) { this._tokensAndSecrets.Remove(requestToken); this._tokensAndSecrets[accessToken] = accessTokenSecret; _tokenType = TokenType.AccessToken; } /// <summary> /// Classifies a token as a request token or an access token. /// </summary> /// <param name="token">The token to classify.</param> /// <returns>Request or Access token, or invalid if the token is not recognized.</returns> public TokenType GetTokenType(string token) { return _tokenType; } #endregion }
4.YDWebConsumer類
/// <summary> /// 有道OPEN AUTH的web端消費者實現 /// </summary> public class YDWebConsumer:WebConsumer { public YDWebConsumer(ServiceProviderDescription serviceProvider, IConsumerTokenManager tokenManager) : base(serviceProvider, tokenManager) { } /// <summary> /// 請求授權 /// </summary> /// <param name="consumer"></param> public static void RequestAuthorization(YDWebConsumer consumer) { if (consumer == null) { throw new ArgumentNullException("YDWebConsumer"); } Uri callback = GetCallbackUrlFromContext(); var request = consumer.PrepareRequestUserAuthorization(callback, null, null); consumer.Channel.Send(request); } /// <summary> /// 獲取CALLBACKURL /// </summary> /// <returns></returns> internal static Uri GetCallbackUrlFromContext() { Uri callback = MessagingUtilities.GetRequestUrlFromContext().StripQueryArgumentsWithPrefix("oauth_"); return callback; } }
5.有了這些我們就可以去請求授權了。讓我們來試試,新建一個ASP.NET項目,在Default.aspx下修改代碼
<%@ Page Title="主頁" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="YDOpenAPI._Default" %> <asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent"> </asp:Content> <asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent"> <h2> 歡迎使用 ASP.NET! </h2> <asp:Label runat="server" ID="lbl"></asp:Label> </asp:Content>
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { var youDao = new YDWebConsumer(YDAuthBaseInfo.ServiceDescription, this.TokenManager); // 是否已經授權
var accessTokenResponse = youDao.ProcessUserAuthorization(); if (accessTokenResponse != null) { this.AccessToken = accessTokenResponse.AccessToken; this.lbl.Text ="Token:"+ this.AccessToken+" Screct:"+this.TokenManager.GetTokenSecret(this.AccessToken); } else if (this.AccessToken == null) { YDWebConsumer.RequestAuthorization(youDao); } } }
//TokenManager private YDTokenManager TokenManager { get { var tokenManager = (YDTokenManager)Session["tokenManager"]; if (tokenManager == null) { string consumerKey = YDOpenAPI4N.YDAuthBaseInfo.ConsumerKey; string consumerSecret = YDOpenAPI4N.YDAuthBaseInfo.ConsumerSecret; if (!string.IsNullOrEmpty(consumerKey)) { tokenManager = new YDTokenManager(consumerKey, consumerSecret); Session["tokenManager"] = tokenManager; } } return tokenManager; } }
跑一下是不是成功了。
有了AccessToken跟AccessSecret我們就可以去訪問有道雲筆記的操作API了:創建,刪除,修改筆記了。這部分接下來我也會實現。
希望對於需要了解OAUTH跟DOTNETOPENAUTH的同學能有幫助。