


Illustration of an example of integrating WeChat login with ASP.NET Core
Apr 26, 2017 pm 02:49 PMThis article mainly introduces the relevant information about ASP.NET Core integrating WeChat login, which has certain reference value. Interested friends can refer to
Tools:
Visual Studio 2015 update 3
Asp.Net Core 1.0
1 Preparation
Apply for a WeChat public platform interface test account, Application URL: (mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login). No public account is required to apply for an interface test account, and you can directly experience and test all advanced interfaces of the public platform.
1.1 Configure interface information
##1.2 Modify web page authorization information
2 Create a new website project
2.1 Select the ASP.NET Core Web Application template
2.2 Select the Web application and change the authentication to a personal user account
3 Integrate WeChat login function
3.1 Add reference
Open the project.json file and add reference Microsoft.AspNetCore.Authentication.OAuth3.2 Add code files
Create a new folder in the project, name it WeChatOAuth, and add the code file (all codes are attached at the end of this article).3.3 Register WeChat login middleware
Open the Startup.cs file and add the code in Configure :app.UseWeChatAuthentication(new WeChatOptions() { AppId = "******", AppSecret = "******" });Note that the insertion position of this code must be below app.UseIdentity().
4 Code
##WeChatAppBuilderExtensions.cs:
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<WeChatOptions> { public WeChatHandler(HttpClient httpClient) : base(httpClient) { } protected override async Task<AuthenticateResult> 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."); } } /// <summary> /// OAuth第一步,獲取code /// </summary> /// <param name="properties"></param> /// <param name="redirectUri"></param> /// <returns></returns> protected override string BuildChallengeUrl(AuthenticationProperties properties, string redirectUri) { //加密OAuth狀態(tài) 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(); } /// <summary> /// OAuth第二步,獲取token /// </summary> /// <param name="code"></param> /// <param name="redirectUri"></param> /// <returns></returns> protected override async Task<OAuthTokenResponse> ExchangeCodeAsync(string code, string redirectUri) { var tokenRequestParameters = new Dictionary<string, string>() { { "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<string>("errcode"); string ErrMsg = payload.Value<string>("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<string>("openid"); return tokens; } else { var error = "OAuth token endpoint failure"; return OAuthTokenResponse.Failed(new Exception(error)); } } /// <summary> /// OAuth第四步,獲取用戶信息 /// </summary> /// <param name="identity"></param> /// <param name="properties"></param> /// <param name="tokens"></param> /// <returns></returns> protected override async Task<AuthenticationTicket> CreateTicketAsync(ClaimsIdentity identity, AuthenticationProperties properties, OAuthTokenResponse tokens) { var queryBuilder = new QueryBuilder() { { "access_token", tokens.AccessToken }, { "openid", tokens.TokenType },//在第二步中,openid被存入TokenType屬性 { "lang", "zh_CN" } }; var infoRequest = Options.UserInformationEndpoint + queryBuilder.ToString(); var response = await Backchannel.GetAsync(infoRequest, Context.RequestAborted); if (!response.IsSuccessStatusCode) { throw new HttpRequestException($"Failed to retrieve WeChat user information ({response.StatusCode}) Please check if the authentication information is correct and the corresponding WeChat Graph API is enabled."); } var user = JObject.Parse(await response.Content.ReadAsStringAsync()); var ticket = new AuthenticationTicket(new ClaimsPrincipal(identity), properties, Options.AuthenticationScheme); var context = new OAuthCreatingTicketContext(ticket, Context, Options, Backchannel, tokens, user); var identifier = user.Value<string>("openid"); if (!string.IsNullOrEmpty(identifier)) { identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, identifier, ClaimValueTypes.String, Options.ClaimsIssuer)); } var nickname = user.Value<string>("nickname"); if (!string.IsNullOrEmpty(nickname)) { identity.AddClaim(new Claim(ClaimTypes.Name, nickname, ClaimValueTypes.String, Options.ClaimsIssuer)); } var sex = user.Value<string>("sex"); if (!string.IsNullOrEmpty(sex)) { identity.AddClaim(new Claim("urn:WeChat:sex", sex, ClaimValueTypes.String, Options.ClaimsIssuer)); } var country = user.Value<string>("country"); if (!string.IsNullOrEmpty(country)) { identity.AddClaim(new Claim(ClaimTypes.Country, country, ClaimValueTypes.String, Options.ClaimsIssuer)); } var province = user.Value<string>("province"); if (!string.IsNullOrEmpty(province)) { identity.AddClaim(new Claim(ClaimTypes.StateOrProvince, province, ClaimValueTypes.String, Options.ClaimsIssuer)); } var city = user.Value<string>("city"); if (!string.IsNullOrEmpty(city)) { identity.AddClaim(new Claim("urn:WeChat:city", city, ClaimValueTypes.String, Options.ClaimsIssuer)); } var headimgurl = user.Value<string>("headimgurl"); if (!string.IsNullOrEmpty(headimgurl)) { identity.AddClaim(new Claim("urn:WeChat:headimgurl", headimgurl, ClaimValueTypes.String, Options.ClaimsIssuer)); } var unionid = user.Value<string>("unionid"); if (!string.IsNullOrEmpty(unionid)) { identity.AddClaim(new Claim("urn:WeChat:unionid", unionid, ClaimValueTypes.String, Options.ClaimsIssuer)); } await Options.Events.CreatingTicket(context); return context.Ticket; } } }
WeChatMiddleware.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 System; using System.Globalization; using System.Text.Encodings.Web; using Microsoft.AspNetCore.Authentication.OAuth; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; namespace Microsoft.AspNetCore.Authentication.WeChat { /// <summary> /// An ASP.NET Core middleware for authenticating users using WeChat. /// </summary> public class WeChatMiddleware : OAuthMiddleware<WeChatOptions> { /// <summary> /// Initializes a new <see cref="WeChatMiddleware"/>. /// </summary> /// <param name="next">The next middleware in the HTTP pipeline to invoke.</param> /// <param name="dataProtectionProvider"></param> /// <param name="loggerFactory"></param> /// <param name="encoder"></param> /// <param name="sharedOptions"></param> /// <param name="options">Configuration options for the middleware.</param> public WeChatMiddleware( RequestDelegate next, IDataProtectionProvider dataProtectionProvider, ILoggerFactory loggerFactory, UrlEncoder encoder, IOptions<SharedAuthenticationOptions> sharedOptions, IOptions<WeChatOptions> options) : base(next, dataProtectionProvider, loggerFactory, encoder, sharedOptions, options) { if (next == null) { throw new ArgumentNullException(nameof(next)); } if (dataProtectionProvider == null) { throw new ArgumentNullException(nameof(dataProtectionProvider)); } if (loggerFactory == null) { throw new ArgumentNullException(nameof(loggerFactory)); } if (encoder == null) { throw new ArgumentNullException(nameof(encoder)); } if (sharedOptions == null) { throw new ArgumentNullException(nameof(sharedOptions)); } if (options == null) { throw new ArgumentNullException(nameof(options)); } if (string.IsNullOrEmpty(Options.AppId)) { throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, nameof(Options.AppId))); } if (string.IsNullOrEmpty(Options.AppSecret)) { throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, nameof(Options.AppSecret))); } } /// <summary> /// Provides the <see cref="AuthenticationHandler{T}"/> object for processing authentication-related requests. /// </summary> /// <returns>An <see cref="AuthenticationHandler{T}"/> configured with the <see cref="WeChatOptions"/> supplied to the constructor.</returns> protected override AuthenticationHandler<WeChatOptions> CreateHandler() { return new WeChatHandler(Backchannel); } } }
WeChatOptions.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 System.Collections.Generic; using Microsoft.AspNetCore.Authentication.WeChat; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Identity; namespace Microsoft.AspNetCore.Builder { /// <summary> /// Configuration options for <see cref="WeChatMiddleware"/>. /// </summary> public class WeChatOptions : OAuthOptions { /// <summary> /// Initializes a new <see cref="WeChatOptions"/>. /// </summary> public WeChatOptions() { AuthenticationScheme = WeChatDefaults.AuthenticationScheme; DisplayName = AuthenticationScheme; CallbackPath = new PathString("/signin-wechat"); StateAddition = "#wechat_redirect"; AuthorizationEndpoint = WeChatDefaults.AuthorizationEndpoint; TokenEndpoint = WeChatDefaults.TokenEndpoint; UserInformationEndpoint = WeChatDefaults.UserInformationEndpoint; //SaveTokens = true; //BaseScope (不彈出授權(quán)頁面,直接跳轉(zhuǎn),只能獲取用戶openid), //InfoScope (彈出授權(quán)頁面,可通過openid拿到昵稱、性別、所在地。并且,即使在未關(guān)注的情況下,只要用戶授權(quán),也能獲取其信息) WeChatScope = InfoScope; } // WeChat uses a non-standard term for this field. /// <summary> /// Gets or sets the WeChat-assigned appId. /// </summary> public string AppId { get { return ClientId; } set { ClientId = value; } } // WeChat uses a non-standard term for this field. /// <summary> /// Gets or sets the WeChat-assigned app secret. /// </summary> public string AppSecret { get { return ClientSecret; } set { ClientSecret = value; } } public string StateAddition { get; set; } public string WeChatScope { get; set; } public string BaseScope = "snsapi_base"; public string InfoScope = "snsapi_userinfo"; } }
The above is the detailed content of Illustration of an example of integrating WeChat login with ASP.NET Core. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

The login portal for the Douyin web version is https://www.douyin.com/. The login steps include: 1. Open the browser; 2. Enter the URL https://www.douyin.com/; 3. Click the "Login" button and select the login method; 4. Enter the account password; 5. Complete login. The web version provides functions such as browsing, searching, interaction, uploading videos and personal homepage management, and has advantages such as large-screen experience, multi-tasking, convenient account management and data statistics.

Copying comics is undoubtedly a treasure that cannot be missed. Here you can find basketball comics in various styles, from passionate and inspiring competitive stories to relaxed and humorous daily comedy. Whether you want to relive the classics or discover new works, copying comics can meet your needs. Through the authentic online reading portal provided by copy comics, you will bid farewell to the trouble of pirated resources, enjoy a high-definition and smooth reading experience, and can support your favorite comic authors and contribute to the development of authentic comics.

Choosing UC browser or QQ browser depends on your needs: 1. UC browser is suitable for users who pursue fast loading and rich entertainment functions; 2. QQ browser is suitable for users who need stability and seamless connection with Tencent products.

Combining the latest industry trends and multi-dimensional evaluation data in 2025, the following are the top ten comprehensive AI writing software recommendations, covering mainstream scenarios such as general creation, academic research, and commercial marketing, while taking into account Chinese optimization and localization services:

Nice Comics, an immersive reading experience platform dedicated to creating for comic lovers, brings together a large number of high-quality comic resources at home and abroad. It is not only a comic reading platform, but also a community that connects comic artists and readers and shares comic culture. Through simple and intuitive interface design and powerful search functions, NES Comics allows you to easily find your favorite works and enjoy a smooth and comfortable reading experience. Say goodbye to the long waiting and tedious operations, enter the world of Nice comics immediately and start your comic journey!

Frogman Comics has become the first choice for many comic lovers with its rich and diverse comic resources and convenient and smooth online reading experience. It is like a vibrant pond, with fresh and interesting stories constantly emerging, waiting for you to discover and explore. Frog Man comics cover a variety of subjects, from passionate adventures to sweet love, from fantasy and science fiction to suspense reasoning, no matter which genre you like, you can find your favorite works here. Its simple and intuitive interface design allows you to easily get started, quickly find the comics you want to read, and immerse yourself in the exciting comic world.

Here, you can enjoy the vast ocean of comics and explore works of various themes and styles, from passionate young man comics to delicate and moving girl comics, from suspenseful and brain-burning mystery comics to relaxed and funny daily comics, there is everything, and there is always one that can touch your heartstrings. We not only have a large amount of genuine comic resources, but also constantly introduce and update the latest works to ensure that you can read your favorite comics as soon as possible.

The latest official website of 2025b Announce is: https://www.marketwebb.co/zh-CN/join?ref=507720986&type=wenzi; Binance Exchange is a global cryptocurrency exchange that serves 180 countries and regions including North America, Europe, Taiwan, the Middle East, Hong Kong, and Malaysia. It provides more than 600 cryptocurrencies and has 270 million registered users worldwide.
