{"id":29840,"date":"2024-11-25T15:00:08","date_gmt":"2024-11-25T07:00:08","guid":{"rendered":"https:\/\/fwq.ai\/blog\/29840\/"},"modified":"2024-11-25T15:00:08","modified_gmt":"2024-11-25T07:00:08","slug":"asp-net-core%e9%9b%86%e6%88%90%e5%be%ae%e4%bf%a1%e7%99%bb%e5%bd%95%e7%9a%84%e5%ae%9e%e4%be%8b%e5%9b%be%e8%a7%a3","status":"publish","type":"post","link":"https:\/\/fwq.ai\/blog\/29840\/","title":{"rendered":"ASP.NET Core\u96c6\u6210\u5fae\u4fe1\u767b\u5f55\u7684\u5b9e\u4f8b\u56fe\u89e3"},"content":{"rendered":"<p>\u8fd9\u7bc7\u6587\u7ae0\u4e3b\u8981\u4ecb\u7ecd\u4e86asp.net core\u96c6\u6210\u767b\u5f55\u7684\u76f8\u5173\u8d44\u6599,\u5177\u6709\u4e00\u5b9a\u7684\u53c2\u8003\u4ef7\u503c\uff0c\u611f\u5174\u8da3\u7684\u5c0f\u4f19\u4f34\u4eec\u53ef\u4ee5\u53c2\u8003\u4e00\u4e0b<\/p>\n<p><strong>\u5de5\u5177\uff1a<\/strong><\/p>\n<p>Visual Studio 2015 update 3<\/p>\n<p>Asp.Net Core 1.0<\/p>\n<p><strong>1 \u51c6\u5907\u5de5\u4f5c<\/strong><\/p>\n<p>\u7533\u8bf7\u5fae\u4fe1\u516c\u4f17\u5e73\u53f0\u63a5\u53e3\u6d4b\u8bd5\u5e10\u53f7\uff0c\u7533\u8bf7\u7f51\u5740\uff1a\uff08mp.weixin.qq.com\/debug\/cgi-bin\/sandbox?t=sandbox\/login\uff09\u3002\u7533\u8bf7\u63a5\u53e3\u6d4b\u8bd5\u53f7\u65e0\u9700\u516c\u4f17\u5e10\u53f7\uff0c\u53ef\u4ee5\u76f4\u63a5\u4f53\u9a8c\u548c\u6d4b\u8bd5\u516c\u4f17\u5e73\u53f0\u6240\u6709\u9ad8\u7ea7\u63a5\u53e3\u3002<\/p>\n<p><span style=\"color: #800000\"><strong>1.1 \u914d\u7f6e\u63a5\u53e3\u4fe1\u606f<\/strong><\/span><\/p>\n<p style=\"text-align: center\"><img decoding=\"async\" src=\"https:\/\/img.php.cn\/upload\/article\/000\/001\/505\/f7778f78c0ef3e8d921696ee6a46b36e-0.png\" class=\"aligncenter\" title=\"ASP.NET Core\u96c6\u6210\u5fae\u4fe1\u767b\u5f55\u7684\u5b9e\u4f8b\u56fe\u89e3\u63d2\u56fe\" alt=\"ASP.NET Core\u96c6\u6210\u5fae\u4fe1\u767b\u5f55\u7684\u5b9e\u4f8b\u56fe\u89e3\u63d2\u56fe\" \/><\/p>\n<p><span style=\"color: #800000\"><strong>1.2 \u4fee\u6539\u7f51\u9875\u6388\u6743\u4fe1\u606f<\/strong><\/span><\/p>\n<p style=\"text-align: center\"><img decoding=\"async\" src=\"https:\/\/img.php.cn\/upload\/article\/000\/001\/505\/f7778f78c0ef3e8d921696ee6a46b36e-1.png\" class=\"aligncenter\" title=\"ASP.NET Core\u96c6\u6210\u5fae\u4fe1\u767b\u5f55\u7684\u5b9e\u4f8b\u56fe\u89e3\u63d2\u56fe1\" alt=\"ASP.NET Core\u96c6\u6210\u5fae\u4fe1\u767b\u5f55\u7684\u5b9e\u4f8b\u56fe\u89e3\u63d2\u56fe1\" \/><\/p>\n<p>\u70b9\u51fb\u201c\u4fee\u6539\u201d\u540e\u5728\u5f39\u51fa\u9875\u9762\u586b\u5165\u4f60\u7684\u7f51\u7ad9\u57df\u540d\uff1a<\/p>\n<p style=\"text-align: center\"><img decoding=\"async\" src=\"https:\/\/img.php.cn\/upload\/article\/000\/001\/505\/2513cc7b3376150b9b1cf71fce3ca5af-2.png\" class=\"aligncenter\" title=\"ASP.NET Core\u96c6\u6210\u5fae\u4fe1\u767b\u5f55\u7684\u5b9e\u4f8b\u56fe\u89e3\u63d2\u56fe2\" alt=\"ASP.NET Core\u96c6\u6210\u5fae\u4fe1\u767b\u5f55\u7684\u5b9e\u4f8b\u56fe\u89e3\u63d2\u56fe2\" \/><\/p>\n<p><strong>2 \u65b0\u5efa\u7f51\u7ad9\u9879\u76ee<\/strong><\/p>\n<p><span style=\"color: #800000\"><strong>2.1 \u9009\u62e9ASP.NET Core Web Application \u6a21\u677f<\/strong><\/span><\/p>\n<p style=\"text-align: center\"><img decoding=\"async\" src=\"https:\/\/img.php.cn\/upload\/article\/000\/001\/505\/2513cc7b3376150b9b1cf71fce3ca5af-3.png\" class=\"aligncenter\" title=\"ASP.NET Core\u96c6\u6210\u5fae\u4fe1\u767b\u5f55\u7684\u5b9e\u4f8b\u56fe\u89e3\u63d2\u56fe3\" alt=\"ASP.NET Core\u96c6\u6210\u5fae\u4fe1\u767b\u5f55\u7684\u5b9e\u4f8b\u56fe\u89e3\u63d2\u56fe3\" \/><\/p>\n<p><span style=\"color: #800000\"><strong>2.2 \u9009\u62e9Web \u5e94\u7528\u7a0b\u5e8f\uff0c\u5e76\u66f4\u6539\u8eab\u4efd\u9a8c\u8bc1\u4e3a\u4e2a\u4eba\u7528\u6237\u8d26\u6237<\/strong><\/span><\/p>\n<p style=\"text-align: center\"><img decoding=\"async\" src=\"https:\/\/img.php.cn\/upload\/article\/000\/001\/505\/89e4994a678d22bf1e25aa5dbd57f270-4.png\" class=\"aligncenter\" title=\"ASP.NET Core\u96c6\u6210\u5fae\u4fe1\u767b\u5f55\u7684\u5b9e\u4f8b\u56fe\u89e3\u63d2\u56fe4\" alt=\"ASP.NET Core\u96c6\u6210\u5fae\u4fe1\u767b\u5f55\u7684\u5b9e\u4f8b\u56fe\u89e3\u63d2\u56fe4\" \/><\/p>\n<p><strong>3 \u96c6\u6210\u5fae\u4fe1\u767b\u5f55\u529f\u80fd<\/strong><\/p>\n<p><strong>3.1\u6dfb\u52a0\u5f15\u7528<\/strong><\/p>\n<p>\u6253\u5f00project.json\u6587\u4ef6\uff0c\u6dfb\u52a0\u5f15\u7528Microsoft.AspNetCore.Authentication.OAuth<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/img.php.cn\/upload\/article\/000\/001\/505\/89e4994a678d22bf1e25aa5dbd57f270-5.png\" class=\"aligncenter\" title=\"ASP.NET Core\u96c6\u6210\u5fae\u4fe1\u767b\u5f55\u7684\u5b9e\u4f8b\u56fe\u89e3\u63d2\u56fe5\" alt=\"ASP.NET Core\u96c6\u6210\u5fae\u4fe1\u767b\u5f55\u7684\u5b9e\u4f8b\u56fe\u89e3\u63d2\u56fe5\" \/><\/p>\n<p><span style=\"color: #800000\"><strong>3.2 \u6dfb\u52a0\u4ee3\u7801\u6587\u4ef6<\/strong><\/span><\/p>\n<p>\u5728\u9879\u76ee\u4e2d\u65b0\u5efa\u6587\u4ef6\u5939\uff0c\u547d\u540d\u4e3aWeChatOAuth\uff0c\u5e76\u6dfb\u52a0\u4ee3\u7801\u6587\u4ef6\uff08\u672c\u6587\u6700\u540e\u9644\u5168\u90e8\u4ee3\u7801\uff09\u3002<\/p>\n<p style=\"text-align: center\"><img decoding=\"async\" src=\"https:\/\/img.php.cn\/upload\/article\/000\/001\/505\/5fcb5e5f19e63f123a85e7ec1000f63d-6.png\" class=\"aligncenter\" title=\"ASP.NET Core\u96c6\u6210\u5fae\u4fe1\u767b\u5f55\u7684\u5b9e\u4f8b\u56fe\u89e3\u63d2\u56fe6\" alt=\"ASP.NET Core\u96c6\u6210\u5fae\u4fe1\u767b\u5f55\u7684\u5b9e\u4f8b\u56fe\u89e3\u63d2\u56fe6\" \/><\/p>\n<p><span style=\"color: #800000\"><strong>3.3 \u6ce8\u518c\u5fae\u4fe1\u767b\u5f55\u4e2d\u95f4\u4ef6<\/strong><\/span><\/p>\n<p>\u6253\u5f00Startup.cs\u6587\u4ef6\uff0c\u5728Configure\u4e2d\u6dfb\u52a0\u4ee3\u7801\uff1a<\/p>\n<pre>app.UseWeChatAuthentication(new&nbsp;WeChatOptions()\r\n{\r\n&nbsp;AppId&nbsp;=&nbsp;\"******\",\r\n\r\n&nbsp;AppSecret&nbsp;=&nbsp;\"******\"\r\n\r\n});<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p>\u6ce8\u610f\u8be5\u4ee3\u7801\u7684\u63d2\u5165\u4f4d\u7f6e\u5fc5\u987b\u5728app.UseIdentity()\u4e0b\u65b9\u3002<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/img.php.cn\/upload\/article\/000\/001\/505\/5fcb5e5f19e63f123a85e7ec1000f63d-7.png\" class=\"aligncenter\" title=\"ASP.NET Core\u96c6\u6210\u5fae\u4fe1\u767b\u5f55\u7684\u5b9e\u4f8b\u56fe\u89e3\u63d2\u56fe7\" alt=\"ASP.NET Core\u96c6\u6210\u5fae\u4fe1\u767b\u5f55\u7684\u5b9e\u4f8b\u56fe\u89e3\u63d2\u56fe7\" \/><\/p>\n<p><span style=\"color: #800000\"><strong>4 \u4ee3\u7801<\/strong><\/span><\/p>\n<p><span>WeChatAppBuilderExtensions.cs<\/span>\uff1a<\/p>\n<pre>\/\/&nbsp;Copyright&nbsp;(c)&nbsp;.NET&nbsp;Foundation.&nbsp;All&nbsp;rights&nbsp;reserved.\r\n\/\/&nbsp;Licensed&nbsp;under&nbsp;the&nbsp;Apache&nbsp;License,&nbsp;Version&nbsp;2.0.&nbsp;See&nbsp;License.txt&nbsp;in&nbsp;the&nbsp;project&nbsp;root&nbsp;for&nbsp;license&nbsp;information.\r\n\r\nusing&nbsp;System;\r\nusing&nbsp;Microsoft.AspNetCore.Authentication.WeChat;\r\nusing&nbsp;Microsoft.Extensions.Options;\r\n\r\nnamespace&nbsp;Microsoft.AspNetCore.Builder\r\n{\r\n&nbsp;\/\/\/&nbsp;&lt;summary&gt;\r\n&nbsp;\/\/\/&nbsp;Extension&nbsp;methods&nbsp;to&nbsp;add&nbsp;WeChat&nbsp;authentication&nbsp;capabilities&nbsp;to&nbsp;an&nbsp;HTTP&nbsp;application&nbsp;pipeline.\r\n&nbsp;\/\/\/&nbsp;&lt;\/summary&gt;\r\n&nbsp;public&nbsp;static&nbsp;class&nbsp;WeChatAppBuilderExtensions\r\n&nbsp;{\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;Adds&nbsp;the&nbsp;&lt;see&gt;&lt;\/see&gt;&nbsp;middleware&nbsp;to&nbsp;the&nbsp;specified&nbsp;&lt;see&gt;&lt;\/see&gt;,&nbsp;which&nbsp;enables&nbsp;WeChat&nbsp;authentication&nbsp;capabilities.\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;\/summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;param&gt;The&nbsp;&lt;see&gt;&lt;\/see&gt;&nbsp;to&nbsp;add&nbsp;the&nbsp;middleware&nbsp;to.\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;returns&gt;A&nbsp;reference&nbsp;to&nbsp;this&nbsp;instance&nbsp;after&nbsp;the&nbsp;operation&nbsp;has&nbsp;completed.&lt;\/returns&gt;\r\n&nbsp;&nbsp;public&nbsp;static&nbsp;IApplicationBuilder&nbsp;UseWeChatAuthentication(this&nbsp;IApplicationBuilder&nbsp;app)\r\n&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;if&nbsp;(app&nbsp;==&nbsp;null)\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;ArgumentNullException(nameof(app));\r\n&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;return&nbsp;app.UseMiddleware&lt;wechatmiddleware&gt;();\r\n&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;Adds&nbsp;the&nbsp;&lt;see&gt;&lt;\/see&gt;&nbsp;middleware&nbsp;to&nbsp;the&nbsp;specified&nbsp;&lt;see&gt;&lt;\/see&gt;,&nbsp;which&nbsp;enables&nbsp;WeChat&nbsp;authentication&nbsp;capabilities.\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;\/summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;param&gt;The&nbsp;&lt;see&gt;&lt;\/see&gt;&nbsp;to&nbsp;add&nbsp;the&nbsp;middleware&nbsp;to.\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;param&gt;A&nbsp;&lt;see&gt;&lt;\/see&gt;&nbsp;that&nbsp;specifies&nbsp;options&nbsp;for&nbsp;the&nbsp;middleware.\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;returns&gt;A&nbsp;reference&nbsp;to&nbsp;this&nbsp;instance&nbsp;after&nbsp;the&nbsp;operation&nbsp;has&nbsp;completed.&lt;\/returns&gt;\r\n&nbsp;&nbsp;public&nbsp;static&nbsp;IApplicationBuilder&nbsp;UseWeChatAuthentication(this&nbsp;IApplicationBuilder&nbsp;app,&nbsp;WeChatOptions&nbsp;options)\r\n&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;if&nbsp;(app&nbsp;==&nbsp;null)\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;ArgumentNullException(nameof(app));\r\n&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;if&nbsp;(options&nbsp;==&nbsp;null)\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;ArgumentNullException(nameof(options));\r\n&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;return&nbsp;app.UseMiddleware&lt;wechatmiddleware&gt;(Options.Create(options));\r\n&nbsp;&nbsp;}\r\n&nbsp;}\r\n}&lt;\/wechatmiddleware&gt;&lt;\/wechatmiddleware&gt;<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p>WeChatDefaults.cs\uff1a<\/p>\n<pre>\/\/&nbsp;Copyright&nbsp;(c)&nbsp;.NET&nbsp;Foundation.&nbsp;All&nbsp;rights&nbsp;reserved.\r\n\/\/&nbsp;Licensed&nbsp;under&nbsp;the&nbsp;Apache&nbsp;License,&nbsp;Version&nbsp;2.0.&nbsp;See&nbsp;License.txt&nbsp;in&nbsp;the&nbsp;project&nbsp;root&nbsp;for&nbsp;license&nbsp;information.\r\n\r\nnamespace&nbsp;Microsoft.AspNetCore.Authentication.WeChat\r\n{\r\n&nbsp;public&nbsp;static&nbsp;class&nbsp;WeChatDefaults\r\n&nbsp;{\r\n&nbsp;&nbsp;public&nbsp;const&nbsp;string&nbsp;AuthenticationScheme&nbsp;=&nbsp;\"WeChat\";\r\n\r\n&nbsp;&nbsp;public&nbsp;static&nbsp;readonly&nbsp;string&nbsp;AuthorizationEndpoint&nbsp;=&nbsp;\"https:\/\/open.weixin.qq.com\/connect\/oauth2\/authorize\";\r\n\r\n&nbsp;&nbsp;public&nbsp;static&nbsp;readonly&nbsp;string&nbsp;TokenEndpoint&nbsp;=&nbsp;\"https:\/\/api.weixin.qq.com\/sns\/oauth2\/access_token\";\r\n\r\n&nbsp;&nbsp;public&nbsp;static&nbsp;readonly&nbsp;string&nbsp;UserInformationEndpoint&nbsp;=&nbsp;\"https:\/\/api.weixin.qq.com\/sns\/userinfo\";\r\n&nbsp;}\r\n}<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p>WeChatHandler.cs<\/p>\n<pre>\/\/&nbsp;Copyright&nbsp;(c)&nbsp;.NET&nbsp;Foundation.&nbsp;All&nbsp;rights&nbsp;reserved.\r\n\/\/&nbsp;Licensed&nbsp;under&nbsp;the&nbsp;Apache&nbsp;License,&nbsp;Version&nbsp;2.0.&nbsp;See&nbsp;License.txt&nbsp;in&nbsp;the&nbsp;project&nbsp;root&nbsp;for&nbsp;license&nbsp;information.\r\n\r\nusing&nbsp;Microsoft.AspNetCore.Authentication.OAuth;\r\nusing&nbsp;Microsoft.AspNetCore.Builder;\r\nusing&nbsp;Microsoft.AspNetCore.Http.Authentication;\r\nusing&nbsp;Microsoft.AspNetCore.Http.Extensions;\r\nusing&nbsp;Microsoft.Extensions.Primitives;\r\nusing&nbsp;Newtonsoft.Json.Linq;\r\nusing&nbsp;System;\r\nusing&nbsp;System.Collections.Generic;\r\nusing&nbsp;System.Net.Http;\r\nusing&nbsp;System.Net.Http.Headers;\r\nusing&nbsp;System.Security.Claims;\r\nusing&nbsp;System.Text;\r\nusing&nbsp;Microsoft.AspNetCore.Mvc;\r\nusing&nbsp;System.Threading.Tasks;\r\n\r\nnamespace&nbsp;Microsoft.AspNetCore.Authentication.WeChat\r\n{\r\n&nbsp;internal&nbsp;class&nbsp;WeChatHandler&nbsp;:&nbsp;OAuthHandler&lt;wechatoptions&gt;\r\n&nbsp;{\r\n&nbsp;&nbsp;public&nbsp;WeChatHandler(HttpClient&nbsp;httpClient)\r\n&nbsp;&nbsp;&nbsp;:&nbsp;base(httpClient)\r\n&nbsp;&nbsp;{\r\n&nbsp;&nbsp;}\r\n\r\n\r\n&nbsp;&nbsp;protected&nbsp;override&nbsp;async&nbsp;Task&lt;authenticateresult&gt;&nbsp;HandleRemoteAuthenticateAsync()\r\n&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;AuthenticationProperties&nbsp;properties&nbsp;=&nbsp;null;\r\n&nbsp;&nbsp;&nbsp;var&nbsp;query&nbsp;=&nbsp;Request.Query;\r\n\r\n&nbsp;&nbsp;&nbsp;var&nbsp;error&nbsp;=&nbsp;query[\"error\"];\r\n&nbsp;&nbsp;&nbsp;if&nbsp;(!StringValues.IsNullOrEmpty(error))\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;failureMessage&nbsp;=&nbsp;new&nbsp;StringBuilder();\r\n&nbsp;&nbsp;&nbsp;&nbsp;failureMessage.Append(error);\r\n&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;errorDescription&nbsp;=&nbsp;query[\"error_description\"];\r\n&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!StringValues.IsNullOrEmpty(errorDescription))\r\n&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;failureMessage.Append(\";Description=\").Append(errorDescription);\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;errorUri&nbsp;=&nbsp;query[\"error_uri\"];\r\n&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!StringValues.IsNullOrEmpty(errorUri))\r\n&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;failureMessage.Append(\";Uri=\").Append(errorUri);\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;AuthenticateResult.Fail(failureMessage.ToString());\r\n&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;var&nbsp;code&nbsp;=&nbsp;query[\"code\"];\r\n&nbsp;&nbsp;&nbsp;var&nbsp;state&nbsp;=&nbsp;query[\"state\"];\r\n&nbsp;&nbsp;&nbsp;var&nbsp;oauthState&nbsp;=&nbsp;query[\"oauthstate\"];\r\n\r\n&nbsp;&nbsp;&nbsp;properties&nbsp;=&nbsp;Options.StateDataFormat.Unprotect(oauthState);\r\n\r\n&nbsp;&nbsp;&nbsp;if&nbsp;(state&nbsp;!=&nbsp;Options.StateAddition&nbsp;||&nbsp;properties&nbsp;==&nbsp;null)\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;AuthenticateResult.Fail(\"The&nbsp;oauth&nbsp;state&nbsp;was&nbsp;missing&nbsp;or&nbsp;invalid.\");\r\n&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;\/\/&nbsp;OAuth2&nbsp;10.12&nbsp;CSRF\r\n&nbsp;&nbsp;&nbsp;if&nbsp;(!ValidateCorrelationId(properties))\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;AuthenticateResult.Fail(\"Correlation&nbsp;failed.\");\r\n&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;if&nbsp;(StringValues.IsNullOrEmpty(code))\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;AuthenticateResult.Fail(\"Code&nbsp;was&nbsp;not&nbsp;found.\");\r\n&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;\/\/\u83b7\u53d6tokens\r\n&nbsp;&nbsp;&nbsp;var&nbsp;tokens&nbsp;=&nbsp;await&nbsp;ExchangeCodeAsync(code,&nbsp;BuildRedirectUri(Options.CallbackPath));\r\n\r\n&nbsp;&nbsp;&nbsp;var&nbsp;identity&nbsp;=&nbsp;new&nbsp;ClaimsIdentity(Options.ClaimsIssuer);\r\n\r\n&nbsp;&nbsp;&nbsp;AuthenticationTicket&nbsp;ticket&nbsp;=&nbsp;null;\r\n\r\n&nbsp;&nbsp;&nbsp;if&nbsp;(Options.WeChatScope&nbsp;==&nbsp;Options.InfoScope)\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;\/\/\u83b7\u53d6\u7528\u6237\u4fe1\u606f\r\n&nbsp;&nbsp;&nbsp;&nbsp;ticket&nbsp;=&nbsp;await&nbsp;CreateTicketAsync(identity,&nbsp;properties,&nbsp;tokens);\r\n&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;else\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;\/\/\u4e0d\u83b7\u53d6\u4fe1\u606f\uff0c\u53ea\u4f7f\u7528openid\r\n&nbsp;&nbsp;&nbsp;&nbsp;identity.AddClaim(new&nbsp;Claim(ClaimTypes.NameIdentifier,&nbsp;tokens.TokenType,&nbsp;ClaimValueTypes.String,&nbsp;Options.ClaimsIssuer));\r\n&nbsp;&nbsp;&nbsp;&nbsp;ticket&nbsp;=&nbsp;new&nbsp;AuthenticationTicket(new&nbsp;ClaimsPrincipal(identity),&nbsp;properties,&nbsp;Options.AuthenticationScheme);\r\n&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;if&nbsp;(ticket&nbsp;!=&nbsp;null)\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;AuthenticateResult.Success(ticket);\r\n&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;else\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;AuthenticateResult.Fail(\"Failed&nbsp;to&nbsp;retrieve&nbsp;user&nbsp;information&nbsp;from&nbsp;remote&nbsp;server.\");\r\n&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;OAuth\u7b2c\u4e00\u6b65,\u83b7\u53d6code\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;override&nbsp;string&nbsp;BuildChallengeUrl(AuthenticationProperties&nbsp;properties,&nbsp;string&nbsp;redirectUri)\r\n&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;\/\/\u52a0\u5bc6OAuth\u72b6\u6001\r\n&nbsp;&nbsp;&nbsp;var&nbsp;oauthstate&nbsp;=&nbsp;Options.StateDataFormat.Protect(properties);\r\n\r\n&nbsp;&nbsp;&nbsp;\/\/\r\n&nbsp;&nbsp;&nbsp;redirectUri&nbsp;=&nbsp;$\"{redirectUri}?{nameof(oauthstate)}={oauthstate}\";\r\n\r\n&nbsp;&nbsp;&nbsp;var&nbsp;queryBuilder&nbsp;=&nbsp;new&nbsp;QueryBuilder()\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;\"appid\",&nbsp;Options.ClientId&nbsp;},\r\n&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;\"redirect_uri\",&nbsp;redirectUri&nbsp;},\r\n&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;\"response_type\",&nbsp;\"code\"&nbsp;},\r\n&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;\"scope\",&nbsp;Options.WeChatScope&nbsp;},&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;\r\n&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;\"state\",&nbsp;Options.StateAddition&nbsp;},\r\n&nbsp;&nbsp;&nbsp;};\r\n&nbsp;&nbsp;&nbsp;return&nbsp;Options.AuthorizationEndpoint&nbsp;+&nbsp;queryBuilder.ToString();\r\n&nbsp;&nbsp;}\r\n\r\n\r\n\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;OAuth\u7b2c\u4e8c\u6b65,\u83b7\u53d6token\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;override&nbsp;async&nbsp;Task&lt;oauthtokenresponse&gt;&nbsp;ExchangeCodeAsync(string&nbsp;code,&nbsp;string&nbsp;redirectUri)\r\n&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;var&nbsp;tokenRequestParameters&nbsp;=&nbsp;new&nbsp;Dictionary&lt;string&gt;()\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;\"appid\",&nbsp;Options.ClientId&nbsp;},\r\n&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;\"secret\",&nbsp;Options.ClientSecret&nbsp;},\r\n&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;\"code\",&nbsp;code&nbsp;},\r\n&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;\"grant_type\",&nbsp;\"authorization_code\"&nbsp;},\r\n&nbsp;&nbsp;&nbsp;};\r\n\r\n&nbsp;&nbsp;&nbsp;var&nbsp;requestContent&nbsp;=&nbsp;new&nbsp;FormUrlEncodedContent(tokenRequestParameters);\r\n\r\n&nbsp;&nbsp;&nbsp;var&nbsp;requestMessage&nbsp;=&nbsp;new&nbsp;HttpRequestMessage(HttpMethod.Post,&nbsp;Options.TokenEndpoint);\r\n&nbsp;&nbsp;&nbsp;requestMessage.Headers.Accept.Add(new&nbsp;MediaTypeWithQualityHeaderValue(\"application\/json\"));\r\n&nbsp;&nbsp;&nbsp;requestMessage.Content&nbsp;=&nbsp;requestContent;\r\n&nbsp;&nbsp;&nbsp;var&nbsp;response&nbsp;=&nbsp;await&nbsp;Backchannel.SendAsync(requestMessage,&nbsp;Context.RequestAborted);\r\n&nbsp;&nbsp;&nbsp;if&nbsp;(response.IsSuccessStatusCode)\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;payload&nbsp;=&nbsp;JObject.Parse(await&nbsp;response.Content.ReadAsStringAsync());\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;ErrCode&nbsp;=&nbsp;payload.Value&lt;string&gt;(\"errcode\");\r\n&nbsp;&nbsp;&nbsp;&nbsp;string&nbsp;ErrMsg&nbsp;=&nbsp;payload.Value&lt;string&gt;(\"errmsg\");\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(!string.IsNullOrEmpty(ErrCode)&nbsp;|&nbsp;!string.IsNullOrEmpty(ErrMsg))\r\n&nbsp;&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;OAuthTokenResponse.Failed(new&nbsp;Exception($\"ErrCode:{ErrCode},ErrMsg:{ErrMsg}\"));&nbsp;\r\n&nbsp;&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;tokens&nbsp;=&nbsp;OAuthTokenResponse.Success(payload);\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;\/\/\u501f\u7528TokenType\u5c5e\u6027\u4fdd\u5b58openid\r\n&nbsp;&nbsp;&nbsp;&nbsp;tokens.TokenType&nbsp;=&nbsp;payload.Value&lt;string&gt;(\"openid\");\r\n\r\n&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;tokens;\r\n&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;else\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;error&nbsp;=&nbsp;\"OAuth&nbsp;token&nbsp;endpoint&nbsp;failure\";\r\n&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;OAuthTokenResponse.Failed(new&nbsp;Exception(error));\r\n&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;OAuth\u7b2c\u56db\u6b65\uff0c\u83b7\u53d6\u7528\u6237\u4fe1\u606f\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;param&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;returns&gt;&lt;\/returns&gt;\r\n&nbsp;&nbsp;protected&nbsp;override&nbsp;async&nbsp;Task&lt;authenticationticket&gt;&nbsp;CreateTicketAsync(ClaimsIdentity&nbsp;identity,&nbsp;AuthenticationProperties&nbsp;properties,&nbsp;OAuthTokenResponse&nbsp;tokens)\r\n&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;var&nbsp;queryBuilder&nbsp;=&nbsp;new&nbsp;QueryBuilder()\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;\"access_token\",&nbsp;tokens.AccessToken&nbsp;},\r\n&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;\"openid\",&nbsp;tokens.TokenType&nbsp;},\/\/\u5728\u7b2c\u4e8c\u6b65\u4e2d\uff0copenid\u88ab\u5b58\u5165TokenType\u5c5e\u6027\r\n&nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;\"lang\",&nbsp;\"zh_CN\"&nbsp;}\r\n&nbsp;&nbsp;&nbsp;};\r\n\r\n&nbsp;&nbsp;&nbsp;var&nbsp;infoRequest&nbsp;=&nbsp;Options.UserInformationEndpoint&nbsp;+&nbsp;queryBuilder.ToString();\r\n\r\n&nbsp;&nbsp;&nbsp;var&nbsp;response&nbsp;=&nbsp;await&nbsp;Backchannel.GetAsync(infoRequest,&nbsp;Context.RequestAborted);\r\n&nbsp;&nbsp;&nbsp;if&nbsp;(!response.IsSuccessStatusCode)\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;HttpRequestException($\"Failed&nbsp;to&nbsp;retrieve&nbsp;WeChat&nbsp;user&nbsp;information&nbsp;({response.StatusCode})&nbsp;Please&nbsp;check&nbsp;if&nbsp;the&nbsp;authentication&nbsp;information&nbsp;is&nbsp;correct&nbsp;and&nbsp;the&nbsp;corresponding&nbsp;WeChat&nbsp;Graph&nbsp;API&nbsp;is&nbsp;enabled.\");\r\n&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;var&nbsp;user&nbsp;=&nbsp;JObject.Parse(await&nbsp;response.Content.ReadAsStringAsync());\r\n&nbsp;&nbsp;&nbsp;var&nbsp;ticket&nbsp;=&nbsp;new&nbsp;AuthenticationTicket(new&nbsp;ClaimsPrincipal(identity),&nbsp;properties,&nbsp;Options.AuthenticationScheme);\r\n&nbsp;&nbsp;&nbsp;var&nbsp;context&nbsp;=&nbsp;new&nbsp;OAuthCreatingTicketContext(ticket,&nbsp;Context,&nbsp;Options,&nbsp;Backchannel,&nbsp;tokens,&nbsp;user);\r\n\r\n&nbsp;&nbsp;&nbsp;var&nbsp;identifier&nbsp;=&nbsp;user.Value&lt;string&gt;(\"openid\");\r\n&nbsp;&nbsp;&nbsp;if&nbsp;(!string.IsNullOrEmpty(identifier))\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;identity.AddClaim(new&nbsp;Claim(ClaimTypes.NameIdentifier,&nbsp;identifier,&nbsp;ClaimValueTypes.String,&nbsp;Options.ClaimsIssuer));\r\n&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;var&nbsp;nickname&nbsp;=&nbsp;user.Value&lt;string&gt;(\"nickname\");\r\n&nbsp;&nbsp;&nbsp;if&nbsp;(!string.IsNullOrEmpty(nickname))\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;identity.AddClaim(new&nbsp;Claim(ClaimTypes.Name,&nbsp;nickname,&nbsp;ClaimValueTypes.String,&nbsp;Options.ClaimsIssuer));\r\n&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;var&nbsp;sex&nbsp;=&nbsp;user.Value&lt;string&gt;(\"sex\");\r\n&nbsp;&nbsp;&nbsp;if&nbsp;(!string.IsNullOrEmpty(sex))\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;identity.AddClaim(new&nbsp;Claim(\"urn:WeChat:sex\",&nbsp;sex,&nbsp;ClaimValueTypes.String,&nbsp;Options.ClaimsIssuer));\r\n&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;var&nbsp;country&nbsp;=&nbsp;user.Value&lt;string&gt;(\"country\");\r\n&nbsp;&nbsp;&nbsp;if&nbsp;(!string.IsNullOrEmpty(country))\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;identity.AddClaim(new&nbsp;Claim(ClaimTypes.Country,&nbsp;country,&nbsp;ClaimValueTypes.String,&nbsp;Options.ClaimsIssuer));\r\n&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;var&nbsp;province&nbsp;=&nbsp;user.Value&lt;string&gt;(\"province\");\r\n&nbsp;&nbsp;&nbsp;if&nbsp;(!string.IsNullOrEmpty(province))\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;identity.AddClaim(new&nbsp;Claim(ClaimTypes.StateOrProvince,&nbsp;province,&nbsp;ClaimValueTypes.String,&nbsp;Options.ClaimsIssuer));\r\n&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;var&nbsp;city&nbsp;=&nbsp;user.Value&lt;string&gt;(\"city\");\r\n&nbsp;&nbsp;&nbsp;if&nbsp;(!string.IsNullOrEmpty(city))\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;identity.AddClaim(new&nbsp;Claim(\"urn:WeChat:city\",&nbsp;city,&nbsp;ClaimValueTypes.String,&nbsp;Options.ClaimsIssuer));\r\n&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;var&nbsp;headimgurl&nbsp;=&nbsp;user.Value&lt;string&gt;(\"headimgurl\");\r\n&nbsp;&nbsp;&nbsp;if&nbsp;(!string.IsNullOrEmpty(headimgurl))\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;identity.AddClaim(new&nbsp;Claim(\"urn:WeChat:headimgurl\",&nbsp;headimgurl,&nbsp;ClaimValueTypes.String,&nbsp;Options.ClaimsIssuer));\r\n&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;var&nbsp;unionid&nbsp;=&nbsp;user.Value&lt;string&gt;(\"unionid\");\r\n&nbsp;&nbsp;&nbsp;if&nbsp;(!string.IsNullOrEmpty(unionid))\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;identity.AddClaim(new&nbsp;Claim(\"urn:WeChat:unionid\",&nbsp;unionid,&nbsp;ClaimValueTypes.String,&nbsp;Options.ClaimsIssuer));\r\n&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;await&nbsp;Options.Events.CreatingTicket(context);\r\n&nbsp;&nbsp;&nbsp;return&nbsp;context.Ticket;\r\n&nbsp;&nbsp;}\r\n&nbsp;}\r\n}&lt;\/string&gt;&lt;\/string&gt;&lt;\/string&gt;&lt;\/string&gt;&lt;\/string&gt;&lt;\/string&gt;&lt;\/string&gt;&lt;\/string&gt;&lt;\/authenticationticket&gt;&lt;\/string&gt;&lt;\/string&gt;&lt;\/string&gt;&lt;\/string&gt;&lt;\/oauthtokenresponse&gt;&lt;\/authenticateresult&gt;&lt;\/wechatoptions&gt;<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p>WeChatMiddleware.cs<\/p>\n<pre>\/\/&nbsp;Copyright&nbsp;(c)&nbsp;.NET&nbsp;Foundation.&nbsp;All&nbsp;rights&nbsp;reserved.\r\n\/\/&nbsp;Licensed&nbsp;under&nbsp;the&nbsp;Apache&nbsp;License,&nbsp;Version&nbsp;2.0.&nbsp;See&nbsp;License.txt&nbsp;in&nbsp;the&nbsp;project&nbsp;root&nbsp;for&nbsp;license&nbsp;information.\r\n\r\nusing&nbsp;System;\r\nusing&nbsp;System.Globalization;\r\nusing&nbsp;System.Text.Encodings.Web;\r\nusing&nbsp;Microsoft.AspNetCore.Authentication.OAuth;\r\nusing&nbsp;Microsoft.AspNetCore.Builder;\r\nusing&nbsp;Microsoft.AspNetCore.DataProtection;\r\nusing&nbsp;Microsoft.AspNetCore.Http;\r\nusing&nbsp;Microsoft.Extensions.Logging;\r\nusing&nbsp;Microsoft.Extensions.Options;\r\n\r\nnamespace&nbsp;Microsoft.AspNetCore.Authentication.WeChat\r\n{\r\n&nbsp;\/\/\/&nbsp;&lt;summary&gt;\r\n&nbsp;\/\/\/&nbsp;An&nbsp;ASP.NET&nbsp;Core&nbsp;middleware&nbsp;for&nbsp;authenticating&nbsp;users&nbsp;using&nbsp;WeChat.\r\n&nbsp;\/\/\/&nbsp;&lt;\/summary&gt;\r\n&nbsp;public&nbsp;class&nbsp;WeChatMiddleware&nbsp;:&nbsp;OAuthMiddleware&lt;wechatoptions&gt;\r\n&nbsp;{\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;Initializes&nbsp;a&nbsp;new&nbsp;&lt;see&gt;&lt;\/see&gt;.\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;\/summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;param&gt;The&nbsp;next&nbsp;middleware&nbsp;in&nbsp;the&nbsp;HTTP&nbsp;pipeline&nbsp;to&nbsp;invoke.\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;param&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;param&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;param&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;param&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;param&gt;Configuration&nbsp;options&nbsp;for&nbsp;the&nbsp;middleware.\r\n&nbsp;&nbsp;public&nbsp;WeChatMiddleware(\r\n&nbsp;&nbsp;&nbsp;RequestDelegate&nbsp;next,\r\n&nbsp;&nbsp;&nbsp;IDataProtectionProvider&nbsp;dataProtectionProvider,\r\n&nbsp;&nbsp;&nbsp;ILoggerFactory&nbsp;loggerFactory,\r\n&nbsp;&nbsp;&nbsp;UrlEncoder&nbsp;encoder,\r\n&nbsp;&nbsp;&nbsp;IOptions&lt;sharedauthenticationoptions&gt;&nbsp;sharedOptions,\r\n&nbsp;&nbsp;&nbsp;IOptions&lt;wechatoptions&gt;&nbsp;options)\r\n&nbsp;&nbsp;&nbsp;:&nbsp;base(next,&nbsp;dataProtectionProvider,&nbsp;loggerFactory,&nbsp;encoder,&nbsp;sharedOptions,&nbsp;options)\r\n&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;if&nbsp;(next&nbsp;==&nbsp;null)\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;ArgumentNullException(nameof(next));\r\n&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;if&nbsp;(dataProtectionProvider&nbsp;==&nbsp;null)\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;ArgumentNullException(nameof(dataProtectionProvider));\r\n&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;if&nbsp;(loggerFactory&nbsp;==&nbsp;null)\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;ArgumentNullException(nameof(loggerFactory));\r\n&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;if&nbsp;(encoder&nbsp;==&nbsp;null)\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;ArgumentNullException(nameof(encoder));\r\n&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;if&nbsp;(sharedOptions&nbsp;==&nbsp;null)\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;ArgumentNullException(nameof(sharedOptions));\r\n&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;if&nbsp;(options&nbsp;==&nbsp;null)\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;ArgumentNullException(nameof(options));\r\n&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;if&nbsp;(string.IsNullOrEmpty(Options.AppId))\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;ArgumentException(string.Format(CultureInfo.CurrentCulture,&nbsp;nameof(Options.AppId)));\r\n&nbsp;&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;&nbsp;if&nbsp;(string.IsNullOrEmpty(Options.AppSecret))\r\n&nbsp;&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;ArgumentException(string.Format(CultureInfo.CurrentCulture,&nbsp;nameof(Options.AppSecret)));\r\n&nbsp;&nbsp;&nbsp;}\r\n&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;Provides&nbsp;the&nbsp;&lt;see&gt;&lt;\/see&gt;&nbsp;object&nbsp;for&nbsp;processing&nbsp;authentication-related&nbsp;requests.\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;\/summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;returns&gt;An&nbsp;&lt;see&gt;&lt;\/see&gt;&nbsp;configured&nbsp;with&nbsp;the&nbsp;&lt;see&gt;&lt;\/see&gt;&nbsp;supplied&nbsp;to&nbsp;the&nbsp;constructor.&lt;\/returns&gt;\r\n&nbsp;&nbsp;protected&nbsp;override&nbsp;AuthenticationHandler&lt;wechatoptions&gt;&nbsp;CreateHandler()\r\n&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;return&nbsp;new&nbsp;WeChatHandler(Backchannel);\r\n&nbsp;&nbsp;}\r\n&nbsp;}\r\n}&lt;\/wechatoptions&gt;&lt;\/wechatoptions&gt;&lt;\/sharedauthenticationoptions&gt;&lt;\/wechatoptions&gt;<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p>WeChatOptions.cs<\/p>\n<pre>\/\/&nbsp;Copyright&nbsp;(c)&nbsp;.NET&nbsp;Foundation.&nbsp;All&nbsp;rights&nbsp;reserved.\r\n\/\/&nbsp;Licensed&nbsp;under&nbsp;the&nbsp;Apache&nbsp;License,&nbsp;Version&nbsp;2.0.&nbsp;See&nbsp;License.txt&nbsp;in&nbsp;the&nbsp;project&nbsp;root&nbsp;for&nbsp;license&nbsp;information.\r\n\r\nusing&nbsp;System.Collections.Generic;\r\nusing&nbsp;Microsoft.AspNetCore.Authentication.WeChat;\r\nusing&nbsp;Microsoft.AspNetCore.Http;\r\nusing&nbsp;Microsoft.AspNetCore.Identity;\r\n\r\nnamespace&nbsp;Microsoft.AspNetCore.Builder\r\n{\r\n&nbsp;\/\/\/&nbsp;&lt;summary&gt;\r\n&nbsp;\/\/\/&nbsp;Configuration&nbsp;options&nbsp;for&nbsp;&lt;see&gt;&lt;\/see&gt;.\r\n&nbsp;\/\/\/&nbsp;&lt;\/summary&gt;\r\n&nbsp;public&nbsp;class&nbsp;WeChatOptions&nbsp;:&nbsp;OAuthOptions\r\n&nbsp;{\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;Initializes&nbsp;a&nbsp;new&nbsp;&lt;see&gt;&lt;\/see&gt;.\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;\/summary&gt;\r\n&nbsp;&nbsp;public&nbsp;WeChatOptions()\r\n&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;AuthenticationScheme&nbsp;=&nbsp;WeChatDefaults.AuthenticationScheme;\r\n&nbsp;&nbsp;&nbsp;DisplayName&nbsp;=&nbsp;AuthenticationScheme;\r\n&nbsp;&nbsp;&nbsp;CallbackPath&nbsp;=&nbsp;new&nbsp;PathString(\"\/signin-wechat\");\r\n&nbsp;&nbsp;&nbsp;StateAddition&nbsp;=&nbsp;\"#wechat_redirect\";\r\n&nbsp;&nbsp;&nbsp;AuthorizationEndpoint&nbsp;=&nbsp;WeChatDefaults.AuthorizationEndpoint;\r\n&nbsp;&nbsp;&nbsp;TokenEndpoint&nbsp;=&nbsp;WeChatDefaults.TokenEndpoint;\r\n&nbsp;&nbsp;&nbsp;UserInformationEndpoint&nbsp;=&nbsp;WeChatDefaults.UserInformationEndpoint;\r\n&nbsp;&nbsp;&nbsp;\/\/SaveTokens&nbsp;=&nbsp;true;&nbsp;&nbsp;&nbsp;\r\n\r\n&nbsp;&nbsp;&nbsp;\/\/BaseScope&nbsp;\uff08\u4e0d\u5f39\u51fa\u6388\u6743\u9875\u9762\uff0c\u76f4\u63a5\u8df3\u8f6c\uff0c\u53ea\u80fd\u83b7\u53d6\u7528\u6237openid\uff09\uff0c\r\n&nbsp;&nbsp;&nbsp;\/\/InfoScope&nbsp;\uff08\u5f39\u51fa\u6388\u6743\u9875\u9762\uff0c\u53ef\u901a\u8fc7openid\u62ff\u5230\u6635\u79f0\u3001\u6027\u522b\u3001\u6240\u5728\u5730\u3002\u5e76\u4e14\uff0c\u5373\u4f7f\u5728\u672a\u5173\u6ce8\u7684\u60c5\u51b5\u4e0b\uff0c\u53ea\u8981\u7528\u6237\u6388\u6743\uff0c\u4e5f\u80fd\u83b7\u53d6\u5176\u4fe1\u606f\uff09\r\n&nbsp;&nbsp;&nbsp;WeChatScope&nbsp;=&nbsp;InfoScope;\r\n&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;\/\/&nbsp;WeChat&nbsp;uses&nbsp;a&nbsp;non-standard&nbsp;term&nbsp;for&nbsp;this&nbsp;field.\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;Gets&nbsp;or&nbsp;sets&nbsp;the&nbsp;WeChat-assigned&nbsp;appId.\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;\/summary&gt;\r\n&nbsp;&nbsp;public&nbsp;string&nbsp;AppId\r\n&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;get&nbsp;{&nbsp;return&nbsp;ClientId;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;set&nbsp;{&nbsp;ClientId&nbsp;=&nbsp;value;&nbsp;}\r\n&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;\/\/&nbsp;WeChat&nbsp;uses&nbsp;a&nbsp;non-standard&nbsp;term&nbsp;for&nbsp;this&nbsp;field.\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;summary&gt;\r\n&nbsp;&nbsp;\/\/\/&nbsp;Gets&nbsp;or&nbsp;sets&nbsp;the&nbsp;WeChat-assigned&nbsp;app&nbsp;secret.\r\n&nbsp;&nbsp;\/\/\/&nbsp;&lt;\/summary&gt;\r\n&nbsp;&nbsp;public&nbsp;string&nbsp;AppSecret\r\n&nbsp;&nbsp;{\r\n&nbsp;&nbsp;&nbsp;get&nbsp;{&nbsp;return&nbsp;ClientSecret;&nbsp;}\r\n&nbsp;&nbsp;&nbsp;set&nbsp;{&nbsp;ClientSecret&nbsp;=&nbsp;value;&nbsp;}\r\n&nbsp;&nbsp;}\r\n\r\n&nbsp;&nbsp;public&nbsp;string&nbsp;StateAddition&nbsp;{&nbsp;get;&nbsp;set;&nbsp;}\r\n&nbsp;&nbsp;public&nbsp;string&nbsp;WeChatScope&nbsp;{&nbsp;get;&nbsp;set;&nbsp;}\r\n\r\n&nbsp;&nbsp;public&nbsp;string&nbsp;BaseScope&nbsp;=&nbsp;\"snsapi_base\";\r\n\r\n&nbsp;&nbsp;public&nbsp;string&nbsp;InfoScope&nbsp;=&nbsp;\"snsapi_userinfo\";\r\n&nbsp;}\r\n}<\/pre>\n<p> \u767b\u5f55\u540e\u590d\u5236 <\/p>\n<p>\u4ee5\u4e0a\u5c31\u662fASP.NET Core\u96c6\u6210\u767b\u5f55\u7684\u5b9e\u4f8b\u56fe\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>\u8fd9\u7bc7\u6587\u7ae0\u4e3b\u8981\u4ecb\u7ecd\u4e86asp.net core\u96c6\u6210\u767b\u5f55\u7684\u76f8\u5173\u8d44\u6599,\u5177\u6709\u4e00\u5b9a\u7684\u53c2\u8003\u4ef7\u503c\uff0c\u611f\u5174\u8da3\u7684\u5c0f\u4f19\u4f34\u4eec\u53ef\u4ee5\u53c2\u8003\u4e00\u4e0b \u5de5\u5177\uff1a Visual Studio 2015 update 3 Asp.Net Core 1.0 1 \u51c6\u5907\u5de5\u4f5c \u7533\u8bf7\u5fae\u4fe1\u516c\u4f17\u5e73\u53f0\u63a5\u53e3\u6d4b\u8bd5\u5e10\u53f7\uff0c\u7533\u8bf7\u7f51\u5740\uff1a\uff08mp.weixin.qq.com\/debug\/cgi-bin\/sandbox?t=sandbox\/login\uff09\u3002\u7533\u8bf7\u63a5\u53e3\u6d4b\u8bd5\u53f7\u65e0\u9700\u516c\u4f17\u5e10\u53f7\uff0c\u53ef\u4ee5\u76f4\u63a5\u4f53\u9a8c\u548c\u6d4b\u8bd5\u516c\u4f17\u5e73\u53f0\u6240\u6709\u9ad8\u7ea7\u63a5\u53e3\u3002 1.1 \u914d\u7f6e\u63a5\u53e3\u4fe1\u606f 1.2 \u4fee\u6539\u7f51\u9875\u6388\u6743\u4fe1\u606f \u70b9\u51fb\u201c\u4fee\u6539\u201d\u540e\u5728\u5f39\u51fa\u9875\u9762\u586b\u5165\u4f60\u7684\u7f51\u7ad9\u57df\u540d\uff1a 2 \u65b0\u5efa\u7f51\u7ad9\u9879\u76ee 2.1 \u9009\u62e9ASP.NET Core Web Application \u6a21\u677f 2.2 \u9009\u62e9Web \u5e94\u7528\u7a0b\u5e8f\uff0c\u5e76\u66f4\u6539\u8eab\u4efd\u9a8c\u8bc1\u4e3a\u4e2a\u4eba\u7528\u6237\u8d26\u6237 3 \u96c6\u6210\u5fae\u4fe1\u767b\u5f55\u529f\u80fd 3.1\u6dfb\u52a0\u5f15\u7528 \u6253\u5f00project.json\u6587\u4ef6\uff0c\u6dfb\u52a0\u5f15\u7528Microsoft.AspNetCore.Authentication.OAuth 3.2 \u6dfb\u52a0\u4ee3\u7801\u6587\u4ef6 \u5728\u9879\u76ee\u4e2d\u65b0\u5efa\u6587\u4ef6\u5939\uff0c\u547d\u540d\u4e3aWeChatOAuth\uff0c\u5e76\u6dfb\u52a0\u4ee3\u7801\u6587\u4ef6\uff08\u672c\u6587\u6700\u540e\u9644\u5168\u90e8\u4ee3\u7801\uff09\u3002 3.3 \u6ce8\u518c\u5fae\u4fe1\u767b\u5f55\u4e2d\u95f4\u4ef6 \u6253\u5f00Startup.cs\u6587\u4ef6\uff0c\u5728Configure\u4e2d\u6dfb\u52a0\u4ee3\u7801\uff1a app.UseWeChatAuthentication(new&nbsp;WeChatOptions() { &nbsp;AppId&nbsp;=&nbsp;&#8220;******&#8221;, &nbsp;AppSecret&nbsp;=&nbsp;&#8220;******&#8221; }); \u767b\u5f55\u540e\u590d\u5236 \u6ce8\u610f\u8be5\u4ee3\u7801\u7684\u63d2\u5165\u4f4d\u7f6e\u5fc5\u987b\u5728app.UseIdentity()\u4e0b\u65b9\u3002 4 \u4ee3\u7801 WeChatAppBuilderExtensions.cs\uff1a \/\/&nbsp;Copyright&nbsp;(c)&nbsp;.NET&nbsp;Foundation.&nbsp;All&nbsp;rights&nbsp;reserved. \/\/&nbsp;Licensed&nbsp;under&nbsp;the&nbsp;Apache&nbsp;License,&nbsp;Version&nbsp;2.0.&nbsp;See&nbsp;License.txt&nbsp;in&nbsp;the&nbsp;project&nbsp;root&nbsp;for&nbsp;license&nbsp;information. using&nbsp;System; using&nbsp;Microsoft.AspNetCore.Authentication.WeChat; using&nbsp;Microsoft.Extensions.Options; [&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-29840","post","type-post","status-publish","format-standard","hentry","category-19"],"_links":{"self":[{"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/posts\/29840","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=29840"}],"version-history":[{"count":0,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/posts\/29840\/revisions"}],"wp:attachment":[{"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/media?parent=29840"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/categories?post=29840"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fwq.ai\/blog\/wp-json\/wp\/v2\/tags?post=29840"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}