1. using System;
  2. using System.Security.Cryptography;
  3. using System.Collections.Generic;
  4. using System.Text;
  5. using System.Web;
  6.  
  7. namespace OAuth {
  8. public class OAuthBase {
  9.  
  10. /// <summary>
  11. /// Provides a predefined set of algorithms that are supported officially by the protocol
  12. /// </summary>
  13. public enum SignatureTypes {
  14. HMACSHA1,
  15. PLAINTEXT,
  16. RSASHA1
  17. }
  18.  
  19. /// <summary>
  20. /// Provides an internal structure to sort the query parameter
  21. /// </summary>
  22. protected class QueryParameter {
  23. private string name = null;
  24. private string value = null;
  25.  
  26. public QueryParameter(string name, string value) {
  27. this.name = name;
  28. this.value = value;
  29. }
  30.  
  31. public string Name {
  32. get { return name; }
  33. }
  34.  
  35. public string Value {
  36. get { return value; }
  37. }
  38. }
  39.  
  40. /// <summary>
  41. /// Comparer class used to perform the sorting of the query parameters
  42. /// </summary>
  43. protected class QueryParameterComparer : IComparer<QueryParameter> {
  44.  
  45. #region IComparer<QueryParameter> Members
  46.  
  47. public int Compare(QueryParameter x, QueryParameter y) {
  48. if (x.Name == y.Name) {
  49. return string.Compare(x.Value, y.Value);
  50. } else {
  51. return string.Compare(x.Name, y.Name);
  52. }
  53. }
  54.  
  55. #endregion
  56. }
  57.  
  58. protected const string OAuthVersion = "1.0";
  59. protected const string OAuthParameterPrefix = "oauth_";
  60.  
  61. //
  62. // List of know and used oauth parameters' names
  63. //
  64. protected const string OAuthConsumerKeyKey = "oauth_consumer_key";
  65. protected const string OAuthCallbackKey = "oauth_callback";
  66. protected const string OAuthVersionKey = "oauth_version";
  67. protected const string OAuthSignatureMethodKey = "oauth_signature_method";
  68. protected const string OAuthSignatureKey = "oauth_signature";
  69. protected const string OAuthTimestampKey = "oauth_timestamp";
  70. protected const string OAuthNonceKey = "oauth_nonce";
  71. protected const string OAuthTokenKey = "oauth_token";
  72. protected const string OAuthTokenSecretKey = "oauth_token_secret";
  73.  
  74. protected const string HMACSHA1SignatureType = "HMAC-SHA1";
  75. protected const string PlainTextSignatureType = "PLAINTEXT";
  76. protected const string RSASHA1SignatureType = "RSA-SHA1";
  77.  
  78. protected Random random = new Random();
  79.  
  80. protected string unreservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~";
  81.  
  82. /// <summary>
  83. /// Helper function to compute a hash value
  84. /// </summary>
  85. /// <param name="hashAlgorithm">The hashing algoirhtm used. If that algorithm needs some initialization, like HMAC and its derivatives, they should be initialized prior to passing it to this function</param>
  86. /// <param name="data">The data to hash</param>
  87. /// <returns>a Base64 string of the hash value</returns>
  88. private string ComputeHash(HashAlgorithm hashAlgorithm, string data) {
  89. if (hashAlgorithm == null) {
  90. throw new ArgumentNullException("hashAlgorithm");
  91. }
  92.  
  93. if (string.IsNullOrEmpty(data)) {
  94. throw new ArgumentNullException("data");
  95. }
  96.  
  97. byte[] dataBuffer = System.Text.Encoding.ASCII.GetBytes(data);
  98. byte[] hashBytes = hashAlgorithm.ComputeHash(dataBuffer);
  99.  
  100. return Convert.ToBase64String(hashBytes);
  101. }
  102.  
  103. /// <summary>
  104. /// Internal function to cut out all non oauth query string parameters (all parameters not begining with "oauth_")
  105. /// </summary>
  106. /// <param name="parameters">The query string part of the Url</param>
  107. /// <returns>A list of QueryParameter each containing the parameter name and value</returns>
  108. private List<QueryParameter> GetQueryParameters(string parameters) {
  109. if (parameters.StartsWith("?")) {
  110. parameters = parameters.Remove(0, 1);
  111. }
  112.  
  113. List<QueryParameter> result = new List<QueryParameter>();
  114.  
  115. if (!string.IsNullOrEmpty(parameters)) {
  116. string[] p = parameters.Split('&');
  117. foreach (string s in p) {
  118. if (!string.IsNullOrEmpty(s) && !s.StartsWith(OAuthParameterPrefix)) {
  119. if (s.IndexOf('=') > -1) {
  120. string[] temp = s.Split('=');
  121. result.Add(new QueryParameter(temp[0], temp[1]));
  122. } else {
  123. result.Add(new QueryParameter(s, string.Empty));
  124. }
  125. }
  126. }
  127. }
  128.  
  129. return result;
  130. }
  131.  
  132. /// <summary>
  133. /// This is a different Url Encode implementation since the default .NET one outputs the percent encoding in lower case.
  134. /// While this is not a problem with the percent encoding spec, it is used in upper case throughout OAuth
  135. /// </summary>
  136. /// <param name="value">The value to Url encode</param>
  137. /// <returns>Returns a Url encoded string</returns>
  138. protected string UrlEncode(string value) {
  139. StringBuilder result = new StringBuilder();
  140.  
  141. foreach (char symbol in value) {
  142. if (unreservedChars.IndexOf(symbol) != -1) {
  143. result.Append(symbol);
  144. } else {
  145. result.Append('%' + String.Format("{0:X2}", (int)symbol));
  146. }
  147. }
  148.  
  149. return result.ToString();
  150. }
  151.  
  152. /// <summary>
  153. /// Normalizes the request parameters according to the spec
  154. /// </summary>
  155. /// <param name="parameters">The list of parameters already sorted</param>
  156. /// <returns>a string representing the normalized parameters</returns>
  157. protected string NormalizeRequestParameters(IList<QueryParameter> parameters) {
  158. StringBuilder sb = new StringBuilder();
  159. QueryParameter p = null;
  160. for (int i = 0; i < parameters.Count; i++) {
  161. p = parameters[i];
  162. sb.AppendFormat("{0}={1}", p.Name, p.Value);
  163.  
  164. if (i < parameters.Count - 1) {
  165. sb.Append("&");
  166. }
  167. }
  168.  
  169. return sb.ToString();
  170. }
  171.  
  172. /// <summary>
  173. /// Generate the signature base that is used to produce the signature
  174. /// </summary>
  175. /// <param name="url">The full url that needs to be signed including its non OAuth url parameters</param>
  176. /// <param name="consumerKey">The consumer key</param>
  177. /// <param name="token">The token, if available. If not available pass null or an empty string</param>
  178. /// <param name="tokenSecret">The token secret, if available. If not available pass null or an empty string</param>
  179. /// <param name="httpMethod">The http method used. Must be a valid HTTP method verb (POST,GET,PUT, etc)</param>
  180. /// <param name="signatureType">The signature type. To use the default values use <see cref="OAuthBase.SignatureTypes">OAuthBase.SignatureTypes</see>.</param>
  181. /// <returns>The signature base</returns>
  182. public string GenerateSignatureBase(Uri url, string consumerKey, string token, string tokenSecret, string httpMethod, string timeStamp, string nonce, string signatureType, out string normalizedUrl, out string normalizedRequestParameters) {
  183. if (token == null) {
  184. token = string.Empty;
  185. }
  186.  
  187. if (tokenSecret == null) {
  188. tokenSecret = string.Empty;
  189. }
  190.  
  191. if (string.IsNullOrEmpty(consumerKey)) {
  192. throw new ArgumentNullException("consumerKey");
  193. }
  194.  
  195. if (string.IsNullOrEmpty(httpMethod)) {
  196. throw new ArgumentNullException("httpMethod");
  197. }
  198.  
  199. if (string.IsNullOrEmpty(signatureType)) {
  200. throw new ArgumentNullException("signatureType");
  201. }
  202.  
  203. normalizedUrl = null;
  204. normalizedRequestParameters = null;
  205.  
  206. List<QueryParameter> parameters = GetQueryParameters(url.Query);
  207. parameters.Add(new QueryParameter(OAuthVersionKey, OAuthVersion));
  208. parameters.Add(new QueryParameter(OAuthNonceKey, nonce));
  209. parameters.Add(new QueryParameter(OAuthTimestampKey, timeStamp));
  210. parameters.Add(new QueryParameter(OAuthSignatureMethodKey, signatureType));
  211. parameters.Add(new QueryParameter(OAuthConsumerKeyKey, consumerKey));
  212.  
  213. if (!string.IsNullOrEmpty(token)) {
  214. parameters.Add(new QueryParameter(OAuthTokenKey, token));
  215. }
  216.  
  217. parameters.Sort(new QueryParameterComparer());
  218.  
  219. normalizedUrl = string.Format("{0}://{1}", url.Scheme, url.Host);
  220. if (!((url.Scheme == "http" && url.Port == 80) || (url.Scheme == "https" && url.Port == 443)))
  221. {
  222. normalizedUrl += ":" + url.Port;
  223. }
  224. normalizedUrl += url.AbsolutePath;
  225. normalizedRequestParameters = NormalizeRequestParameters(parameters);
  226.  
  227. StringBuilder signatureBase = new StringBuilder();
  228. signatureBase.AppendFormat("{0}&", httpMethod.ToUpper());
  229. signatureBase.AppendFormat("{0}&", UrlEncode(normalizedUrl));
  230. signatureBase.AppendFormat("{0}", UrlEncode(normalizedRequestParameters));
  231.  
  232. return signatureBase.ToString();
  233. }
  234.  
  235. /// <summary>
  236. /// Generate the signature value based on the given signature base and hash algorithm
  237. /// </summary>
  238. /// <param name="signatureBase">The signature based as produced by the GenerateSignatureBase method or by any other means</param>
  239. /// <param name="hash">The hash algorithm used to perform the hashing. If the hashing algorithm requires initialization or a key it should be set prior to calling this method</param>
  240. /// <returns>A base64 string of the hash value</returns>
  241. public string GenerateSignatureUsingHash(string signatureBase, HashAlgorithm hash) {
  242. return ComputeHash(hash, signatureBase);
  243. }
  244.  
  245. /// <summary>
  246. /// Generates a signature using the HMAC-SHA1 algorithm
  247. /// </summary>
  248. /// <param name="url">The full url that needs to be signed including its non OAuth url parameters</param>
  249. /// <param name="consumerKey">The consumer key</param>
  250. /// <param name="consumerSecret">The consumer seceret</param>
  251. /// <param name="token">The token, if available. If not available pass null or an empty string</param>
  252. /// <param name="tokenSecret">The token secret, if available. If not available pass null or an empty string</param>
  253. /// <param name="httpMethod">The http method used. Must be a valid HTTP method verb (POST,GET,PUT, etc)</param>
  254. /// <returns>A base64 string of the hash value</returns>
  255. public string GenerateSignature(Uri url, string consumerKey, string consumerSecret, string token, string tokenSecret, string httpMethod, string timeStamp, string nonce, out string normalizedUrl, out string normalizedRequestParameters) {
  256. return GenerateSignature(url, consumerKey, consumerSecret, token, tokenSecret, httpMethod, timeStamp, nonce, SignatureTypes.HMACSHA1, out normalizedUrl, out normalizedRequestParameters);
  257. }
  258.  
  259. /// <summary>
  260. /// Generates a signature using the specified signatureType
  261. /// </summary>
  262. /// <param name="url">The full url that needs to be signed including its non OAuth url parameters</param>
  263. /// <param name="consumerKey">The consumer key</param>
  264. /// <param name="consumerSecret">The consumer seceret</param>
  265. /// <param name="token">The token, if available. If not available pass null or an empty string</param>
  266. /// <param name="tokenSecret">The token secret, if available. If not available pass null or an empty string</param>
  267. /// <param name="httpMethod">The http method used. Must be a valid HTTP method verb (POST,GET,PUT, etc)</param>
  268. /// <param name="signatureType">The type of signature to use</param>
  269. /// <returns>A base64 string of the hash value</returns>
  270. public string GenerateSignature(Uri url, string consumerKey, string consumerSecret, string token, string tokenSecret, string httpMethod, string timeStamp, string nonce, SignatureTypes signatureType, out string normalizedUrl, out string normalizedRequestParameters) {
  271. normalizedUrl = null;
  272. normalizedRequestParameters = null;
  273.  
  274. switch (signatureType) {
  275. case SignatureTypes.PLAINTEXT:
  276. return HttpUtility.UrlEncode(string.Format("{0}&{1}", consumerSecret, tokenSecret));
  277. case SignatureTypes.HMACSHA1:
  278. string signatureBase = GenerateSignatureBase(url, consumerKey, token, tokenSecret, httpMethod, timeStamp, nonce, HMACSHA1SignatureType, out normalizedUrl, out normalizedRequestParameters);
  279.  
  280. HMACSHA1 hmacsha1 = new HMACSHA1();
  281. hmacsha1.Key = Encoding.ASCII.GetBytes(string.Format("{0}&{1}", UrlEncode(consumerSecret), string.IsNullOrEmpty(tokenSecret) ? "" : UrlEncode(tokenSecret)));
  282.  
  283. return GenerateSignatureUsingHash(signatureBase, hmacsha1);
  284. case SignatureTypes.RSASHA1:
  285. throw new NotImplementedException();
  286. default:
  287. throw new ArgumentException("Unknown signature type", "signatureType");
  288. }
  289. }
  290.  
  291. /// <summary>
  292. /// Generate the timestamp for the signature
  293. /// </summary>
  294. /// <returns></returns>
  295. public virtual string GenerateTimeStamp() {
  296. // Default implementation of UNIX time of the current UTC time
  297. TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
  298. return Convert.ToInt64(ts.TotalSeconds).ToString();
  299. }
  300.  
  301. /// <summary>
  302. /// Generate a nonce
  303. /// </summary>
  304. /// <returns></returns>
  305. public virtual string GenerateNonce() {
  306. // Just a simple implementation of a random number between 123400 and 9999999
  307. return random.Next(123400, 9999999).ToString();
  308. }
  309.  
  310. }
  311. }

OAuthBase.cs的更多相关文章

  1. 新浪微博开放平台OAuth授权解决方案(含代码)

    前几日一位朋友项目中需要使用新浪微博的接口,故和这位朋友一同研究了新浪微博开放平台上面所提供的资料,首先要使用这些接口是需要用户登录并且授权的,新浪微博开放平台其实是提供两种授权方式的,第一种是:OA ...

  2. 豆瓣api之OAuth认证

    豆瓣api通过OAuth允许第三方应用访问用户数据,所以OAuth认证就是我们整个project的基础了. OAuth认证听起来挺神秘,其实挺简单的. 现在的大型网站的开放平台的认证几乎都是采用OAu ...

  3. [C#] 剖析 AssemblyInfo.cs - 了解常用的特性 Attribute

    剖析 AssemblyInfo.cs - 了解常用的特性 Attribute [博主]反骨仔 [原文]http://www.cnblogs.com/liqingwen/p/5944391.html 序 ...

  4. Atitit 软件架构方法的进化与演进cs bs soa roa  msa  attilax总结

    Atitit 软件架构方法的进化与演进cs bs soa roa  msa  attilax总结 1.1. 软件体系架构是沿着单机到 CS 架构,再到 BS 的三层架构甚至多层架构逐步发展过来的,关于 ...

  5. 从java文件和CS文件里查询方法使用次数工具

    前几天,领导让我找一下老系统(Java)里getRemoteUser方法都哪个文件用了,package是什么,方法被调用了多少次,当时因为着急,所以,直接人工找的,但是以后要是再出现,人工找就太讨厌了 ...

  6. 关于 WP 开发中.xaml 与.xaml.cs 的关系

    今天我们先来看一下在WP8.1开发中最长见到的几个文件之间的关系.比较论证,在看这个问题之前我们简单看看.NET平台其他两个不同的框架: Windows Forms 先看看Window Forms中的 ...

  7. .net 用户控件ascx.cs注册js脚本代码无效果

    在.net web项目中碰到一个比较奇怪的问题,网上没找到解决方案,先自己mark一下 问题描述: 添加一个用户控件ascx,在后端.cs添加js注册脚本,执行后没有弹出框 注册脚本为: this.P ...

  8. DateHelper.cs日期时间操作辅助类C#

    //==================================================================== //** Copyright © classbao.com ...

  9. 仅用aspx文件实现Ajax调用后台cs程序。(实例)

    仅用aspx文件实现Ajax调用后台cs无刷新程序.(实例) 两个文件:aaa.aspx 和aaa.aspx.cs 一.aaa.aspx <script type="text/java ...

随机推荐

  1. css案例学习之relative与absolute

    代码 <!DOCTYPE html PUBliC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.o ...

  2. [转]linux下IPTABLES配置详解

    如果你的IPTABLES基础知识还不了解,建议先去看看.开始配置我们来配置一个filter表的防火墙.(1)查看本机关于IPTABLES的设置情况[root@tp ~]# iptables -L -n ...

  3. poj 3753 Training little cats_矩阵快速幂

    题意: 通过各种操作进行,给第i只猫花生,第i只猫吃光花生,第i只猫和第j只猫互换花生,问n次循环操作后结果是什么 很明显是构建个矩阵,然后矩阵相乘就好了 #include <iostream& ...

  4. hdu 2571 命运(dp)

    Problem Description 穿过幽谷意味着离大魔王lemon已经无限接近了! 可谁能想到,yifenfei在斩杀了一些虾兵蟹将后,却再次面临命运大迷宫的考验,这是魔王lemon设下的又一个 ...

  5. JAVA File类 分析(三)

    前面两篇与大家一起研究了unix下的文件系统,本篇将和大家一起分析 文件的属性和文件夹. ok,废话不说,先来段代码 #include <stdio.h> #include <sys ...

  6. 谈谈 css 的各种居中——读编写高质量代码有感

    css 的居中有水平居中和垂直居中,这两种居中又分为行内元素居中和块级元素居中,不同的居中用不同方法. 水平居中 1.行内元素水平居中(文本,图片) 给父层设置 text-align:center; ...

  7. Web--->>>Cookie与Session

    1.cookie 1.cookie是存在客户端(浏览器)的进程内存中和客户端所在的机器硬盘上 2.cookie只能能够存储少量文本,大概4K大小 3.cookie是不能在不同浏览器之间共享 3.创建c ...

  8. Silverlight学习(五)图形标绘

    Silverlight中进行图形标绘的方法太多了,这里的标绘和Arcgis中的标绘不同,这里大多是静态的标绘.标绘的方法主要有Path(路径标记法).直接标绘(Line等).几何标记(LineGeom ...

  9. vbox下安装 linux 64 bit出现“kernel requires an x86_64 cpu

        今天在vbox下安装linux 64bit出现"kernel requires an x86_64 cpu, but only detected "的错误,网上有很多文章介 ...

  10. JSP简介

    论坛 博客 微论 问答 游戏厅 天涯客 读书 更多 手机 服务 登录 注册   聚焦 民生 文学 旅游 财经 汽车 IT数码 时尚 情感 娱乐 视频 更多 北京 上海 广东 更多 天涯部落> J ...