【移動(dòng)應(yīng)用開發(fā)技術(shù)】ASP.NET Core集成微信登錄的示例分析_第1頁(yè)
【移動(dòng)應(yīng)用開發(fā)技術(shù)】ASP.NET Core集成微信登錄的示例分析_第2頁(yè)
【移動(dòng)應(yīng)用開發(fā)技術(shù)】ASP.NET Core集成微信登錄的示例分析_第3頁(yè)
【移動(dòng)應(yīng)用開發(fā)技術(shù)】ASP.NET Core集成微信登錄的示例分析_第4頁(yè)
【移動(dòng)應(yīng)用開發(fā)技術(shù)】ASP.NET Core集成微信登錄的示例分析_第5頁(yè)
已閱讀5頁(yè),還剩17頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

【移動(dòng)應(yīng)用開發(fā)技術(shù)】ASP.NETCore集成微信登錄的示例分析

工具:1準(zhǔn)備工作1.1配置接口信息/upload/information/20201208/260/10251.jpg1.2修改網(wǎng)頁(yè)授權(quán)信息/upload/information/20201208/260/10252.jpg/upload/information/20201208/260/10253.jpg2新建網(wǎng)站項(xiàng)目2.1選擇ASP.NETCoreWebApplication模板/upload/information/20201208/260/10254.jpg2.2選擇Web應(yīng)用程序,并更改身份驗(yàn)證為個(gè)人用戶賬戶/upload/information/20201208/260/10255.jpg3集成微信登錄功能3.1添加引用/upload/information/20201208/260/10256.jpg3.2添加代碼文件/upload/information/20201208/260/10257.jpg3.3注冊(cè)微信登錄中間件app.UseWeChatAuthentication(new

WeChatOptions()

{

AppId

=

"******",

AppSecret

=

"******"

});/upload/information/20201208/260/10258.jpg4代碼//

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));

}

}

}//

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

=

"/connect/oauth3/authorize";

public

static

readonly

string

TokenEndpoint

=

"/sns/oauth3/access_token";

public

static

readonly

string

UserInformationEndpoint

=

"/sns/userinfo";

}

}//

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.");

}

//

OAuth3

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;

}

}

}//

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);

}

}

}//

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

Micr

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論