国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

ASP.NET Core Web API下基于Keycloak的多租戶(hù)用戶(hù)授權(quán)的實(shí)現(xiàn)

這篇具有很好參考價(jià)值的文章主要介紹了ASP.NET Core Web API下基于Keycloak的多租戶(hù)用戶(hù)授權(quán)的實(shí)現(xiàn)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

在上文《Keycloak中授權(quán)的實(shí)現(xiàn)》中,以一個(gè)實(shí)際案例介紹了Keycloak中用戶(hù)授權(quán)的設(shè)置方法。現(xiàn)在回顧一下這個(gè)案例:

  1. 服務(wù)供應(yīng)商(Service Provider)發(fā)布/WeatherForecast API供外部訪(fǎng)問(wèn)
  2. 在企業(yè)應(yīng)用(Client)里有三個(gè)用戶(hù):super,daxnet,nobody
  3. 在企業(yè)應(yīng)用里有兩個(gè)用戶(hù)組:administrators,users
  4. 在企業(yè)應(yīng)用里定義了兩個(gè)用戶(hù)角色:administrator,regular user
  5. super用戶(hù)同時(shí)屬于users和administrators組,daxnet屬于users組,nobody不屬于任何組
  6. administrators組被賦予了administrator角色,users組被賦予了regular user角色
  7. 對(duì)于/WeatherForecast API,它支持兩種操作:GET /WeatherForecast,用以返回天氣預(yù)報(bào)數(shù)據(jù);PATCH /WeatherForecast,用以調(diào)整天氣預(yù)報(bào)數(shù)據(jù)
  8. 擁有administrator角色的用戶(hù)/組,具有PATCH操作的權(quán)限;擁有regular user角色但沒(méi)有administrator角色的用戶(hù)/組,具有GET操作的權(quán)限;沒(méi)有任何角色的用戶(hù),就沒(méi)有訪(fǎng)問(wèn)/WeatherForecast API的權(quán)限

于是,基于這個(gè)需求,我們?cè)贙eycloak的一個(gè)Client下,進(jìn)行了如下與授權(quán)有關(guān)的配置:

  1. 創(chuàng)建了weather-api的Resource
  2. 創(chuàng)建了weather.read、weather.update兩個(gè)Scope
  3. weather-api具有weather.read、weather.update兩個(gè)授權(quán)Scope
  4. 新建了三個(gè)用戶(hù):super, daxnet, nobody
  5. 新建了兩個(gè)用戶(hù)組:administrators,users
  6. 新建了兩個(gè)角色:administrator,regular user
  7. super用戶(hù)同時(shí)屬于administrators和users兩個(gè)用戶(hù)組;daxnet用戶(hù)僅屬于users組,而nobody不屬于任何組
  8. administrators用戶(hù)組被賦予了administrator角色,users組被賦予了regular user角色
  9. 定義了兩個(gè)基于角色的授權(quán)策略:
    1. require-admin-policy:期望資源訪(fǎng)問(wèn)方已被賦予administrator角色
    2. require-registered-user:期望資源訪(fǎng)問(wèn)方已被賦予regular user角色
  10. 定義了兩個(gè)權(quán)限,表示對(duì)什么樣的授權(quán)策略允許訪(fǎng)問(wèn)什么樣的資源:
    1. weather-view-permission:對(duì)于require-registered-user策略,具有weather.read操作的權(quán)限
    2. weather-modify-permission:對(duì)于require-admin-policy策略,具有weather.update操作的權(quán)限

接下來(lái)的一步,就是在應(yīng)用程序中實(shí)現(xiàn)一套機(jī)制,通過(guò)這套機(jī)制來(lái)控制用戶(hù)(資源訪(fǎng)問(wèn)方)對(duì)API(資源)的訪(fǎng)問(wèn)。

思考:ASP.NET Core標(biāo)準(zhǔn)授權(quán)模型能滿(mǎn)足需求嗎?

ASP.NET Core已經(jīng)提供了一套易學(xué)易用的授權(quán)組件,包括AuthorizeAttribute、IAuthorizationHandler、IAuthorizationRequirement、IAuthorizationFilter等,使用這些組件,可以方便地實(shí)現(xiàn)基于角色(Role)和基于策略(Policy)的授權(quán)機(jī)制。在使用AuthorizeAttribute特性來(lái)完成授權(quán)時(shí),可以指定被賦予哪些角色的用戶(hù)可以獲得授權(quán),也可以指定一個(gè)策略名稱(chēng),只要是滿(mǎn)足該策略下各條件的用戶(hù),就可以獲得授權(quán)。

如果是基于角色,首先需要在AuthorizeAttribute上指定Roles屬性,然后在配置JwtBearer Authentication的時(shí)候,在TokenValidationParameter上,設(shè)置RoleClaimType,這樣一來(lái),框架就會(huì)從認(rèn)證用戶(hù)的access token中獲得由RoleClaimType指定的Claim中所包含的角色信息,然后判斷它是否已在AuthorizationAttribute.Roles屬性上指定,從而進(jìn)一步判斷該用戶(hù)是否可以獲得授權(quán)。

如果是基于策略,那么就需要自己實(shí)現(xiàn)IAuthorizationHandlerIAuthorizationRequirement接口,在這些接口的實(shí)現(xiàn)中,基于Claims來(lái)判斷該用戶(hù)是否可以獲得授權(quán),所以在ASP.NET Core中,這種授權(quán)也稱(chēng)作“基于Claim的授權(quán)”,只不過(guò)策略就是基于Claim數(shù)據(jù)的判定結(jié)果而已。具體實(shí)現(xiàn)方式可以參考這篇官方文檔,這里不再贅述。

不管是基于角色,還是基于策略(或者基于Claim),一個(gè)用戶(hù)是否可被授權(quán),判斷條件都是看這個(gè)用戶(hù)是否已被賦予某個(gè)角色(超級(jí)管理員?管理員?普通用戶(hù)?),或者它自身的屬性是否滿(mǎn)足某個(gè)或某幾個(gè)條件(年齡?性別?是否誠(chéng)信有問(wèn)題?或者是這些條件的組合?)。當(dāng)應(yīng)用程序僅服務(wù)于一個(gè)客戶(hù)時(shí),基于角色的授權(quán)(RBAC)或者基于Claim的授權(quán)都是沒(méi)有問(wèn)題的,因?yàn)閱吾槍?duì)這個(gè)客戶(hù)而言,需求相對(duì)是比較簡(jiǎn)單的:該公司對(duì)用戶(hù)的角色定義僅有超級(jí)管理員、管理員和普通用戶(hù)三種,并且該公司下的所有用戶(hù)的個(gè)人信息都包含年齡和性別兩個(gè)字段,并且這兩個(gè)字段始終有值。當(dāng)然,如果需要擴(kuò)展出新的角色,或者在用戶(hù)個(gè)人信息上加入新的字段并使其成為判斷條件,那么還是需要修改源代碼并重新部署整個(gè)應(yīng)用。

在多租戶(hù)的云服務(wù)中,情況就變得復(fù)雜,在《在Keycloak中實(shí)現(xiàn)多租戶(hù)并在ASP.NET Core下進(jìn)行驗(yàn)證》一文中,我介紹過(guò)如何基于Keycloak設(shè)計(jì)多租戶(hù)的認(rèn)證模型,其中有兩個(gè)主要觀(guān)點(diǎn):1、租戶(hù)間數(shù)據(jù)隔離;2、在Single Realm下使用不同的Client區(qū)分不同的租戶(hù)。在Keycloak中,授權(quán)的設(shè)定是基于Client,這也就意味著,不同的租戶(hù)可以選擇使用完全不同的授權(quán)模型。不僅如此,用戶(hù)角色(Role)的設(shè)計(jì)也是按Client區(qū)分的,所以,不同的租戶(hù)可以有完全不同的用戶(hù)角色定義:A租戶(hù)下的用戶(hù)不分角色,所有用戶(hù)都是User角色;B租戶(hù)下的用戶(hù)分管理員和普通用戶(hù)兩種角色。更進(jìn)一步,對(duì)于某個(gè)API,A租戶(hù)希望只有年滿(mǎn)18歲的用戶(hù)才能訪(fǎng)問(wèn),而B(niǎo)租戶(hù)則指定僅有管理員才能訪(fǎng)問(wèn)。

如果在ASP.NET Core中單純使用AuthorizeAttribute配合基于角色或者基于Claim的授權(quán),你會(huì)發(fā)現(xiàn),你無(wú)法在AuthorizeAttribute上指定角色的名稱(chēng),因?yàn)椴煌鈶?hù)不一定都會(huì)使用相同的角色名稱(chēng);也無(wú)法在AuthorizeAttribute上指定一個(gè)Policy的名稱(chēng),并正確地實(shí)現(xiàn)這個(gè)Policy的邏輯,因?yàn)椴煌鈶?hù)下登錄的用戶(hù)ClaimsPrincipal中不一定會(huì)帶上授權(quán)所需的Claim(因?yàn)樵撟鈶?hù)壓根就沒(méi)有定義這樣的Claim)。

所以,在多租戶(hù)環(huán)境下,授權(quán)應(yīng)該基于應(yīng)用本身能夠提供什么,而不是租戶(hù)或者租戶(hù)下的用戶(hù)能夠提供什么。對(duì)于一個(gè)ASP.NET Core Web API應(yīng)用來(lái)說(shuō),資源(Resource)和操作(Scope)是根據(jù)應(yīng)用程序的API設(shè)計(jì)而設(shè)計(jì)的,與租戶(hù)和租戶(hù)下的用戶(hù)沒(méi)有關(guān)系。所以,在多租戶(hù)應(yīng)用中,授權(quán)應(yīng)該基于Resource和Scope來(lái)實(shí)現(xiàn)。

設(shè)計(jì):ASP.NET Core下基于Resource和Scope的授權(quán)

仍然以Weather API為例,在獲取天氣數(shù)據(jù)的時(shí)候,就會(huì)定義一個(gè)Get的API,這個(gè)API就是應(yīng)用里的一個(gè)Resource,并且這個(gè)API能夠提供的Scope為Read,表示這個(gè)Resource是可以被讀取的。那么,很有可能這個(gè)Get Weather的API就有類(lèi)似這樣的定義(具體實(shí)現(xiàn)部分省略):

[ProtectedResource("weather-api", "weather.read")]
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
    return Ok();
}

ProtectedResourceAttribute特性指定了當(dāng)前被修飾的方法為一個(gè)受保護(hù)的資源,該資源名為weather-api,它能提供的Scope為weather.read。因此,只要訪(fǎng)問(wèn)該API的User(ClaimsPrincipal)對(duì)weather-api這種Resource具有weather.read操作,就可以允許該用戶(hù)訪(fǎng)問(wèn)此API。那么User如何才可以對(duì)weather-api這種Resource進(jìn)行weather.read操作呢?這部分內(nèi)容在上一篇文章中已經(jīng)詳細(xì)介紹過(guò)了,只需要在Keycloak中合理地配置策略(Policies)和授權(quán)(Permissions)即可。由于Policy不僅可以基于角色,而且可以基于用戶(hù)、用戶(hù)組、正則表達(dá)式等,甚至可以進(jìn)行組合,因此,對(duì)于不同的Client(租戶(hù)),可以定義非常靈活的授權(quán)策略,比如:定義一個(gè)策略,該策略指定用戶(hù)需要滿(mǎn)足的條件為:屬于“銷(xiāo)售科”用戶(hù)組,并且工作年限大于10年,然后在授權(quán)的配置部分,指定對(duì)于weather-api Resource,滿(mǎn)足該策略的訪(fǎng)問(wèn)方可以執(zhí)行weather.read操作即可。

在ASP.NET Core中,ProtectedResourceAttribute需要實(shí)現(xiàn)為IAuthorizationFilter(或者IAsyncAuthorizationFilter),這樣就可以使得API在被調(diào)用之前,可以檢查訪(fǎng)問(wèn)者是否有權(quán)限訪(fǎng)問(wèn)。由于不需要使用基于角色或者基于標(biāo)準(zhǔn)Claims的授權(quán),所以不需要繼承于AuthorizeAttribute。在ProtectedResourceAttribute的實(shí)現(xiàn)邏輯中,判斷當(dāng)前ClaimsPrincipal是否具有對(duì)當(dāng)前受保護(hù)資源的操作權(quán)限就行了,那么如何進(jìn)行判斷?就需要在ProtectedResourceAttribute執(zhí)行前,將這些信息附加到ClaimsPrincipal上。

在OIDC的認(rèn)證和授權(quán)體系中,通過(guò)authentication flow獲得的access token往往不會(huì)包含授權(quán)相關(guān)的信息,這是出于性能考慮。在有些情況下,授權(quán)信息會(huì)比較復(fù)雜龐大,認(rèn)證的時(shí)候?qū)⑹跈?quán)信息附加在token中,會(huì)大大增加token的大小,讓authentication flow變得不是那么的輕量。在Keycloak中,通常都是首先獲得access token,然后將access token用作Bearer token再次調(diào)用token API端點(diǎn),并將grant_type設(shè)置為urn:ietf:params:oauth:grant-type:uma-ticket以獲得授權(quán)信息,這個(gè)步驟在上一篇文章中也介紹過(guò)。因此,看上去我們不得不在獲得access token之后的某個(gè)時(shí)間點(diǎn),再次調(diào)用Keycloak的token API端點(diǎn),也就是需要第二次的API調(diào)用來(lái)完成授權(quán)信息的獲得。

我們當(dāng)然可以考慮在ProtectedResourceAttribute的代碼里調(diào)用這個(gè)API來(lái)獲得授權(quán)信息,但這并不是推薦做法。通常情況下,IAuthorizationFilter中,應(yīng)該只通過(guò)附加在ClaimsPrincipal上的Claims做判斷,而不應(yīng)該在其中又調(diào)用第二個(gè)API來(lái)獲取信息。一個(gè)比較合理的做法是,在authorization flow中,當(dāng)發(fā)生“token已被校驗(yàn)事件”(OnTokenValidated)時(shí),調(diào)用API以獲得授權(quán)信息,然后將獲得的授權(quán)信息附加到當(dāng)前ClaimsPrincipal的Claims上,進(jìn)而就可以在ProtectedResourceAttribute里進(jìn)行授權(quán)判定了。當(dāng)然,即使是在OnTokenValidated事件中調(diào)用API,也還是會(huì)存在性能問(wèn)題,所以,在真實(shí)場(chǎng)景中,應(yīng)該考慮將獲得的授權(quán)信息緩存起來(lái),但這又帶來(lái)新的問(wèn)題:何時(shí)應(yīng)該刷新緩存。不過(guò)現(xiàn)在我們暫時(shí)不考慮這些。

因此,整個(gè)模型的設(shè)計(jì)大概如下圖所示:

ASP.NET Core Web API下基于Keycloak的多租戶(hù)用戶(hù)授權(quán)的實(shí)現(xiàn)

我們可以設(shè)計(jì)一個(gè)IPermissionService的接口,接口中有一個(gè)方法:ReadPermissionClaimsAsync,用于使用當(dāng)前已認(rèn)證過(guò)的access token換取授權(quán)信息,并以一組Claims的形式返回。單獨(dú)設(shè)計(jì)這個(gè)接口的目的就在于方便今后加入緩存這樣的邏輯。在OnTokenValidated事件中,通過(guò)ASP.NET Core的IoC/DI獲得IPermissionService的實(shí)例,然后調(diào)用ReadPermissionClaimsAsync方法獲得授權(quán)相關(guān)的Claims,并將這些Claims附加到ClaimsPrincipal上。另一方面,當(dāng)ProtectedResourceAttribute執(zhí)行授權(quán)邏輯時(shí),將ClaimsPrincipal上與授權(quán)相關(guān)的Claims的值與當(dāng)前Resource的名稱(chēng)和Scope進(jìn)行比較,即可判定是否應(yīng)該授予相關(guān)權(quán)限。

實(shí)現(xiàn):ASP.NET Core中授權(quán)的實(shí)現(xiàn)

上面已經(jīng)分析得比較徹底了,現(xiàn)在直接上代碼。首先就是定義并實(shí)現(xiàn)IPermissionService接口:

public interface IPermissionService
{
    Task<IEnumerable<Claim>?> ReadPermissionClaimsAsync(string bearerToken, string audience, string requestUri);
}

public sealed class PermissionService(IHttpClientFactory httpClientFactory) : IPermissionService
{
    public async Task<IEnumerable<Claim>?> ReadPermissionClaimsAsync(string bearerToken, string audience,
        string requestUri)
    {
        var result = new List<Claim>();
        using var httpClient = httpClientFactory.CreateClient("JwtTokenClient");
        httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", bearerToken);
        var payload = new Dictionary<string, string>
        {
            { "grant_type", "urn:ietf:params:oauth:grant-type:uma-ticket" },
            { "audience", audience }
        };

        var request = new HttpRequestMessage(HttpMethod.Post, requestUri)
        {
            Content = new FormUrlEncodedContent(payload)
        };

        try
        {
            var response = await httpClient.SendAsync(request);
            response.EnsureSuccessStatusCode();
            var responseJson = await response.Content.ReadAsStringAsync();
            var responseJsonObject = JObject.Parse(responseJson);
            var authTokenString = responseJsonObject["access_token"]?.Value<string>();
            if (string.IsNullOrEmpty(authTokenString))
                return null;

            var tokenHandler = new JwtSecurityTokenHandler();
            var authToken = tokenHandler.ReadJwtToken(authTokenString);
            var authClaim = authToken.Claims.FirstOrDefault(a => a.Type == "authorization");
            if (authClaim is null)
                return null;

            var authObject = JObject.Parse(authClaim.Value);
            if (authObject["permissions"] is not JArray permissionsArray)
                return null;

            foreach (var permissionObj in permissionsArray)
            {
                var accessibleResource = permissionObj["rsname"]?.Value<string>();
                if (string.IsNullOrEmpty(accessibleResource))
                    continue;
                var allowedScopes = new List<string?>();
                var scopesObj = permissionObj["scopes"];
                if (scopesObj is JArray scopesArray)
                {
                    allowedScopes.AddRange(scopesArray.Select(s => s.Value<string>())
                        .Where(val => !string.IsNullOrEmpty(val)));
                }

                result.Add(new Claim($"res:{accessibleResource}",
                    string.Join(",", allowedScopes)));
            }

            return result;
        }
        catch
        {
            return null;
        }
    }
}

然后,在OnTokenValidated事件中,調(diào)用IPermissionService,并將獲得的Claims附加到ClaimsPrincipal上:

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        // 其它配置省略
        options.Events = new JwtBearerEvents
        {
            OnTokenValidated = async context =>
            {
                if (context is { Principal.Identity: ClaimsIdentity claimsIdentity } and
                    { SecurityToken: JsonWebToken jwt })
                {
                    var bearerToken = jwt.EncodedToken;
                    var permissionService = context.HttpContext.RequestServices.GetService<IPermissionService>();
                    if (permissionService is not null)
                    {
                        var permissionClaims = await permissionService.ReadPermissionClaimsAsync(bearerToken,
                            "weatherapiclient", "/realms/aspnetcoreauthz/protocol/openid-connect/token");
                        var permissionClaimsList = permissionClaims?.ToList();
                        permissionClaimsList?.ForEach(claim => claimsIdentity.AddClaim(claim));
                    }
                }
            }
        };
    });

// 不要忘記注冊(cè)相關(guān)的Service
builder.Services.AddSingleton<IPermissionService, PermissionService>();
builder.Services.AddHttpClient("JwtTokenClient", client =>
{
    client.BaseAddress = new Uri("http://localhost:5600/");

});

?然后實(shí)現(xiàn)ProtectedResourceAttribute:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class ProtectedResourceAttribute(string resourceName, params string[] allowedScopes) : Attribute,
    IAsyncAuthorizationFilter
{
    public string ResourceName { get; } = resourceName;

    public string[] AllowedScopes { get; } = allowedScopes;

    public Task OnAuthorizationAsync(AuthorizationFilterContext context)
    {
        var user = context.HttpContext.User;
        if (user is { Identity.IsAuthenticated: false })
        {
            // 若未認(rèn)證,返回403
            context.Result = new ForbidResult();
        }
        else
        {
            // 從user claims中獲得與當(dāng)前資源名稱(chēng)相同的permission claim
            var permissionClaim = user.Claims.FirstOrDefault(c => c.Type == $"res:{ResourceName}");
            if (permissionClaim is not null)
            {
                // 若存在permission claim
                if (AllowedScopes.Length == 0)
                {
                    // 并且在當(dāng)前資源上并未定義所支持的scope,則說(shuō)明任何scope都可以接受,直接返回
                    return Task.CompletedTask;
                }

                // 否則,檢查permission claim中是否有包含當(dāng)前資源所支持的scope
                var permittedScopes = permissionClaim.Value.Split(',');

                // 如果不存在,則返回403
                if (permittedScopes.Length == 0 || !AllowedScopes.Intersect(permittedScopes).Any())
                {
                    context.Result = new ForbidResult();
                }
            }
            else
            {
                // 如果user claims中不存在與當(dāng)前資源對(duì)應(yīng)的permission claim,則返回403
                context.Result = new ForbidResult();
            }
        }

        return Task.CompletedTask;
    }
}

最后,在API上使用ProtectedResourceAttribute:

[ProtectedResource("weather-api", "weather.read")]
[HttpGet]
public IEnumerable<WeatherForecast> Get()
{
    return Enumerable.Range(1, 5).Select(index => new WeatherForecast
    {
        Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
        TemperatureC = Random.Shared.Next(-20, 55),
        Summary = Summaries[Random.Shared.Next(Summaries.Length)]
    })
    .ToArray();
}

[ProtectedResource("weather-api", "weather.update")]
[HttpPost]
public IActionResult Update()
{
    return Ok("Succeeded");
}

執(zhí)行測(cè)試

現(xiàn)在來(lái)簡(jiǎn)單測(cè)試一下,就測(cè)一個(gè)case:nobody用戶(hù)應(yīng)該對(duì)weather.read和weather.update都不具有訪(fǎng)問(wèn)權(quán)限:

首先獲得access token:

ASP.NET Core Web API下基于Keycloak的多租戶(hù)用戶(hù)授權(quán)的實(shí)現(xiàn)

然后使用該token,調(diào)用Get請(qǐng)求,返回403 Forbidden:

ASP.NET Core Web API下基于Keycloak的多租戶(hù)用戶(hù)授權(quán)的實(shí)現(xiàn)

然后調(diào)用Post請(qǐng)求,同樣403:

ASP.NET Core Web API下基于Keycloak的多租戶(hù)用戶(hù)授權(quán)的實(shí)現(xiàn)

現(xiàn)在Keycloak中,將nobody用戶(hù)加入到Users組:

ASP.NET Core Web API下基于Keycloak的多租戶(hù)用戶(hù)授權(quán)的實(shí)現(xiàn)

然后重新生成Bearer token,再次調(diào)用Get API,發(fā)現(xiàn)現(xiàn)在可以正常訪(fǎng)問(wèn)了:

ASP.NET Core Web API下基于Keycloak的多租戶(hù)用戶(hù)授權(quán)的實(shí)現(xiàn)

但是Post API仍然返回403:

ASP.NET Core Web API下基于Keycloak的多租戶(hù)用戶(hù)授權(quán)的實(shí)現(xiàn)

這是因?yàn)?,Post API需要在weather-api這個(gè)Resource上具有weather.update Scope(操作),然而,在weather-modify-permission的定義中,weather.update Scope所依賴(lài)的策略為require-admin-policy,該策略要求用戶(hù)具有administrator角色,但nobody只在users用戶(hù)組中,它并不在已被賦予administrator角色的administrators用戶(hù)組中。于是,就當(dāng)前這個(gè)租戶(hù)而言,在整個(gè)權(quán)限系統(tǒng)的模型設(shè)計(jì)中,我們已經(jīng)實(shí)現(xiàn)了無(wú)需修改代碼的靈活的授權(quán)管理,而且這種模式可以被其它租戶(hù)重用。

?文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-855773.html

到了這里,關(guān)于ASP.NET Core Web API下基于Keycloak的多租戶(hù)用戶(hù)授權(quán)的實(shí)現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶(hù)投稿,該文觀(guān)點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • ASP.NET Core 中的兩種 Web API

    ASP.NET Core 有兩種創(chuàng)建 RESTful Web API 的方式: 基于 Controller,使用完整的基于ControllerBase的基類(lèi)定義接口endpoints。 基于 Minimal APIs,使用Lambda表達(dá)式定義接口 endpoints。 基于 Controller 的 Web API 可以使用構(gòu)造函數(shù)注入,或者屬性注入,遵循面向?qū)ο竽J健?基于 Minimal APIs 的 Web API 通

    2024年02月09日
    瀏覽(33)
  • ASP.NET Core Web API 流式返回,逐字顯示

    ASP.NET Core Web API 流式返回,逐字顯示

    Websocket、SSE(Server-Sent Events)和長(zhǎng)輪詢(xún)(Long Polling)都是用于網(wǎng)頁(yè)和服務(wù)端通信的技術(shù)。 Websocket是一種全雙工通信協(xié)議,能夠?qū)崿F(xiàn)客戶(hù)端和服務(wù)端之間的實(shí)時(shí)通信。它基于TCP協(xié)議,并且允許服務(wù)器主動(dòng)向客戶(hù)端推送數(shù)據(jù),同時(shí)也允許客戶(hù)端向服務(wù)器發(fā)送數(shù)據(jù)。 SSE是一種單向

    2023年04月23日
    瀏覽(21)
  • ASP.NET Core Web API之Token驗(yàn)證

    ASP.NET Core Web API之Token驗(yàn)證

    在實(shí)際開(kāi)發(fā)中,我們經(jīng)常需要對(duì)外提供接口以便客戶(hù)獲取數(shù)據(jù),由于數(shù)據(jù)屬于私密信息,并不能隨意供其他人訪(fǎng)問(wèn),所以就需要驗(yàn)證客戶(hù)身份。那么如何才能驗(yàn)證客戶(hù)的什么呢?今天以一個(gè)簡(jiǎn)單的小例子,簡(jiǎn)述ASP.NET Core Web API開(kāi)發(fā)過(guò)程中,常用的一種JWT身份驗(yàn)證方式。僅供學(xué)

    2024年02月11日
    瀏覽(22)
  • ASP.NET Core Web API入門(mén)之三:使用EF Core

    ASP.NET Core Web API入門(mén)之三:使用EF Core

    一般來(lái)講我們做項(xiàng)目都會(huì)用實(shí)體類(lèi)跟數(shù)據(jù)庫(kù)實(shí)體進(jìn)行關(guān)系對(duì)應(yīng),這樣的好處方便我們維護(hù)、增刪改查,并且可以減少SQL的編寫(xiě),從而統(tǒng)一風(fēng)格,那么 Entity Framework Core 就是很不錯(cuò)的ORM框架。 1、跨數(shù)據(jù)庫(kù)支持能力強(qiáng)大,只需修改配置就可以輕松實(shí)現(xiàn)數(shù)據(jù)庫(kù)切換。 2、提升了開(kāi)發(fā)效

    2024年02月10日
    瀏覽(21)
  • 2.1 .net 8 ASP.NET Core Web API - Controller詳解

    2.1 .net 8 ASP.NET Core Web API - Controller詳解

    書(shū)接上回,上節(jié)我們留了幾個(gè)問(wèn)題,即: 1、接口Hello的名字究竟怎么來(lái)的? 2、我們?nèi)绻氚呀涌诟某善渌拿Q(chēng),應(yīng)該怎么做? 3、我們繼承ControllerBase,以及[Route(“[controller]”)]屬性,又是分別起到什么作用? 需要解決以上幾個(gè)問(wèn)題,我們就要繼續(xù)深入研究Controller相關(guān)的

    2024年02月20日
    瀏覽(21)
  • 在 ASP.NET Core Web API 中處理 Patch 請(qǐng)求

    PUT 和 PATCH 方法用于更新現(xiàn)有資源。 它們之間的區(qū)別是,PUT 會(huì)替換整個(gè)資源,而 PATCH 僅指定更改。 在 ASP.NET Core Web API 中,由于 C# 是一種靜態(tài)語(yǔ)言( dynamic 在此不表),當(dāng)我們定義了一個(gè)類(lèi)型用于接收 HTTP Patch 請(qǐng)求參數(shù)的時(shí)候,在 Action 中無(wú)法直接從實(shí)例中得知客戶(hù)端提供了哪

    2024年02月04日
    瀏覽(97)
  • ASP.NET Core 的 Web Api 實(shí)現(xiàn)限流 中間件

    ASP.NET Core 的 Web Api 實(shí)現(xiàn)限流 中間件

    Microsoft.AspNetCore.RateLimiting ?中間件提供速率限制(限流)中間件。 它是.NET 7 以上版本才支持的中間件,剛看了一下,確實(shí)挺好用,下面給大家簡(jiǎn)單介紹一下: RateLimiterOptionsExtensions?類(lèi)提供下列用于限制速率的擴(kuò)展方法:????? 固定窗口限制器 滑動(dòng)窗口限制器 令牌桶限

    2024年01月17日
    瀏覽(18)
  • ASP.NET Core Web API 流式返回,實(shí)現(xiàn)ChatGPT逐字顯示

    ASP.NET Core Web API 流式返回,實(shí)現(xiàn)ChatGPT逐字顯示

    ??作者:科技、互聯(lián)網(wǎng)行業(yè)優(yōu)質(zhì)創(chuàng)作者 ??專(zhuān)注領(lǐng)域:.Net技術(shù)、軟件架構(gòu)、人工智能、數(shù)字化轉(zhuǎn)型、DeveloperSharp、微服務(wù)、工業(yè)互聯(lián)網(wǎng)、智能制造 ??歡迎關(guān)注我(Net數(shù)字智慧化基地),里面有很多 高價(jià)值 技術(shù)文章, 是你刻苦努力也積累不到的經(jīng)驗(yàn) ,能助你快速成長(zhǎng)。升職

    2024年02月22日
    瀏覽(26)
  • asp.net web api 用戶(hù)身份驗(yàn)證

    ? ? ? ? 前后端分離的開(kāi)發(fā)中,應(yīng)用服務(wù)需要進(jìn)行用戶(hù)身份的驗(yàn)證才允許訪(fǎng)問(wèn)數(shù)據(jù)。實(shí)現(xiàn)的方法很簡(jiǎn)單。創(chuàng)建一個(gè)webapi項(xiàng)目。在App_Start目錄下找到WebApiConfig.cs, 在里面增加一個(gè)實(shí)現(xiàn)類(lèi)。 Controller 類(lèi)的實(shí)現(xiàn):

    2024年02月20日
    瀏覽(17)
  • C# ASP.NET Core Web API 身份授權(quán)(JWT)驗(yàn)證(一)

    C# ASP.NET Core Web API 身份授權(quán)(JWT)驗(yàn)證(一)

    1.開(kāi)發(fā)環(huán)境 VS2022,安裝時(shí)記得勾選ASP.NET有關(guān)的都選上,建議全選,省的麻煩。 ???????? 2.創(chuàng)建初始工程 TestApi (你自己的工程名稱(chēng))。 ? ?這就創(chuàng)建工程成功了,按 F5 則可以進(jìn)行調(diào)試了。 而在項(xiàng)目中,我們不僅僅會(huì)用到基礎(chǔ)的api功能,我們一般還會(huì)用到? 身份授權(quán)(J

    2024年02月02日
    瀏覽(29)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包