您现在的位置是:网站首页> 编程资料编程资料

ASP.NET Core集成微信登录_实用技巧_

2023-05-24 313人已围观

简介 ASP.NET Core集成微信登录_实用技巧_

工具:

Visual Studio 2015 update 3

Asp.Net Core 1.0

1 准备工作

申请微信公众平台接口测试帐号,申请网址:(http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login)。申请接口测试号无需公众帐号,可以直接体验和测试公众平台所有高级接口。

1.1 配置接口信息

1.2 修改网页授权信息

点击“修改”后在弹出页面填入你的网站域名:

2 新建网站项目

2.1 选择ASP.NET Core Web Application 模板

2.2 选择Web 应用程序,并更改身份验证为个人用户账户

3 集成微信登录功能

3.1添加引用

打开project.json文件,添加引用Microsoft.AspNetCore.Authentication.OAuth

3.2 添加代码文件

在项目中新建文件夹,命名为WeChatOAuth,并添加代码文件(本文最后附全部代码)。

3.3 注册微信登录中间件

打开Startup.cs文件,在Configure中添加代码:

 app.UseWeChatAuthentication(new WeChatOptions() { AppId = "******", AppSecret = "******" }); 

注意该代码的插入位置必须在app.UseIdentity()下方。

4 代码

 // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using Microsoft.AspNetCore.Authentication.WeChat; using Microsoft.Extensions.Options; namespace Microsoft.AspNetCore.Builder { ///  /// Extension methods to add WeChat authentication capabilities to an HTTP application pipeline. ///  public static class WeChatAppBuilderExtensions { ///  /// Adds the  middleware to the specified , which enables WeChat authentication capabilities. ///  /// The  to add the middleware to. /// A reference to this instance after the operation has completed. public static IApplicationBuilder UseWeChatAuthentication(this IApplicationBuilder app) { if (app == null) { throw new ArgumentNullException(nameof(app)); } return app.UseMiddleware(); } ///  /// Adds the  middleware to the specified , which enables WeChat authentication capabilities. ///  /// The  to add the middleware to. /// A  that specifies options for the middleware. /// A reference to this instance after the operation has completed. public static IApplicationBuilder UseWeChatAuthentication(this IApplicationBuilder app, WeChatOptions options) { if (app == null) { throw new ArgumentNullException(nameof(app)); } if (options == null) { throw new ArgumentNullException(nameof(options)); } return app.UseMiddleware(Options.Create(options)); } } } 

WeChatDefaults.cs:

 // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. namespace Microsoft.AspNetCore.Authentication.WeChat { public static class WeChatDefaults { public const string AuthenticationScheme = "WeChat"; public static readonly string AuthorizationEndpoint = "https://open.weixin.qq.com/connect/oauth2/authorize"; public static readonly string TokenEndpoint = "https://api.weixin.qq.com/sns/oauth2/access_token"; public static readonly string UserInformationEndpoint = "https://api.weixin.qq.com/sns/userinfo"; } } 

WeChatHandler.cs

 // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.AspNetCore.Authentication.OAuth; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http.Authentication; using Microsoft.AspNetCore.Http.Extensions; using Microsoft.Extensions.Primitives; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Net.Http; using System.Net.Http.Headers; using System.Security.Claims; using System.Text; using Microsoft.AspNetCore.Mvc; using System.Threading.Tasks; namespace Microsoft.AspNetCore.Authentication.WeChat { internal class WeChatHandler : OAuthHandler { public WeChatHandler(HttpClient httpClient) : base(httpClient) { } protected override async Task HandleRemoteAuthenticateAsync() { AuthenticationProperties properties = null; var query = Request.Query; var error = query["error"]; if (!StringValues.IsNullOrEmpty(error)) { var failureMessage = new StringBuilder(); failureMessage.Append(error); var errorDescription = query["error_description"]; if (!StringValues.IsNullOrEmpty(errorDescription)) { failureMessage.Append(";Description=").Append(errorDescription); } var errorUri = query["error_uri"]; if (!StringValues.IsNullOrEmpty(errorUri)) { failureMessage.Append(";Uri=").Append(errorUri); } return AuthenticateResult.Fail(failureMessage.ToString()); } var code = query["code"]; var state = query["state"]; var oauthState = query["oauthstate"]; properties = Options.StateDataFormat.Unprotect(oauthState); if (state != Options.StateAddition || properties == null) { return AuthenticateResult.Fail("The oauth state was missing or invalid."); } // OAuth2 10.12 CSRF if (!ValidateCorrelationId(properties)) { return AuthenticateResult.Fail("Correlation failed."); } if (StringValues.IsNullOrEmpty(code)) { return AuthenticateResult.Fail("Code was not found."); } //获取tokens var tokens = await ExchangeCodeAsync(code, BuildRedirectUri(Options.CallbackPath)); var identity = new ClaimsIdentity(Options.ClaimsIssuer); AuthenticationTicket ticket = null; if (Options.WeChatScope == Options.InfoScope) { //获取用户信息 ticket = await CreateTicketAsync(identity, properties, tokens); } else { //不获取信息,只使用openid identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, tokens.TokenType, ClaimValueTypes.String, Options.ClaimsIssuer)); ticket = new AuthenticationTicket(new ClaimsPrincipal(identity), properties, Options.AuthenticationScheme); } if (ticket != null) { return AuthenticateResult.Success(ticket); } else { return AuthenticateResult.Fail("Failed to retrieve user information from remote server."); } } ///  /// OAuth第一步,获取code ///  ///  ///  ///  protected override string BuildChallengeUrl(AuthenticationProperties properties, string redirectUri) { //加密OAuth状态 var oauthstate = Options.StateDataFormat.Protect(properties); // redirectUri = $"{redirectUri}?{nameof(oauthstate)}={oauthstate}"; var queryBuilder = new QueryBuilder() { { "appid", Options.ClientId }, { "redirect_uri", redirectUri }, { "response_type", "code" }, { "scope", Options.WeChatScope }, { "state", Options.StateAddition }, }; return Options.AuthorizationEndpoint + queryBuilder.ToString(); } ///  /// OAuth第二步,获取token ///  ///  ///  ///  protected override async Task ExchangeCodeAsync(string code, string redirectUri) { var tokenRequestParameters = new Dictionary() { { "appid", Options.ClientId }, { "secret", Options.ClientSecret }, { "code", code }, { "grant_type", "authorization_code" }, }; var requestContent = new FormUrlEncodedContent(tokenRequestParameters); var requestMessage = new HttpRequestMessage(HttpMethod.Post, Options.TokenEndpoint); requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); requestMessage.Content = requestContent; var response = await Backchannel.SendAsync(requestMessage, Context.RequestAborted); if (response.IsSuccessStatusCode) { var payload = JObject.Parse(await response.Content.ReadAsStringAsync()); string ErrCode = payload.Value("errcode"); string ErrMsg = payload.Value("errmsg"); if (!string.IsNullOrEmpty(ErrCode) | !string.IsNullOrEmpty(ErrMsg)) { return OAuthTokenResponse.Failed(new Exception($"ErrCode:{ErrCode},ErrMsg:{ErrMsg}")); } var tokens = OAuthTokenResponse.Success(payload); //借用TokenType属性保存openid tokens.TokenType = payload.Value("openid"); return tokens; } else { var error = "OAuth token endpoint failure"; return OAuthTokenResponse.Failed(new Exception(error)); } } ///  /// OAuth第四步,获取用户信息 ///  ///  ///  ///  ///  protected override async Task CreateTicketAsync(ClaimsIdentity
                
                

-六神源码网