{"id":29802,"date":"2024-11-25T13:02:34","date_gmt":"2024-11-25T05:02:34","guid":{"rendered":"https:\/\/fwq.ai\/blog\/29802\/"},"modified":"2024-11-25T13:02:34","modified_gmt":"2024-11-25T05:02:34","slug":"asp-net%e5%ae%9e%e7%8e%b0qq%e3%80%81%e5%be%ae%e4%bf%a1%e3%80%81%e6%96%b0%e6%b5%aa%e5%be%ae%e5%8d%9aoauth2-0%e6%8e%88%e6%9d%83%e7%99%bb%e5%bd%95%e7%9a%84%e5%ae%9e%e4%be%8b%e8%af%a6%e8%a7%a3","status":"publish","type":"post","link":"https:\/\/fwq.ai\/blog\/29802\/","title":{"rendered":"ASP.NET\u5b9e\u73b0QQ\u3001\u5fae\u4fe1\u3001\u65b0\u6d6a\u5fae\u535aOAuth2.0\u6388\u6743\u767b\u5f55\u7684\u5b9e\u4f8b\u8be6\u89e3"},"content":{"rendered":"<p>\u672c\u6587\u4e3b\u8981\u4ecb\u7ecd\u4e86qq\u3001\u5fae\u4fe1\u3001\u65b0\u6d6a\u5fae\u535aoauth2.0\u6388\u6743\u767b\u5f55\u7684\u793a\u4f8b\uff0c\u4e3b\u8981\u5c31\u662fget\u3001post\u8fdc\u7a0b\u63a5\u53e3\uff0c\u8fd4\u56de\u76f8\u5e94\u7684\u6570\u636e\uff0c\u8fd9\u91cc\u5217\u51fa\u76f8\u5173\u7684\u4ee3\u7801\uff0c\u4f9b\u5927\u5bb6\u53c2\u8003\u3002<\/p>\n<p>\u4e0d\u7ba1\u662f\u817e\u8baf\u8fd8\u662f\u65b0\u6d6a\uff0c\u67e5\u770b\u4ed6\u4eec\u7684API\uff0cPHP\u90fd\u662f\u6709\u5b8c\u6574\u7684\u63a5\u53e3\uff0c\u4f46\u5bf9C#\u652f\u6301\u4f3c\u4e4e\u90fd\u4e0d\u662f\u90a3\u4e48\u5b8c\u5584\uff0c\u90fd\u6ca1\u6709\uff0c\u817e\u8baf\u662f\u5b8c\u5168\u6ca1\u6709\uff0c\u65b0\u6d6a\u662f\u63d0\u4f9b\u7b2c\u4e09\u65b9\u7684\uff0c\u800c\u4e14\u540e\u671f\u8fd8\u4e0d\u4e00\u5b9a\u5347\u7ea7\uff0cNND\uff0c\u7528\u7b2c\u4e09\u65b9\u7684\u52a8\u8f84\u5c31\u4e00\u4e2a\u7c7b\u5e93\uff0c\u5404\u79cd\u914d\u7f6e\u8fd8\u5fc5\u987b\u6309\u7167\u4ed6\u4eec\u7ea6\u5b9a\u7684\u5199\uff0c\u70e6\u800c\u4e14\u4e71\uff0c\u7d22\u6027\u81ea\u5df1\u5199\uff0c\u540e\u671f\u7684\u6269\u5c55\u4e5f\u5bb9\u6613\uff0c\u770b\u8fc7\u63a5\u53e3\u540e\uff0c\u5f00\u59cb\u4ee5\u4e3a\u5f88\u96be\uff0c\u53c2\u8003\u4e86\u51e0\u4e2a\u6e90\u7801\u4e4b\u540e\u53d1\u73b0\u4e5f\u4e0d\u662f\u90a3\u4e48\u96be\uff0c\u65e0\u975e\u662fGET\u6216POST\u8bf7\u6c42\u4ed6\u4eec\u7684\u63a5\u53e3\u83b7\u53d6\u8fd4\u56de\u503c\u4e4b\u7c7b\u7684\uff0c\u8bdd\u4e0d\u591a\u8bf4\uff0c\u8fd9\u91cc\u53ea\u63d0\u4f9b\u51e0\u4e2a\u4ee3\u7801\u5171\u53c2\u8003\uff0c\u629b\u7816\u5f15\u7389\u4e86\u3002\u3002\u3002<\/p>\n<p>\u6211\u8fd9\u4e2a\u5199\u6cd5\u7684\u7279\u70b9\u662f\uff0c\u7528\u5230\u4e86Session\uff0c\u4f7f\u7528\u5bf9\u8c61\u5b9e\u4f8b\u5316\u4e4b\u540e\u8c03\u7528 Login() \u8df3\u8f6c\u5230\u767b\u5f55\u9875\u9762\uff0c\u5728\u56de\u8c03\u9875\u9762\u8c03\u7528Callback() \u6267\u884c\u4e4b\u540e\uff0c\u53ef\u4ee5\u4eceSession\u4e5f\u53ef\u4ee5\u5199\u72ec\u7acb\u7684\u51fd\u6570\uff08\u5982\uff1aGetOpenID()\uff09\u4e2d\u83b7\u53d6access_token\u6216\u7528\u6237\u7684\u552f\u4e00\u6807\u8bc6\uff0c\u4ee5\u65b9\u4fbf\u505a\u4e0b\u4e00\u6b65\u7684\u64cd\u4f5c\u3002\u6240\u8c13\u7ed1\u5b9a\u5c31\u662f\u628a\u7528\u6237\u7684\u552f\u4e00\u6807\u8bc6\u53d6\u51fa\uff0c\u63d2\u5165\u6570\u636e\u5e93\uff0c\u548c\u5e10\u53f7\u7ed1\u5b9a\u8d77\u6765\u3002<\/p>\n<p><strong>1.\u9996\u5148\u662f\u6240\u6709OAuth\u7c7b\u7684\u57fa\u7c7b\uff0c\u653e\u4e00\u4e9b\u9700\u8981\u516c\u7528\u7684\u65b9\u6cd5<\/strong><\/p>\n<pre>public&nbsp;abstract&nbsp;class&nbsp;BaseOAuth\r\n{\r\n&nbsp;&nbsp;public&nbsp;HttpRequest&nbsp;Request&nbsp;=&nbsp;HttpContext.Current.Request;\r\n&nbsp;&nbsp;public&nbsp;HttpResponse&nbsp;Response&nbsp;=&nbsp;HttpContext.Current.Response;\r\n&nbsp;&nbsp;public&nbsp;HttpSessionState&nbsp;Session&nbsp;=&nbsp;HttpContext.Current.Session;\r\n&nbsp;&nbsp;public&nbsp;abstract&nbsp;void&nbsp;Login();\r\n&nbsp;&nbsp;public&nbsp;abstract&nbsp;string&nbsp;Callback();\r\n&nbsp;&nbsp;#region&nbsp;\u5185\u90e8\u4f7f\u7528\u51fd\u6570\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;\u751f\u6210\u552f\u4e00\u968f\u673a\u4e32\u9632CSRF\u653b\u51fb\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;\/summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;returns&gt;&lt;\/returns&gt;\r\n&nbsp;&nbsp;protected&nbsp;string&nbsp;GetStateCode()\r\n&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;Random&nbsp;rand&nbsp;=&nbsp;new&nbsp;Random();\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;data&nbsp;=&nbsp;DateTime.Now.ToString(\"yyyyMMddHHmmssffff\")&nbsp;+&nbsp;rand.Next(1,&nbsp;0xf423f).ToString();\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;MD5CryptoServiceProvider&nbsp;md5&nbsp;=&nbsp;new&nbsp;MD5CryptoServiceProvider();\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;byte[]&nbsp;md5byte&nbsp;=&nbsp;md5.ComputeHash(UTF8Encoding.Default.GetBytes(data));\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;BitConverter.ToString(md5byte).Replace(\"-\",&nbsp;\"\");\r\n\r\n&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;GET\u8bf7\u6c42\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;\/summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;param&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;returns&gt;&lt;\/returns&gt;\r\n&nbsp;&nbsp;protected&nbsp;string&nbsp;GetRequest(string&nbsp;url)\r\n&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;HttpWebRequest&nbsp;httpWebRequest&nbsp;=&nbsp;System.Net.WebRequest.Create(url)&nbsp;as&nbsp;HttpWebRequest;\r\n&nbsp;&nbsp;&nbsp;&nbsp;httpWebRequest.Method&nbsp;=&nbsp;\"GET\";\r\n&nbsp;&nbsp;&nbsp;&nbsp;httpWebRequest.ServicePoint.Expect100Continue&nbsp;=&nbsp;false;\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;StreamReader&nbsp;responseReader&nbsp;=&nbsp;null;\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;responseData;\r\n&nbsp;&nbsp;&nbsp;&nbsp;try\r\n&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;responseReader&nbsp;=&nbsp;new&nbsp;StreamReader(httpWebRequest.GetResponse().GetResponseStream());\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;responseData&nbsp;=&nbsp;responseReader.ReadToEnd();\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&nbsp;finally\r\n&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;httpWebRequest.GetResponse().GetResponseStream().Close();\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;responseReader.Close();\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;responseData;\r\n&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;POST\u8bf7\u6c42\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;\/summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;param&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;param&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;returns&gt;&lt;\/returns&gt;\r\n&nbsp;&nbsp;protected&nbsp;string&nbsp;PostRequest(string&nbsp;url,&nbsp;string&nbsp;postData)\r\n&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;HttpWebRequest&nbsp;httpWebRequest&nbsp;=&nbsp;System.Net.WebRequest.Create(url)&nbsp;as&nbsp;HttpWebRequest;\r\n&nbsp;&nbsp;&nbsp;&nbsp;httpWebRequest.Method&nbsp;=&nbsp;\"POST\";\r\n&nbsp;&nbsp;&nbsp;&nbsp;httpWebRequest.ServicePoint.Expect100Continue&nbsp;=&nbsp;false;\r\n&nbsp;&nbsp;&nbsp;&nbsp;httpWebRequest.ContentType&nbsp;=&nbsp;\"application\/x-www-form-urlencoded\";\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;\/\/\u5199\u5165POST\u53c2\u6570\r\n&nbsp;&nbsp;&nbsp;&nbsp;StreamWriter&nbsp;requestWriter&nbsp;=&nbsp;new&nbsp;StreamWriter(httpWebRequest.GetRequestStream());\r\n&nbsp;&nbsp;&nbsp;&nbsp;try\r\n&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;requestWriter.Write(postData);\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&nbsp;finally\r\n&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;requestWriter.Close();\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;\/\/\u8bfb\u53d6\u8bf7\u6c42\u540e\u7684\u7ed3\u679c\r\n&nbsp;&nbsp;&nbsp;&nbsp;StreamReader&nbsp;responseReader&nbsp;=&nbsp;null;\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;responseData;\r\n&nbsp;&nbsp;&nbsp;&nbsp;try\r\n&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;responseReader&nbsp;=&nbsp;new&nbsp;StreamReader(httpWebRequest.GetResponse().GetResponseStream());\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;responseData&nbsp;=&nbsp;responseReader.ReadToEnd();\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&nbsp;finally\r\n&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;httpWebRequest.GetResponse().GetResponseStream().Close();\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;responseReader.Close();\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;responseData;\r\n&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;\u89e3\u6790JSON\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;\/summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;param&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;returns&gt;&lt;\/returns&gt;\r\n&nbsp;&nbsp;protected&nbsp;NameValueCollection&nbsp;ParseJson(string&nbsp;strJson)\r\n&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;NameValueCollection&nbsp;mc&nbsp;=&nbsp;new&nbsp;NameValueCollection();\r\n&nbsp;&nbsp;&nbsp;&nbsp;Regex&nbsp;regex&nbsp;=&nbsp;new&nbsp;Regex(@\"(s*\"\"?([^\"\"]*)\"\"?s*:s*\"\"?([^\"\"]*)\"\"?,?)\");\r\n&nbsp;&nbsp;&nbsp;&nbsp;strJson&nbsp;=&nbsp;strJson.Trim();\r\n&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(strJson.StartsWith(\"{\"))\r\n&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;strJson&nbsp;=&nbsp;strJson.Substring(1,&nbsp;strJson.Length&nbsp;-&nbsp;2);\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;foreach&nbsp;(Match&nbsp;m&nbsp;in&nbsp;regex.Matches(strJson))\r\n&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mc.Add(m.Groups[2].Value,&nbsp;m.Groups[3].Value);\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;mc;\r\n&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;\u89e3\u6790URL\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;\/summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;param&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;returns&gt;&lt;\/returns&gt;\r\n&nbsp;&nbsp;protected&nbsp;NameValueCollection&nbsp;ParseUrlParameters(string&nbsp;strParams)\r\n&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;NameValueCollection&nbsp;nc&nbsp;=&nbsp;new&nbsp;NameValueCollection();\r\n&nbsp;&nbsp;&nbsp;&nbsp;foreach&nbsp;(string&nbsp;p&nbsp;in&nbsp;strParams.Split('&amp;amp;'))\r\n&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string[]&nbsp;ps&nbsp;=&nbsp;p.Split('=');\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nc.Add(ps[0],&nbsp;ps[1]);\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;nc;\r\n&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;#endregion\r\n\r\n}<\/pre>\n<p>  \u767b\u5f55\u540e\u590d\u5236   <\/p>\n<p><strong>2.QQ\u7684OAuth\u7c7b<\/strong><\/p>\n<pre>public&nbsp;class&nbsp;QQOAuth&nbsp;:&nbsp;BaseOAuth\r\n{\r\n&nbsp;&nbsp;public&nbsp;string&nbsp;AppId&nbsp;=&nbsp;ConfigurationManager.AppSettings[\"OAuth_QQ_AppId\"];\r\n&nbsp;&nbsp;public&nbsp;string&nbsp;AppKey&nbsp;=&nbsp;ConfigurationManager.AppSettings[\"OAuth_QQ_AppKey\"];\r\n&nbsp;&nbsp;public&nbsp;string&nbsp;RedirectUrl&nbsp;=&nbsp;ConfigurationManager.AppSettings[\"OAuth_QQ_RedirectUrl\"];\r\n\r\n&nbsp;&nbsp;public&nbsp;const&nbsp;string&nbsp;GET_AUTH_CODE_URL&nbsp;=&nbsp;\"https:\/\/graph.qq.com\/oauth2.0\/authorize\";\r\n&nbsp;&nbsp;public&nbsp;const&nbsp;string&nbsp;GET_ACCESS_TOKEN_URL&nbsp;=&nbsp;\"https:\/\/graph.qq.com\/oauth2.0\/token\";\r\n&nbsp;&nbsp;public&nbsp;const&nbsp;string&nbsp;GET_OPENID_URL&nbsp;=&nbsp;\"https:\/\/graph.qq.com\/oauth2.0\/me\";\r\n\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;QQ\u767b\u5f55\uff0c\u8df3\u8f6c\u5230\u767b\u5f55\u9875\u9762\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;\/summary&gt;\r\n&nbsp;&nbsp;public&nbsp;override&nbsp;void&nbsp;Login()\r\n&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;\/\/-------\u751f\u6210\u552f\u4e00\u968f\u673a\u4e32\u9632CSRF\u653b\u51fb\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;state&nbsp;=&nbsp;GetStateCode();\r\n&nbsp;&nbsp;&nbsp;&nbsp;Session[\"QC_State\"]&nbsp;=&nbsp;state;&nbsp;\/\/state&nbsp;\u653e\u5165Session\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;parms&nbsp;=&nbsp;\"?response_type=code&amp;amp;\"\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+&nbsp;\"client_id=\"&nbsp;+&nbsp;AppId&nbsp;+&nbsp;\"&amp;amp;redirect_uri=\"&nbsp;+&nbsp;Uri.EscapeDataString(RedirectUrl)&nbsp;+&nbsp;\"&amp;amp;state=\"&nbsp;+&nbsp;state;\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;url&nbsp;=&nbsp;GET_AUTH_CODE_URL&nbsp;+&nbsp;parms;\r\n&nbsp;&nbsp;&nbsp;&nbsp;Response.Redirect(url);&nbsp;\/\/\u8df3\u8f6c\u5230\u767b\u5f55\u9875\u9762\r\n&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;QQ\u56de\u8c03\u51fd\u6570\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;\/summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;param&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;param&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;returns&gt;&lt;\/returns&gt;\r\n&nbsp;&nbsp;public&nbsp;override&nbsp;string&nbsp;Callback()\r\n&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;code&nbsp;=&nbsp;Request.QueryString[\"code\"];\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;state&nbsp;=&nbsp;Request.QueryString[\"state\"];\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;\/\/--------\u9a8c\u8bc1state\u9632\u6b62CSRF\u653b\u51fb\r\n&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(state&nbsp;!=&nbsp;(string)Session[\"QC_State\"])\r\n&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ShowError(\"30001\");\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;parms&nbsp;=&nbsp;\"?grant_type=authorization_code&amp;amp;\"\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+&nbsp;\"client_id=\"&nbsp;+&nbsp;AppId&nbsp;+&nbsp;\"&amp;amp;redirect_uri=\"&nbsp;+&nbsp;Uri.EscapeDataString(RedirectUrl)\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+&nbsp;\"&amp;amp;client_secret=\"&nbsp;+&nbsp;AppKey&nbsp;+&nbsp;\"&amp;amp;code=\"&nbsp;+&nbsp;code;\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;url&nbsp;=&nbsp;GET_ACCESS_TOKEN_URL&nbsp;+&nbsp;parms;\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;str&nbsp;=&nbsp;GetRequest(url);\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(str.IndexOf(\"callback\")&nbsp;!=&nbsp;-1)\r\n&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;lpos&nbsp;=&nbsp;str.IndexOf(\"(\");\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;rpos&nbsp;=&nbsp;str.IndexOf(\")\");\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;str&nbsp;=&nbsp;str.Substring(lpos&nbsp;+&nbsp;1,&nbsp;rpos&nbsp;-&nbsp;lpos&nbsp;-&nbsp;1);\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NameValueCollection&nbsp;msg&nbsp;=&nbsp;ParseJson(str);\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!string.IsNullOrEmpty(msg[\"error\"]))\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ShowError(msg[\"error\"],&nbsp;msg[\"error_description\"]);\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;NameValueCollection&nbsp;token&nbsp;=&nbsp;ParseUrlParameters(str);\r\n&nbsp;&nbsp;&nbsp;&nbsp;Session[\"QC_AccessToken\"]&nbsp;=&nbsp;token[\"access_token\"];&nbsp;\/\/access_token&nbsp;\u653e\u5165Session\r\n&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;token[\"access_token\"];\r\n&nbsp;&nbsp;}\r\n\r\n\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;\u4f7f\u7528Access&nbsp;Token\u6765\u83b7\u53d6\u7528\u6237\u7684OpenID\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;\/summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;param&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;returns&gt;&lt;\/returns&gt;\r\n&nbsp;&nbsp;public&nbsp;string&nbsp;GetOpenID()\r\n&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;parms&nbsp;=&nbsp;\"?access_token=\"&nbsp;+&nbsp;Session[\"QC_AccessToken\"];\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;url&nbsp;=&nbsp;GET_OPENID_URL&nbsp;+&nbsp;parms;\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;str&nbsp;=&nbsp;GetRequest(url);\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(str.IndexOf(\"callback\")&nbsp;!=&nbsp;-1)\r\n&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;lpos&nbsp;=&nbsp;str.IndexOf(\"(\");\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int&nbsp;rpos&nbsp;=&nbsp;str.IndexOf(\")\");\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;str&nbsp;=&nbsp;str.Substring(lpos&nbsp;+&nbsp;1,&nbsp;rpos&nbsp;-&nbsp;lpos&nbsp;-&nbsp;1);\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;NameValueCollection&nbsp;user&nbsp;=&nbsp;ParseJson(str);\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!string.IsNullOrEmpty(user[\"error\"]))\r\n&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ShowError(user[\"error\"],&nbsp;user[\"error_description\"]);\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;Session[\"QC_OpenId\"]&nbsp;=&nbsp;user[\"openid\"];&nbsp;\/\/openid&nbsp;\u653e\u5165Session\r\n&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;user[\"openid\"];\r\n&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;\u663e\u793a\u9519\u8bef\u4fe1\u606f\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;\/summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;param&gt;\u9519\u8bef\u7f16\u53f7\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;param&gt;\u9519\u8bef\u63cf\u8ff0\r\n&nbsp;&nbsp;private&nbsp;void&nbsp;ShowError(string&nbsp;code,&nbsp;string&nbsp;description&nbsp;=&nbsp;null)\r\n&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(description&nbsp;==&nbsp;null)\r\n&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;switch&nbsp;(code)\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;\"20001\":\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;description&nbsp;=&nbsp;\"&lt;h2&gt;\u914d\u7f6e\u6587\u4ef6\u635f\u574f\u6216\u65e0\u6cd5\u8bfb\u53d6\uff0c\u8bf7\u68c0\u67e5web.config&lt;\/h2&gt;\";\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;\"30001\":\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;description&nbsp;=&nbsp;\"&lt;h2&gt;The&nbsp;state&nbsp;does&nbsp;not&nbsp;match.&nbsp;You&nbsp;may&nbsp;be&nbsp;a&nbsp;victim&nbsp;of&nbsp;CSRF.&lt;\/h2&gt;\";\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;\"50001\":\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;description&nbsp;=&nbsp;\"&lt;h2&gt;\u53ef\u80fd\u662f\u670d\u52a1\u5668\u65e0\u6cd5\u8bf7\u6c42https\u534f\u8bae&lt;\/h2&gt;\u53ef\u80fd\u672a\u5f00\u542fcurl\u652f\u6301,\u8bf7\u5c1d\u8bd5\u5f00\u542fcurl\u652f\u6301\uff0c\u91cd\u542fweb\u670d\u52a1\u5668\uff0c\u5982\u679c\u95ee\u9898\u4ecd\u672a\u89e3\u51b3\uff0c\u8bf7\u8054\u7cfb\u6211\u4eec\";\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;default:\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;description&nbsp;=&nbsp;\"&lt;h2&gt;\u7cfb\u7edf\u672a\u77e5\u9519\u8bef\uff0c\u8bf7\u8054\u7cfb\u6211\u4eec&lt;\/h2&gt;\";\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Response.Write(description);\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Response.End();\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&nbsp;else\r\n&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Response.Write(\"&lt;h3&gt;error:&lt;h3&gt;\"&nbsp;+&nbsp;code&nbsp;+&nbsp;\"&lt;h3&gt;msg:&lt;h3&gt;\"&nbsp;+&nbsp;description);\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Response.End();\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;}\r\n\r\n}&lt;\/h3&gt;\n&lt;\/h3&gt;\n&lt;\/h3&gt;\n&lt;\/h3&gt;<\/pre>\n<p>  \u767b\u5f55\u540e\u590d\u5236   <\/p>\n<p><strong>3.\u65b0\u6d6a\u5fae\u535a\u7684OAuth\u7c7b<\/strong><\/p>\n<pre>public&nbsp;class&nbsp;SinaOAuth&nbsp;:&nbsp;BaseOAuth\r\n{\r\n&nbsp;&nbsp;public&nbsp;string&nbsp;AppKey&nbsp;=&nbsp;ConfigurationManager.AppSettings[\"OAuth_Sina_AppKey\"];\r\n&nbsp;&nbsp;public&nbsp;string&nbsp;AppSecret&nbsp;=&nbsp;ConfigurationManager.AppSettings[\"OAuth_Sina_AppSecret\"];\r\n&nbsp;&nbsp;public&nbsp;string&nbsp;RedirectUrl&nbsp;=&nbsp;ConfigurationManager.AppSettings[\"OAuth_Sina_RedirectUrl\"];\r\n\r\n&nbsp;&nbsp;public&nbsp;const&nbsp;string&nbsp;GET_AUTH_CODE_URL&nbsp;=&nbsp;\"https:\/\/api.weibo.com\/oauth2\/authorize\";\r\n&nbsp;&nbsp;public&nbsp;const&nbsp;string&nbsp;GET_ACCESS_TOKEN_URL&nbsp;=&nbsp;\"https:\/\/api.weibo.com\/oauth2\/access_token\";\r\n&nbsp;&nbsp;public&nbsp;const&nbsp;string&nbsp;GET_UID_URL&nbsp;=&nbsp;\"https:\/\/api.weibo.com\/2\/account\/get_uid.json\";\r\n\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;\u65b0\u6d6a\u5fae\u535a\u767b\u5f55\uff0c\u8df3\u8f6c\u5230\u767b\u5f55\u9875\u9762\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;\/summary&gt;\r\n&nbsp;&nbsp;public&nbsp;override&nbsp;void&nbsp;Login()\r\n&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;\/\/-------\u751f\u6210\u552f\u4e00\u968f\u673a\u4e32\u9632CSRF\u653b\u51fb\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;state&nbsp;=&nbsp;GetStateCode();\r\n&nbsp;&nbsp;&nbsp;&nbsp;Session[\"Sina_State\"]&nbsp;=&nbsp;state;&nbsp;\/\/state&nbsp;\u653e\u5165Session\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;parms&nbsp;=&nbsp;\"?client_id=\"&nbsp;+&nbsp;AppKey&nbsp;+&nbsp;\"&amp;amp;redirect_uri=\"&nbsp;+&nbsp;Uri.EscapeDataString(RedirectUrl)\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+&nbsp;\"&amp;amp;state=\"&nbsp;+&nbsp;state;\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;url&nbsp;=&nbsp;GET_AUTH_CODE_URL&nbsp;+&nbsp;parms;\r\n&nbsp;&nbsp;&nbsp;&nbsp;Response.Redirect(url);&nbsp;\/\/\u8df3\u8f6c\u5230\u767b\u5f55\u9875\u9762\r\n&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;\u65b0\u6d6a\u5fae\u535a\u56de\u8c03\u51fd\u6570\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;\/summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;returns&gt;&lt;\/returns&gt;\r\n&nbsp;&nbsp;public&nbsp;override&nbsp;string&nbsp;Callback()\r\n&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;code&nbsp;=&nbsp;Request.QueryString[\"code\"];\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;state&nbsp;=&nbsp;Request.QueryString[\"state\"];\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;\/\/--------\u9a8c\u8bc1state\u9632\u6b62CSRF\u653b\u51fb\r\n&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(state&nbsp;!=&nbsp;(string)Session[\"Sina_State\"])\r\n&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ShowError(\"The&nbsp;state&nbsp;does&nbsp;not&nbsp;match.&nbsp;You&nbsp;may&nbsp;be&nbsp;a&nbsp;victim&nbsp;of&nbsp;CSRF.\");\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;parms&nbsp;=&nbsp;\"client_id=\"&nbsp;+&nbsp;AppKey&nbsp;+&nbsp;\"&amp;amp;client_secret=\"&nbsp;+&nbsp;AppSecret\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+&nbsp;\"&amp;amp;grant_type=authorization_code&amp;amp;code=\"&nbsp;+&nbsp;code&nbsp;+&nbsp;\"&amp;amp;redirect_uri=\"&nbsp;+&nbsp;Uri.EscapeDataString(RedirectUrl);\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;str&nbsp;=&nbsp;PostRequest(GET_ACCESS_TOKEN_URL,&nbsp;parms);\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;NameValueCollection&nbsp;user&nbsp;=&nbsp;ParseJson(str);\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;Session[\"Sina_AccessToken\"]&nbsp;=&nbsp;user[\"access_token\"];&nbsp;\/\/access_token&nbsp;\u653e\u5165Session\r\n&nbsp;&nbsp;&nbsp;&nbsp;Session[\"Sina_UId\"]&nbsp;=&nbsp;user[\"uid\"];&nbsp;\/\/uid&nbsp;\u653e\u5165Session\r\n&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;user[\"access_token\"];\r\n&nbsp;&nbsp;}\r\n\r\n\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;\u663e\u793a\u9519\u8bef\u4fe1\u606f\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;\/summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;param&gt;\u9519\u8bef\u63cf\u8ff0\r\n&nbsp;&nbsp;private&nbsp;void&nbsp;ShowError(string&nbsp;description&nbsp;=&nbsp;null)\r\n&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;Response.Write(\"&lt;h2&gt;\"&nbsp;+&nbsp;description&nbsp;+&nbsp;\"&lt;\/h2&gt;\");\r\n&nbsp;&nbsp;&nbsp;&nbsp;Response.End();\r\n&nbsp;&nbsp;}\r\n}<\/pre>\n<p>  \u767b\u5f55\u540e\u590d\u5236   <\/p>\n<p><strong>4.\u5fae\u4fe1\u7684OAuth\u7c7b<\/strong><\/p>\n<pre>public&nbsp;class&nbsp;WeixinOAuth&nbsp;:&nbsp;BaseOAuth\r\n{\r\n&nbsp;&nbsp;public&nbsp;string&nbsp;AppId&nbsp;=&nbsp;ConfigurationManager.AppSettings[\"OAuth_Weixin_AppId\"];\r\n&nbsp;&nbsp;public&nbsp;string&nbsp;AppSecret&nbsp;=&nbsp;ConfigurationManager.AppSettings[\"OAuth_Weixin_AppSecret\"];\r\n&nbsp;&nbsp;public&nbsp;string&nbsp;RedirectUrl&nbsp;=&nbsp;ConfigurationManager.AppSettings[\"OAuth_Weixin_RedirectUrl\"];\r\n\r\n&nbsp;&nbsp;public&nbsp;const&nbsp;string&nbsp;GET_AUTH_CODE_URL&nbsp;=&nbsp;\"https:\/\/open.weixin.qq.com\/connect\/qrconnect\";\r\n&nbsp;&nbsp;public&nbsp;const&nbsp;string&nbsp;GET_ACCESS_TOKEN_URL&nbsp;=&nbsp;\"https:\/\/api.weixin.qq.com\/sns\/oauth2\/access_token\";\r\n&nbsp;&nbsp;public&nbsp;const&nbsp;string&nbsp;GET_USERINFO_URL&nbsp;=&nbsp;\"https:\/\/api.weixin.qq.com\/sns\/userinfo\";\r\n\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;\u5fae\u4fe1\u767b\u5f55\uff0c\u8df3\u8f6c\u5230\u767b\u5f55\u9875\u9762\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;\/summary&gt;\r\n&nbsp;&nbsp;public&nbsp;override&nbsp;void&nbsp;Login()\r\n&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;\/\/-------\u751f\u6210\u552f\u4e00\u968f\u673a\u4e32\u9632CSRF\u653b\u51fb\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;state&nbsp;=&nbsp;GetStateCode();\r\n&nbsp;&nbsp;&nbsp;&nbsp;Session[\"Weixin_State\"]&nbsp;=&nbsp;state;&nbsp;\/\/state&nbsp;\u653e\u5165Session\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;parms&nbsp;=&nbsp;\"?appid=\"&nbsp;+&nbsp;AppId\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+&nbsp;\"&amp;amp;redirect_uri=\"&nbsp;+&nbsp;Uri.EscapeDataString(RedirectUrl)&nbsp;+&nbsp;\"&amp;amp;response_type=code&amp;amp;scope=snsapi_login\"\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+&nbsp;\"&amp;amp;state=\"&nbsp;+&nbsp;state&nbsp;+&nbsp;\"#wechat_redirect\";\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;url&nbsp;=&nbsp;GET_AUTH_CODE_URL&nbsp;+&nbsp;parms;\r\n&nbsp;&nbsp;&nbsp;&nbsp;Response.Redirect(url);&nbsp;\/\/\u8df3\u8f6c\u5230\u767b\u5f55\u9875\u9762\r\n&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;\u5fae\u4fe1\u56de\u8c03\u51fd\u6570\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;\/summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;param&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;param&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;returns&gt;&lt;\/returns&gt;\r\n&nbsp;&nbsp;public&nbsp;override&nbsp;string&nbsp;Callback()\r\n&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;code&nbsp;=&nbsp;Request.QueryString[\"code\"];\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;state&nbsp;=&nbsp;Request.QueryString[\"state\"];\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;\/\/--------\u9a8c\u8bc1state\u9632\u6b62CSRF\u653b\u51fb\r\n&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(state&nbsp;!=&nbsp;(string)Session[\"Weixin_State\"])\r\n&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ShowError(\"30001\");\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;parms&nbsp;=&nbsp;\"?appid=\"&nbsp;+&nbsp;AppId&nbsp;+&nbsp;\"&amp;amp;secret=\"&nbsp;+&nbsp;AppSecret\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;+&nbsp;\"&amp;amp;code=\"&nbsp;+&nbsp;code&nbsp;+&nbsp;\"&amp;amp;grant_type=authorization_code\";\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;url&nbsp;=&nbsp;GET_ACCESS_TOKEN_URL&nbsp;+&nbsp;parms;\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;str&nbsp;=&nbsp;GetRequest(url);\r\n\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;NameValueCollection&nbsp;msg&nbsp;=&nbsp;ParseJson(str);\r\n&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!string.IsNullOrEmpty(msg[\"errcode\"]))\r\n&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ShowError(msg[\"errcode\"],&nbsp;msg[\"errmsg\"]);\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;Session[\"Weixin_AccessToken\"]&nbsp;=&nbsp;msg[\"access_token\"];&nbsp;\/\/access_token&nbsp;\u653e\u5165Session\r\n&nbsp;&nbsp;&nbsp;&nbsp;Session[\"Weixin_OpenId\"]&nbsp;=&nbsp;msg[\"openid\"];&nbsp;\/\/access_token&nbsp;\u653e\u5165Session\r\n&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;msg[\"access_token\"];\r\n&nbsp;&nbsp;}\r\n\r\n\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;\u663e\u793a\u9519\u8bef\u4fe1\u606f\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;\/summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;param&gt;\u9519\u8bef\u7f16\u53f7\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;param&gt;\u9519\u8bef\u63cf\u8ff0\r\n&nbsp;&nbsp;private&nbsp;void&nbsp;ShowError(string&nbsp;code,&nbsp;string&nbsp;description&nbsp;=&nbsp;null)\r\n&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(description&nbsp;==&nbsp;null)\r\n&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;switch&nbsp;(code)\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;\"20001\":\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;description&nbsp;=&nbsp;\"&lt;h2&gt;\u914d\u7f6e\u6587\u4ef6\u635f\u574f\u6216\u65e0\u6cd5\u8bfb\u53d6\uff0c\u8bf7\u68c0\u67e5web.config&lt;\/h2&gt;\";\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;\"30001\":\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;description&nbsp;=&nbsp;\"&lt;h2&gt;The&nbsp;state&nbsp;does&nbsp;not&nbsp;match.&nbsp;You&nbsp;may&nbsp;be&nbsp;a&nbsp;victim&nbsp;of&nbsp;CSRF.&lt;\/h2&gt;\";\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case&nbsp;\"50001\":\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;description&nbsp;=&nbsp;\"&lt;h2&gt;\u63a5\u53e3\u672a\u6388\u6743&lt;\/h2&gt;\";\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;default:\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;description&nbsp;=&nbsp;\"&lt;h2&gt;\u7cfb\u7edf\u672a\u77e5\u9519\u8bef\uff0c\u8bf7\u8054\u7cfb\u6211\u4eec&lt;\/h2&gt;\";\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Response.Write(description);\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Response.End();\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&nbsp;else\r\n&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Response.Write(\"&lt;h3&gt;error:&lt;h3&gt;\"&nbsp;+&nbsp;code&nbsp;+&nbsp;\"&lt;h3&gt;msg:&lt;h3&gt;\"&nbsp;+&nbsp;description);\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Response.End();\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;}\r\n\r\n}&lt;\/h3&gt;\n&lt;\/h3&gt;\n&lt;\/h3&gt;\n&lt;\/h3&gt;<\/pre>\n<p>  \u767b\u5f55\u540e\u590d\u5236   <\/p>\n<p><strong>5.web.config\u914d\u7f6e\u4fe1\u606f<\/strong><\/p>\n<pre>&lt;appsettings&gt;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--QQ\u767b\u5f55\u76f8\u5173\u914d\u7f6e--&gt;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&lt;add&gt;&lt;\/add&gt;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&lt;add&gt;&lt;\/add&gt;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&lt;add&gt;&lt;\/add&gt;\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--\u65b0\u6d6a\u5fae\u535a\u767b\u5f55\u76f8\u5173\u914d\u7f6e--&gt;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&lt;add&gt;&lt;\/add&gt;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&lt;add&gt;&lt;\/add&gt;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&lt;add&gt;&lt;\/add&gt;\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;&lt;!--\u5fae\u4fe1\u767b\u5f55\u76f8\u5173\u914d\u7f6e--&gt;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&lt;add&gt;&lt;\/add&gt;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&lt;add&gt;&lt;\/add&gt;\r\n&nbsp;&nbsp;&nbsp;&nbsp;&lt;add&gt;&lt;\/add&gt;&lt;\/appsettings&gt;<\/pre>\n<p>  \u767b\u5f55\u540e\u590d\u5236   <\/p>\n<p>\u4ee5\u4e0a\u5c31\u662fASP.NET\u5b9e\u73b0QQ\u3001\u5fae\u4fe1\u3001\u65b0\u6d6a\u5fae\u535aOAuth2.0\u6388\u6743\u767b\u5f55\u7684\u5b9e\u4f8b\u8be6\u89e3\u7684\u8be6\u7ec6\u5185\u5bb9\uff0c\u66f4\u591a\u8bf7\u5173\u6ce8\u7c73\u4e91\u5176\u5b83\u76f8\u5173\u6587\u7ae0\uff01<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u672c\u6587\u4e3b\u8981\u4ecb\u7ecd\u4e86qq\u3001\u5fae\u4fe1\u3001\u65b0\u6d6a\u5fae\u535aoauth2.0\u6388\u6743\u767b\u5f55\u7684\u793a\u4f8b\uff0c\u4e3b\u8981\u5c31\u662fget\u3001post\u8fdc\u7a0b\u63a5\u53e3\uff0c\u8fd4\u56de\u76f8\u5e94\u7684\u6570\u636e\uff0c\u8fd9\u91cc\u5217\u51fa\u76f8\u5173\u7684\u4ee3\u7801\uff0c\u4f9b\u5927\u5bb6\u53c2\u8003\u3002 \u4e0d\u7ba1\u662f\u817e\u8baf\u8fd8\u662f\u65b0\u6d6a\uff0c\u67e5\u770b\u4ed6\u4eec\u7684API\uff0cPHP\u90fd\u662f\u6709\u5b8c\u6574\u7684\u63a5\u53e3\uff0c\u4f46\u5bf9C#\u652f\u6301\u4f3c\u4e4e\u90fd\u4e0d\u662f\u90a3\u4e48\u5b8c\u5584\uff0c\u90fd\u6ca1\u6709\uff0c\u817e\u8baf\u662f\u5b8c\u5168\u6ca1\u6709\uff0c\u65b0\u6d6a\u662f\u63d0\u4f9b\u7b2c\u4e09\u65b9\u7684\uff0c\u800c\u4e14\u540e\u671f\u8fd8\u4e0d\u4e00\u5b9a\u5347\u7ea7\uff0cNND\uff0c\u7528\u7b2c\u4e09\u65b9\u7684\u52a8\u8f84\u5c31\u4e00\u4e2a\u7c7b\u5e93\uff0c\u5404\u79cd\u914d\u7f6e\u8fd8\u5fc5\u987b\u6309\u7167\u4ed6\u4eec\u7ea6\u5b9a\u7684\u5199\uff0c\u70e6\u800c\u4e14\u4e71\uff0c\u7d22\u6027\u81ea\u5df1\u5199\uff0c\u540e\u671f\u7684\u6269\u5c55\u4e5f\u5bb9\u6613\uff0c\u770b\u8fc7\u63a5\u53e3\u540e\uff0c\u5f00\u59cb\u4ee5\u4e3a\u5f88\u96be\uff0c\u53c2\u8003\u4e86\u51e0\u4e2a\u6e90\u7801\u4e4b\u540e\u53d1\u73b0\u4e5f\u4e0d\u662f\u90a3\u4e48\u96be\uff0c\u65e0\u975e\u662fGET\u6216POST\u8bf7\u6c42\u4ed6\u4eec\u7684\u63a5\u53e3\u83b7\u53d6\u8fd4\u56de\u503c\u4e4b\u7c7b\u7684\uff0c\u8bdd\u4e0d\u591a\u8bf4\uff0c\u8fd9\u91cc\u53ea\u63d0\u4f9b\u51e0\u4e2a\u4ee3\u7801\u5171\u53c2\u8003\uff0c\u629b\u7816\u5f15\u7389\u4e86\u3002\u3002\u3002 \u6211\u8fd9\u4e2a\u5199\u6cd5\u7684\u7279\u70b9\u662f\uff0c\u7528\u5230\u4e86Session\uff0c\u4f7f\u7528\u5bf9\u8c61\u5b9e\u4f8b\u5316\u4e4b\u540e\u8c03\u7528 Login() \u8df3\u8f6c\u5230\u767b\u5f55\u9875\u9762\uff0c\u5728\u56de\u8c03\u9875\u9762\u8c03\u7528Callback() \u6267\u884c\u4e4b\u540e\uff0c\u53ef\u4ee5\u4eceSession\u4e5f\u53ef\u4ee5\u5199\u72ec\u7acb\u7684\u51fd\u6570\uff08\u5982\uff1aGetOpenID()\uff09\u4e2d\u83b7\u53d6access_token\u6216\u7528\u6237\u7684\u552f\u4e00\u6807\u8bc6\uff0c\u4ee5\u65b9\u4fbf\u505a\u4e0b\u4e00\u6b65\u7684\u64cd\u4f5c\u3002\u6240\u8c13\u7ed1\u5b9a\u5c31\u662f\u628a\u7528\u6237\u7684\u552f\u4e00\u6807\u8bc6\u53d6\u51fa\uff0c\u63d2\u5165\u6570\u636e\u5e93\uff0c\u548c\u5e10\u53f7\u7ed1\u5b9a\u8d77\u6765\u3002 1.\u9996\u5148\u662f\u6240\u6709OAuth\u7c7b\u7684\u57fa\u7c7b\uff0c\u653e\u4e00\u4e9b\u9700\u8981\u516c\u7528\u7684\u65b9\u6cd5 public&nbsp;abstract&nbsp;class&nbsp;BaseOAuth { &nbsp;&nbsp;public&nbsp;HttpRequest&nbsp;Request&nbsp;=&nbsp;HttpContext.Current.Request; &nbsp;&nbsp;public&nbsp;HttpResponse&nbsp;Response&nbsp;=&nbsp;HttpContext.Current.Response; &nbsp;&nbsp;public&nbsp;HttpSessionState&nbsp;Session&nbsp;=&nbsp;HttpContext.Current.Session; &nbsp;&nbsp;public&nbsp;abstract&nbsp;void&nbsp;Login(); &nbsp;&nbsp;public&nbsp;abstract&nbsp;string&nbsp;Callback(); &nbsp;&nbsp;#region&nbsp;\u5185\u90e8\u4f7f\u7528\u51fd\u6570 &nbsp;&nbsp;\/\/\/&nbsp;&lt;summary&gt; &nbsp;&nbsp;\/\/\/&nbsp;\u751f\u6210\u552f\u4e00\u968f\u673a\u4e32\u9632CSRF\u653b\u51fb &nbsp;&nbsp;\/\/\/&nbsp;&lt;\/summary&gt; &nbsp;&nbsp;\/\/\/&nbsp;&lt;returns&gt;&lt;\/returns&gt; &nbsp;&nbsp;protected&nbsp;string&nbsp;GetStateCode() &nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;Random&nbsp;rand&nbsp;=&nbsp;new&nbsp;Random(); &nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;data&nbsp;=&nbsp;DateTime.Now.ToString(&#8220;yyyyMMddHHmmssffff&#8221;)&nbsp;+&nbsp;rand.Next(1,&nbsp;0xf423f).ToString(); &nbsp;&nbsp;&nbsp;&nbsp;MD5CryptoServiceProvider&nbsp;md5&nbsp;=&nbsp;new&nbsp;MD5CryptoServiceProvider(); &nbsp;&nbsp;&nbsp;&nbsp;byte[]&nbsp;md5byte&nbsp;=&nbsp;md5.ComputeHash(UTF8Encoding.Default.GetBytes(data)); &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;BitConverter.ToString(md5byte).Replace(&#8220;-&#8220;,&nbsp;&#8220;&#8221;); &nbsp;&nbsp;} &nbsp;&nbsp;\/\/\/&nbsp;&lt;summary&gt; &nbsp;&nbsp;\/\/\/&nbsp;GET\u8bf7\u6c42 &nbsp;&nbsp;\/\/\/&nbsp;&lt;\/summary&gt; &nbsp;&nbsp;\/\/\/&nbsp;&lt;param&gt; &nbsp;&nbsp;\/\/\/&nbsp;&lt;returns&gt;&lt;\/returns&gt; &nbsp;&nbsp;protected&nbsp;string&nbsp;GetRequest(string&nbsp;url) &nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;HttpWebRequest&nbsp;httpWebRequest&nbsp;=&nbsp;System.Net.WebRequest.Create(url)&nbsp;as&nbsp;HttpWebRequest; &nbsp;&nbsp;&nbsp;&nbsp;httpWebRequest.Method&nbsp;=&nbsp;&#8220;GET&#8221;; &nbsp;&nbsp;&nbsp;&nbsp;httpWebRequest.ServicePoint.Expect100Continue&nbsp;=&nbsp;false; &nbsp;&nbsp;&nbsp;&nbsp;StreamReader&nbsp;responseReader&nbsp;=&nbsp;null; &nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;responseData; &nbsp;&nbsp;&nbsp;&nbsp;try &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;responseReader&nbsp;=&nbsp;new&nbsp;StreamReader(httpWebRequest.GetResponse().GetResponseStream()); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;responseData&nbsp;=&nbsp;responseReader.ReadToEnd(); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;finally &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;httpWebRequest.GetResponse().GetResponseStream().Close(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;responseReader.Close(); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;responseData; &nbsp;&nbsp;} &nbsp;&nbsp;\/\/\/&nbsp;&lt;summary&gt; &nbsp;&nbsp;\/\/\/&nbsp;POST\u8bf7\u6c42 &nbsp;&nbsp;\/\/\/&nbsp;&lt;\/summary&gt; &nbsp;&nbsp;\/\/\/&nbsp;&lt;param&gt; [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[19],"tags":[],"class_list":["post-29802","post","type-post","status-publish","format-standard","hentry","category-19"],"_links":{"self":[{"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/posts\/29802","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/comments?post=29802"}],"version-history":[{"count":0,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/posts\/29802\/revisions"}],"wp:attachment":[{"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/media?parent=29802"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/categories?post=29802"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/tags?post=29802"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}