ASP. NET Core integrates with WeChat logon, asp. netcore

Source: Internet
Author: User
Tags oauth openid

ASP. NET Core integrated logon, asp. netcore

Tools:

Visual Studio 2015 update 3

Asp. Net Core 1.0

1. Preparations

Apply for public platform Interface Test account, apply for web site :( http://mp.weixin.qq.com/debug/cgi-bin/sandbox? T = sandbox/login ). You can apply for an API test number without a public account. You can directly experience and test all the advanced interfaces on the public platform.

1.1 configure Interface Information

1.2 modify webpage authorization information

Click "modify" and enter your website domain name on the pop-up page:

2. Create a website project

2.1 select an ASP. NET Core Web Application Template

2.2 select a Web application and change authentication to personal user account

3. Integrated Login

3.1 add reference

Open the project. json file and add the reference Microsoft. AspNetCore. Authentication. OAuth

3.2 Add a code file

Create a folder in the project, name it WeChatOAuth, and add a code file (all code is attached at the end of this Article ).

3.3 register and log on Middleware

Open the Startup. cs file and add the code in Configure:

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

Note that the Code must be inserted under app. UseIdentity.

4. Code

WeChatAppBuilderExtensions. 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 Microsoft.AspNetCore.Authentication.WeChat;using Microsoft.Extensions.Options;namespace Microsoft.AspNetCore.Builder{  /// <summary>  /// Extension methods to add WeChat authentication capabilities to an HTTP application pipeline.  /// </summary>  public static class WeChatAppBuilderExtensions  {    /// <summary>    /// Adds the <see cref="WeChatMiddleware"/> middleware to the specified <see cref="IApplicationBuilder"/>, which enables WeChat authentication capabilities.    /// </summary>    /// <param name="app">The <see cref="IApplicationBuilder"/> to add the middleware to.</param>    /// <returns>A reference to this instance after the operation has completed.</returns>    public static IApplicationBuilder UseWeChatAuthentication(this IApplicationBuilder app)    {      if (app == null)      {        throw new ArgumentNullException(nameof(app));      }      return app.UseMiddleware<WeChatMiddleware>();    }    /// <summary>    /// Adds the <see cref="WeChatMiddleware"/> middleware to the specified <see cref="IApplicationBuilder"/>, which enables WeChat authentication capabilities.    /// </summary>    /// <param name="app">The <see cref="IApplicationBuilder"/> to add the middleware to.</param>    /// <param name="options">A <see cref="WeChatOptions"/> that specifies options for the middleware.</param>    /// <returns>A reference to this instance after the operation has completed.</returns>    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<WeChatMiddleware>(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. lin Q; 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 o Verride async Task <AuthenticateResult> HandleRemoteAuthenticateAsync () {AuthenticationProperties = 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.");} // oauh2 10.12 CSRF if (! ValidateCorrelationId (properties) {return AuthenticateResult. fail ("Correlation failed. ");} if (StringValues. isNullOrEmpty (code) {return AuthenticateResult. fail ("Code was not found. ");} // get tokens var tokens = await ExchangeCodeAsync (code, BuildRedirectUri (Options. callbackPath); var identity = new ClaimsIdentity (Options. claimsIssuer); AuthenticationTicket ticket = null; if (Options. weChatScop E = Options. infoScope) {// obtain user information ticket = await CreateTicketAsync (identity, properties, tokens);} else {// do not obtain information, only use 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 step 1, get code /// </summary> /// <param name = "properties"> </param> /// <param name = "redirectUri"> </param>/ // <returns> </returns> protected override string BuildChallengeUrl (AuthenticationProperties properties, string redire CtUri) {// encrypted OAuth status 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> // step 2 of OAuth, get 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 (tokenR EquestParameters); 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); // use the TokenType attribute to save the openid tokens. tokenType = payload. value <string> ("openid"); return tokens;} else {var error = "OAuth token endpoint failure"; return OAuthTokenResponse. failed (new Exception (error) ;}/// <summary> // step 4 of OAuth, Get user information /// </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}, {"o Penid ", tokens. tokenType}, // in step 2, The openid is saved to the TokenType attribute {"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, Opti Ons. 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 <s Ee cref = "WeChatMiddleware"/>. /// </summary> public class WeChatOptions: oautexceptions {// <summary> // Initializes a new <see cref = "WeChatOptions"/>. /// </summary> public WeChatOptions () {AuthenticationScheme = WeChatDefaults. authenticationScheme; DisplayName = AuthenticationScheme; CallbackPath = new PathString ("/signin-wechat"); StateAddition = "# wechat_redirect"; AuthorizationEndpoint = W EChatDefaults. authorizationEndpoint; TokenEndpoint = WeChatDefaults. tokenEndpoint; UserInformationEndpoint = WeChatDefaults. userInformationEndpoint; // SaveTokens = true; // baseline, you can obtain the nickname, gender, and location through openid. In addition, even if the user is not concerned, the user can obtain the information as long as the user is authorized.) 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 Baseline = "snsapi_base"; public string InfoScope = "snsapi_userinfo ";}}

The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.