asp.net core in the integrated micro-mail Fast login program

Source: Internet
Author: User
Tags oauth openid reserved static class ticket


Tools:



Visual Studio 2015 Update 3



asp.net Core 1.0




1 Preparation work



Application for micro-trust public Platform Interface test account number, application URL: (http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login). Application interface test number without public account, you can directly experience and test all the advanced interface of public platform.



1.1 Configuring Interface Information






1.2 Modify the page authorization information






Click "Modify" to fill in your site's domain name on the pop-up page:









2 new Web site projects



2.1 Select asp.net Core Web application Template









2.2 Select the Web application and change the authentication to personal user account









3 Integrated micro-Credit login function



3.1 Adding references



Open Project.json file, add Reference Microsoft.AspNetCore.Authentication.OAuth









3.2 Adding code files



Create a new folder in your project, name it Wechatoauth, and add a code file (with all the code at the end of this article).









3.3 Registered micro-letter Login Middleware



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




App. Usewechatauthentication (New Wechatoptions ()
{
AppId = "Hu Jintao",
Appsecret = "Hu Jintao"
});
Note that the insertion position of the code must be in the app. Useidentity () below.






4 Code





 1 // Copyright (c) .NET Foundation. All rights reserved.
 2 // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
 3
 4 using System;
 5 using Microsoft.AspNetCore.Authentication.WeChat;
 6 using Microsoft.Extensions.Options;
 7
 8 namespace Microsoft.AspNetCore.Builder
 9 {
10     /// <summary>
11     /// Extension methods to add WeChat authentication capabilities to an HTTP application pipeline.
12     /// </summary>
13     public static class WeChatAppBuilderExtensions
14     {
15         /// <summary>
16         /// Adds the <see cref="WeChatMiddleware"/> middleware to the specified <see cref="IApplicationBuilder"/>, which enables WeChat authentication capabilities.
17         /// </summary>
18         /// <param name="app">The <see cref="IApplicationBuilder"/> to add the middleware to.</param>
19         /// <returns>A reference to this instance after the operation has completed.</returns>
20         public static IApplicationBuilder UseWeChatAuthentication(this IApplicationBuilder app)
21         {
22             if (app == null)
23             {
24                 throw new ArgumentNullException(nameof(app));
25             }
26
27             return app.UseMiddleware<WeChatMiddleware>();
28         }
29
30         /// <summary>
31         /// Adds the <see cref="WeChatMiddleware"/> middleware to the specified <see cref="IApplicationBuilder"/>, which enables WeChat authentication capabilities.
32         /// </summary>
33         /// <param name="app">The <see cref="IApplicationBuilder"/> to add the middleware to.</param>
34         /// <param name="options">A <see cref="WeChatOptions"/> that specifies options for the middleware.</param>
35         /// <returns>A reference to this instance after the operation has completed.</returns>
36         public static IApplicationBuilder UseWeChatAuthentication(this IApplicationBuilder app, WeChatOptions options)
37         {
38             if (app == null)
39             {
40                 throw new ArgumentNullException(nameof(app));
41             }
42             if (options == null)
43             {
44                 throw new ArgumentNullException(nameof(options));
45             }
46
47             return app.UseMiddleware<WeChatMiddleware>(Options.Create(options));
48         }
49     }
50 }





Copyright (c). NET Foundation. All rights reserved.
Licensed under the Apache License, Version 2.0. 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";
}
}






Copyright (c). NET Foundation. All rights reserved.
Licensed under the Apache License, Version 2.0. 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 (";D escription="). 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 is missing or invalid.");
}



OAuth2 10.12 CSRF
if (! Validatecorrelationid (properties))
{
Return Authenticateresult.fail ("Correlation failed.");
}



if (Stringvalues.isnullorempty (code))
{
Return Authenticateresult.fail ("Code is not found.");
}



Get tokens
var tokens = await Exchangecodeasync (code, Buildredirecturi (Options.callbackpath));



var identity = new Claimsidentity (Options.claimsissuer);



Authenticationticket ticket = null;


if (Options.wechatscope = = Options.infoscope)
{
Get user Information
Ticket = await Createticketasync (identity, properties, tokens);
}
Else
{
Do not get information, use OpenID only
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 First step, get code
        </summary>
       ///<param name= "Properties" ></param
       ///<param name= "Redirecturi" ></PARAM>
        ///<returns></returns>
         protected override string Buildchallengeurl (Authenticationproperties properties, String Redirecturi)
         {
           // 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>
OAuth second step, 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 (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);



Use Tokentype property to save OpenID
Tokens. Tokentype = payload. Value<string> ("OpenID");



return tokens;
}
Else
{
var error = "OAuth token endpoint Failure";
Return oauthtokenresponse.failed (new Exception (error));
}
}


<summary>
OAuth step Fourth, 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},
{"OpenID", tokens. Tokentype},//in the second step, OpenID is deposited in 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 are 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;
}
}
}






Copyright (c). NET Foundation. All rights reserved.
Licensed under the Apache License, Version 2.0. 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"/&GT;.
</summary>
<param name= "Next" >the next middleware 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.
</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);
}
}
}






Copyright (c). NET Foundation. All rights reserved.
Licensed under the Apache License, Version 2.0. 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"/&GT;.
</summary>
public class Wechatoptions:oauthoptions
{
<summary>
Initializes a new <see cref= "Wechatoptions"/&GT;.
</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 (does not eject the authorization page, direct jump, can only get user OpenID),
           //infoscope (Eject the authorization page, you can get the nickname, Sex, location via OpenID). And, even in the event of no concern, as long as the user authorized to obtain their information)
            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";
   }
}


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.