欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

asp.net core 認(rèn)證和授權(quán)實(shí)例詳解

 更新時(shí)間:2022年09月09日 16:19:34   作者:chenxin.dm  
這篇文章主要為大家介紹了asp.net core 認(rèn)證和授權(quán)實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

正文

使用asp.net core 開發(fā)應(yīng)用系統(tǒng)過程中,基本上都會(huì)涉及到用戶身份的認(rèn)證,及授權(quán)訪問控制,因此了解認(rèn)證和授權(quán)流程也相當(dāng)重要,下面通過分析asp.net core 框架中的認(rèn)證和授權(quán)的源碼來分析認(rèn)證、授權(quán)的原理及認(rèn)證和授權(quán)的關(guān)系。

認(rèn)證是什么?

認(rèn)證是應(yīng)用系統(tǒng)識別當(dāng)前訪問者的身份的一個(gè)過程,當(dāng)應(yīng)用系統(tǒng)接收到瀏覽器的請求后,通常會(huì)根據(jù)請求中攜帶的一些用戶的的關(guān)鍵信息來識別當(dāng)前登錄用戶的身份,通過解析這些信息,對用戶進(jìn)行合法性校驗(yàn)并進(jìn)行解密,如果校驗(yàn)通過,則表示認(rèn)證通過,應(yīng)用系統(tǒng)會(huì)將認(rèn)證通過后的用戶信息存儲(chǔ)到Http請求上下文中,以便后續(xù)業(yè)務(wù)使用及授權(quán)流程中使用。

asp.net core中通常將認(rèn)證信息加密后存儲(chǔ)到cookie中,每次訪問需要認(rèn)證的頁面時(shí)將這些cookie信息發(fā)送到應(yīng)用系統(tǒng),以便應(yīng)用系統(tǒng)識別訪問者的身份,也就是經(jīng)典的Cookie認(rèn)證。

需要注意的是:認(rèn)證僅僅只是識別當(dāng)前訪問用戶的身份,并不負(fù)責(zé)具體的訪問權(quán)限控制邏輯,如不具備某個(gè)資源的訪問權(quán)限返回403,未登錄返回401等,這些均由授權(quán)流程來控制。

asp.net core 中負(fù)責(zé)認(rèn)證流程的中間件是AuthenticationMiddleware 類,以下是asp.net core 3.1 的源代碼,可以看到,先遍歷所有實(shí)現(xiàn)了IAuthenticationRequestHandler接口的認(rèn)證方案,并調(diào)用IAuthenticationRequestHandler接口的HandleRequestAsync方法,如果認(rèn)證通過,則不再繼續(xù)往下執(zhí)行,并且此時(shí)HttpContext.User已經(jīng)包含認(rèn)證后的用戶信息,如果所有實(shí)現(xiàn) IAuthenticationRequestHandler 接口的認(rèn)證方案,都未能對當(dāng)前訪問用戶進(jìn)行身份認(rèn)證,則使用默認(rèn)的認(rèn)證方案進(jìn)行認(rèn)證(也就是:GetDefaultAuthenticateSchemeAsync返回的認(rèn)證方案),可以看到認(rèn)證流程即使沒能識別當(dāng)前訪問者的用戶身份,也會(huì)繼續(xù)執(zhí)行下一個(gè)流程,(尾部:await _next(context);)

public class AuthenticationMiddleware
{
	private readonly RequestDelegate _next;
	public IAuthenticationSchemeProvider Schemes
	{
		get;
		set;
	}
	public AuthenticationMiddleware(RequestDelegate next, IAuthenticationSchemeProvider schemes)
	{
		if (next == null)
		{
			throw new ArgumentNullException("next");
		}
		if (schemes == null)
		{
			throw new ArgumentNullException("schemes");
		}
		_next = next;
		Schemes = schemes;
	}
	public async Task Invoke(HttpContext context)
	{
		context.Features.Set((IAuthenticationFeature)new AuthenticationFeature
		{
			OriginalPath = context.Request.Path,
			OriginalPathBase = context.Request.PathBase
		});
		IAuthenticationHandlerProvider handlers = context.RequestServices.GetRequiredService<IAuthenticationHandlerProvider>();
		foreach (AuthenticationScheme item in await Schemes.GetRequestHandlerSchemesAsync())
		{
			IAuthenticationRequestHandler authenticationRequestHandler = (await handlers.GetHandlerAsync(context, item.Name)) as IAuthenticationRequestHandler;
			bool flag = authenticationRequestHandler != null;
			if (flag)
			{
				flag = await authenticationRequestHandler.HandleRequestAsync();
			}
			if (flag)
			{
				return;
			}
		}
		AuthenticationScheme authenticationScheme = await Schemes.GetDefaultAuthenticateSchemeAsync();
		if (authenticationScheme != null)
		{
                        //內(nèi)部調(diào)用IAuthenticationService進(jìn)行認(rèn)證。
			AuthenticateResult authenticateResult = await context.AuthenticateAsync(authenticationScheme.Name);
			if (authenticateResult?.Principal != null)
			{
				context.User = authenticateResult.Principal;
			}
		}
		await _next(context);
	}
}

授權(quán)是什么?

授權(quán)是確定當(dāng)前訪問用戶是否具備訪問某個(gè)系統(tǒng)資源權(quán)限的過程,對于需要授權(quán)才能訪問的系統(tǒng)資源,通常通過[Authorize]特性來標(biāo)識,通過該特性,可以指定該資源需要哪個(gè)用戶角色才能訪問、必須符合哪個(gè)授權(quán)策略才能訪問,以及訪問該資源時(shí)采用的用戶認(rèn)證方案是什么,當(dāng)用戶訪問系統(tǒng)的某個(gè)API或者頁面時(shí),授權(quán)流程會(huì)檢查當(dāng)前用戶是否具備該API或者頁面的訪問權(quán)限,如果授權(quán)檢查失敗,那么會(huì)判斷當(dāng)前用戶是否已經(jīng)認(rèn)證通過,如果認(rèn)證通過,但無訪問該資源的權(quán)限,那么返回403(禁止訪問),如果未認(rèn)證,那么直接返回401(未認(rèn)證),表示需要用戶登錄認(rèn)證后在進(jìn)行訪問,需要注意的是:檢查是否具備訪問權(quán)限之前會(huì)先進(jìn)行用戶身份的認(rèn)證,至于用什么認(rèn)證方案就看AuthorizeAttribute有沒有指定特定的認(rèn)證方案,如果沒有,則直接采用認(rèn)證流程的認(rèn)證成功的身份信息。

asp.net core 中,授權(quán)流程的執(zhí)行是通過AuthorizationMiddleware類來完成的,以下是asp.net core 3.1中的源碼。

// Microsoft.AspNetCore.Authorization.AuthorizationMiddleware
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authorization.Policy;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
public class AuthorizationMiddleware
{
	private const string AuthorizationMiddlewareInvokedWithEndpointKey = "__AuthorizationMiddlewareWithEndpointInvoked";
	private static readonly object AuthorizationMiddlewareWithEndpointInvokedValue = new object();
	private readonly RequestDelegate _next;
	private readonly IAuthorizationPolicyProvider _policyProvider;
	public AuthorizationMiddleware(RequestDelegate next, IAuthorizationPolicyProvider policyProvider)
	{
		_next = next ?? throw new ArgumentNullException("next");
		_policyProvider = policyProvider ?? throw new ArgumentNullException("policyProvider");
	}
	public async Task Invoke(HttpContext context)
	{
		if (context == null)
		{
			throw new ArgumentNullException("context");
		}
		Endpoint endpoint = context.GetEndpoint();
		if (endpoint != null)
		{
			context.Items["__AuthorizationMiddlewareWithEndpointInvoked"] = AuthorizationMiddlewareWithEndpointInvokedValue;
		}
                //獲取訪問當(dāng)前資源所需要的所有角色權(quán)限,及授權(quán)策略,以及訪問該資源時(shí)需要使用的認(rèn)證方案列表,并統(tǒng)一合并到一個(gè)AuthorizationPolicy對象中。
		IReadOnlyList<IAuthorizeData> authorizeData = endpoint?.Metadata.GetOrderedMetadata<IAuthorizeData>() ?? Array.Empty<IAuthorizeData>();
		AuthorizationPolicy policy = await AuthorizationPolicy.CombineAsync(_policyProvider, authorizeData);
		if (policy == null)
		{
			await _next(context);
			return;
		}
		IPolicyEvaluator policyEvaluator = context.RequestServices.GetRequiredService<IPolicyEvaluator>();
                //通過IPolicyEvaluator.AuthenticateAsync()方法,對當(dāng)前訪問者進(jìn)行認(rèn)證,至于使用哪種方案認(rèn)證,根據(jù)該資源要求使用的認(rèn)證方案來,如果沒有指定,
                //則使用默認(rèn)認(rèn)證方案進(jìn)行認(rèn)證。
		AuthenticateResult authenticationResult = await policyEvaluator.AuthenticateAsync(policy, context);
                //如果包含實(shí)現(xiàn)了IAllowAnonymous接口的特性,則不進(jìn)行授權(quán)檢查。
		if (endpoint?.Metadata.GetMetadata<IAllowAnonymous>() != null)
		{
			await _next(context);
			return;
		}
                //這里調(diào)用AuthorizeAsync進(jìn)行授權(quán)檢查,注意,這里將上一步認(rèn)證結(jié)果authenticationResult也傳到了授權(quán)檢查方法內(nèi)部。
		PolicyAuthorizationResult policyAuthorizationResult = await policyEvaluator.AuthorizeAsync(policy, authenticationResult, context, endpoint);
		//檢查授權(quán)結(jié)果,如果是未登錄,則返回401未認(rèn)證,讓用戶進(jìn)行登錄,如果該資源指定了特定的認(rèn)證方案,則調(diào)用特定認(rèn)證方案的Challenge方法,
                //否則調(diào)用默認(rèn)認(rèn)證方案的Challenge方法,通常Challenge做的事情就是重定向用戶的瀏覽器到登錄頁面或者對于ajax異步請求返回401.
                if (policyAuthorizationResult.Challenged)
		{
			if (policy.AuthenticationSchemes.Any())
			{
				foreach (string authenticationScheme in policy.AuthenticationSchemes)
				{
					await context.ChallengeAsync(authenticationScheme);
				}
			}
			else
			{
				await context.ChallengeAsync();
			}
		}
                //如果當(dāng)前訪問者用戶身份認(rèn)證通過,但是不被允許訪問該資源的權(quán)限,那么默認(rèn)返回401(禁止訪問)給瀏覽器端,通常對于未授權(quán)的訪問請求,應(yīng)用常常的做法是將用戶的瀏覽器重定向到禁止訪問的提示頁面,或者對于ajax異步請求來說,通常返回403狀態(tài)碼,和上面未認(rèn)證情況一樣,如果該資源指定了特定的認(rèn)證方案,那么會(huì)調(diào)用特定認(rèn)證方案的Forbid方法,否則調(diào)用默認(rèn)認(rèn)證方案的Forbid方法。
		else if (policyAuthorizationResult.Forbidden)
		{
			if (policy.AuthenticationSchemes.Any())
			{
				foreach (string authenticationScheme2 in policy.AuthenticationSchemes)
				{
					await context.ForbidAsync(authenticationScheme2);
				}
			}
			else
			{
				await context.ForbidAsync();
			}
		}
		else
		{
			await _next(context);
		}
	}
}

IPolicyEvaluator接口實(shí)現(xiàn)類 PolicyEvaluator類代碼如下,該類主要是負(fù)責(zé)授權(quán)流程中的認(rèn)證和授權(quán)。

// Microsoft.AspNetCore.Authorization.Policy.PolicyEvaluator
using System;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Authorization.Policy;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Internal;
public class PolicyEvaluator : IPolicyEvaluator
{
	private readonly IAuthorizationService _authorization;
	public PolicyEvaluator(IAuthorizationService authorization)
	{
		_authorization = authorization;
	}
	public virtual async Task<AuthenticateResult> AuthenticateAsync(AuthorizationPolicy policy, HttpContext context)
	{
                //這里去判斷當(dāng)前資源是否有要求特定的認(rèn)證方案進(jìn)行認(rèn)證,如果有指定特定的認(rèn)證方案,則分別對每個(gè)認(rèn)證方案進(jìn)行認(rèn)證,并把認(rèn)證后的用戶信息進(jìn)行合并
                //最終存儲(chǔ)到HttpContext.User屬性中,并返回認(rèn)證成功,如果沒有指定認(rèn)證方案,則使用認(rèn)證流程中已經(jīng)認(rèn)證的用戶信息作為認(rèn)證結(jié)果返回,
                //從這里可以看出,認(rèn)證流程還是很有必要的,在資源沒有指定認(rèn)證方案的前提下,認(rèn)證流程為授權(quán)流程提供當(dāng)前訪問者的身份信息,以便執(zhí)行是否具備相應(yīng)資源的訪問權(quán)限檢查,否則就直接進(jìn)入Challenge流程將要求用戶先進(jìn)行身份認(rèn)證了
		if (policy.AuthenticationSchemes != null && policy.AuthenticationSchemes.Count > 0)
		{
			ClaimsPrincipal newPrincipal = null;
			foreach (string authenticationScheme in policy.AuthenticationSchemes)
			{
				AuthenticateResult authenticateResult = await context.AuthenticateAsync(authenticationScheme);
				if (authenticateResult != null && authenticateResult.Succeeded)
				{
					newPrincipal = SecurityHelper.MergeUserPrincipal(newPrincipal, authenticateResult.Principal);
				}
			}
			if (newPrincipal != null)
			{
				context.User = newPrincipal;
				return AuthenticateResult.Success(new AuthenticationTicket(newPrincipal, string.Join(";", policy.AuthenticationSchemes)));
			}
			context.User = new ClaimsPrincipal(new ClaimsIdentity());
			return AuthenticateResult.NoResult();
		}
		return (context.User?.Identity?.IsAuthenticated).GetValueOrDefault() ? AuthenticateResult.Success(new AuthenticationTicket(context.User, "context.User")) : AuthenticateResult.NoResult();
	}
        //resource為EndPoint對象。
	public virtual async Task<PolicyAuthorizationResult> AuthorizeAsync(AuthorizationPolicy policy, AuthenticateResult authenticationResult, HttpContext context, object resource)
	{
		if (policy == null)
		{
			throw new ArgumentNullException("policy");
		}
                //這里調(diào)用IAuthorizationService.AuthorizeAsync方法進(jìn)行授權(quán)檢查,默認(rèn)實(shí)現(xiàn)類為:DefaultAuthorizationService。
		if ((await _authorization.AuthorizeAsync(context.User, resource, policy)).Succeeded)
		{
			return PolicyAuthorizationResult.Success();
		}
                //下面這句表示如果授權(quán)檢查失敗的情況下是進(jìn)入Forbid流程還是進(jìn)入Challenge流程,可以看到如果認(rèn)證成功,那么表示無權(quán)限訪問進(jìn)入Forbid流程。
                //如果未認(rèn)證,則進(jìn)入Challenge流程,引導(dǎo)用戶登錄認(rèn)證。
		return authenticationResult.Succeeded ? PolicyAuthorizationResult.Forbid() : PolicyAuthorizationResult.Challenge();
	}
}

認(rèn)證和授權(quán)的關(guān)系?

授權(quán)檢查之前都會(huì)先執(zhí)行用戶身份的認(rèn)證,不過這里的認(rèn)證流程只有在被訪問的資源有指定特定的認(rèn)證方案時(shí)才會(huì)執(zhí)行,否則直接采用統(tǒng)一認(rèn)證流程中的產(chǎn)生的認(rèn)證信息。

可以理解為認(rèn)證流程一方面是為了告訴應(yīng)用系統(tǒng)當(dāng)前訪問者的身份,一方面是為了給授權(quán)檢查時(shí)識別用戶的身份信息,當(dāng)資源沒有指定采用何種認(rèn)證方案時(shí),授權(quán)流程將會(huì)采用統(tǒng)一認(rèn)證流程里認(rèn)證通過產(chǎn)生的用戶信息,如果不啟用認(rèn)證流程,并且被訪問的資源也沒有指定特定的認(rèn)證方案對訪問者身份進(jìn)行認(rèn)證時(shí),那么最終訪問該資源時(shí)還是會(huì)被要求先登錄認(rèn)證,因此認(rèn)證流程的另外一個(gè)用途就是為授權(quán)流程提供默認(rèn)的用戶認(rèn)證信息。

總結(jié)起來說,

認(rèn)證流程主要有如下幾個(gè)作用:

  • 識別系統(tǒng)訪問者的身份信息,認(rèn)證通過后提供給后續(xù)業(yè)務(wù)使用。
  • 給授權(quán)流程提供訪問者身份信息(資源沒有指定特定認(rèn)證方案時(shí),采用默認(rèn)認(rèn)證方案認(rèn)證通過的用戶信息)。
  • 實(shí)現(xiàn)授權(quán)失敗后的處理邏輯,比如授權(quán)檢查失敗后返回的 401(未認(rèn)證),403(禁止訪問)等最終都是認(rèn)證方案的 ChallegeAsync方法以及ForbidAsync方法來處理,這些方法是IAuthenticationHandler里面定義的,這些流程在授權(quán)失敗為401/403的時(shí)候分別被授權(quán)流程調(diào)用。

授權(quán)流程主要如下幾個(gè)作用:

  • 授權(quán)流程主要是檢查當(dāng)前用戶是否具備指定資源的訪問權(quán)限,如果授權(quán)檢查失敗,如401(未認(rèn)證),403(禁止訪問),那么最終會(huì)分別調(diào)用認(rèn)證方案的ChallegenAsync和ForbidAsync方法,也就是說,授權(quán)流程側(cè)重于授權(quán)失敗后的流程控制。
  • 授權(quán)流程另外一個(gè)主要的任務(wù)是檢查授權(quán)策略是否均能檢驗(yàn)通過,如果一個(gè)資源通過AuthorizeAttribute的Policy屬性指定了一個(gè)或者多個(gè)授權(quán)策略,那么必須所有授權(quán)策略都驗(yàn)證通過才算授權(quán)成功,如果未指定授權(quán)策略,那么就驗(yàn)證默認(rèn)的授權(quán)策略是否能檢驗(yàn)通過,默認(rèn)的授權(quán)策略則是要求必須用戶認(rèn)證通過才允許訪問資源。

授權(quán)流程本質(zhì)上就是遍歷所有注入到容器中的IAuthorizationHandler(微軟默認(rèn)在AddAuthorization的時(shí)候向容器注入了:PassThroughAuthorizationHandler,這個(gè)授權(quán)處理程序遍歷AuthorizationHandlerContext.Requirements中所有實(shí)現(xiàn)了IAuthorizationHandler的Requirement類,并調(diào)用其HandleAsync方法來檢查當(dāng)前Requirement是否能校驗(yàn)通過),并對訪問指定資源所要滿足的所有策略中包含的Requirement進(jìn)行驗(yàn)證,如果所有策略包含的Requirement都驗(yàn)證通過,那么表示授權(quán)成功,這里的Requirement是指實(shí)現(xiàn)了IAuthorizationRequirement的類,這個(gè)接口是一個(gè)空接口,用于標(biāo)記Requirement使用。

以上就是asp.net core 認(rèn)證和授權(quán)實(shí)例詳解的詳細(xì)內(nèi)容,更多關(guān)于asp.net core 認(rèn)證授權(quán)的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 在asp.NET 中使用SMTP發(fā)送郵件的實(shí)現(xiàn)代碼

    在asp.NET 中使用SMTP發(fā)送郵件的實(shí)現(xiàn)代碼

    本文簡單介紹了SMTP協(xié)議(RFC2554)發(fā)送郵件的過程,并討論了在 .NET 中使用SMTP發(fā)送郵件由簡到繁的三種不同方案、各自可能遇到的問題及其解決辦法
    2011-05-05
  • asp.net core MVC之實(shí)現(xiàn)基于token的認(rèn)證

    asp.net core MVC之實(shí)現(xiàn)基于token的認(rèn)證

    這篇文章主要介紹了asp.net core MVC之實(shí)現(xiàn)基于token的認(rèn)證,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-05-05
  • asp.net(C#)跨域及跨域?qū)慍ookie問題

    asp.net(C#)跨域及跨域?qū)慍ookie問題

    在網(wǎng)站www.A.com下通過iframe或ajax調(diào)用www.B.com下的內(nèi)容時(shí),默認(rèn)情況下IE會(huì)阻止www.B.com寫任何Cookie
    2011-10-10
  • .NET實(shí)現(xiàn)魔方游戲(一)之任意階魔方的表示

    .NET實(shí)現(xiàn)魔方游戲(一)之任意階魔方的表示

    這篇文章主要介紹了.NET實(shí)現(xiàn)魔方游戲(一)之任意階魔方的表示 的相關(guān)資料,需要的朋友可以參考下
    2016-02-02
  • ASP.NET Web.config配置文件詳解

    ASP.NET Web.config配置文件詳解

    這篇文章主要為大家詳細(xì)介紹了ASP.NET Web.config配置文件,教大家如何配置Web.config文件,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • 淺析常用分詞算法的比較與設(shè)想

    淺析常用分詞算法的比較與設(shè)想

    這篇文章介紹了常用分詞算法的比較與設(shè)想,有需要的朋友可以參考一下
    2013-10-10
  • ASP.NET中常用的三十三種代碼

    ASP.NET中常用的三十三種代碼

    ASP.NET中常用的三十三種代碼...
    2007-03-03
  • .NET微信公眾號查看關(guān)注者接口

    .NET微信公眾號查看關(guān)注者接口

    這篇文章主要為大家詳細(xì)介紹了.NET微信公眾號查看關(guān)注者接口的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-10-10
  • .net開發(fā)人員常犯的錯(cuò)誤分析小結(jié)

    .net開發(fā)人員常犯的錯(cuò)誤分析小結(jié)

    我最新一直在和新手和入手級開發(fā)人員打交道,我注意到一些開發(fā)人員(甚至是老手)在粗心時(shí)常犯的錯(cuò)誤。這些錯(cuò)誤各不相同,從工具的使用到網(wǎng)絡(luò)服務(wù)的適當(dāng)應(yīng)用都有。以下是六個(gè)主要的開發(fā)錯(cuò)誤。
    2009-03-03
  • .NET集成ORM框架HiSql

    .NET集成ORM框架HiSql

    這篇文章介紹了.NET集成ORM框架HiSql的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-07-07

最新評論