簡體   English   中英

為什么身份驗證 Cookie 對 [Authorize] 屬性不起作用?

[英]Why is the Authentication Cookie not working against the [Authorize] attribute?

我們嘗試在 Blazor-WebAssembly 應用程序中通過 Cookies 實現身份驗證。

Controller:設置 Auth-Cookie:

[Route("[controller]")]
[ApiController]
public class AuthController : ControllerBase
{
    [HttpPost]
    public async Task<AdUser> Login(Credentials pCredentials)
    {
        // [...] credential check jere

            var lClaims = new List<Claim> {
                new Claim(ClaimTypes.Name, "SamAccountName"),
            };
            var lClaimsIdentity = new ClaimsIdentity(lClaims, CookieAuthenticationDefaults.AuthenticationScheme);

            // set cookie
            await HttpContext.SignInAsync(
            CookieAuthenticationDefaults.AuthenticationScheme,
            new ClaimsPrincipal(lClaimsIdentity),
            new AuthenticationProperties
            {
                IsPersistent = true,
                ExpiresUtc = DateTime.UtcNow.AddYears(1),
                RedirectUri = this.Request.Host.Value
            });

        // [...]
    }
}

當我查看邊緣瀏覽器的開發人員工具時,我可以看到,cookie 已設置:

在此處輸入圖像描述

現在下面的Controller有一個 Search-Action 並且應該通過添加 [Authorize] 屬性來限制訪問:

[Route("[controller]")]
[ApiController]
public class ClientsController : ControllerBase
{
    [HttpGet("search")]
    [Authorize]
    public ActionResult<List<Shared.Client>> Search(string pText)
    {
        // [...] Code here
        
        return lResult;
    }
}

當我對 ClientsController 執行 HTTP-Request /Clients?search=My Search Text時,Edge 的開發人員工具向我顯示,有一個對/Account/Login的請求。 這讓我很困惑,因為響應代碼是 200,但我的項目中不存在 Account-Controller。

為什么我的身份驗證 Cookie 對[Authorize]屬性不起作用?

在此處輸入圖像描述

有關我的配置的更多詳細信息:

Startup.cs (服務器端)

namespace BlazorWebAssemblyApp.Server
{
    public class Startup
    {
        /// [...]

        public void ConfigureServices(IServiceCollection services)
        {
            // [...]
            services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(); // This line is required for the authentication cookie       
            // [...]
        }
    }
    
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        // [...]

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapRazorPages();
            endpoints.MapControllers();
            endpoints.MapFallbackToFile("index.html");
        });
    }
}

如果您在使用 cookie 身份驗證方案顯式登錄后發現用戶在將來的請求中無法識別,則表明您沒有正確配置身份驗證中間件。 根據文檔,您不僅需要使用services.AddAuthentication(…)添加身份驗證服務,還必須配置身份驗證中間件以作為請求管道的一部分運行。 這通常看起來像這樣:

app.UseRouting();

// add the call to `UseAuthentication`
app.UseAuthentication();
app.UseAuthorization();

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
});

通過將UseAuthentication()調用添加到中間件中,您將導致默認身份驗證方案(在您的情況下為 cookie 方案)嘗試對用戶進行身份驗證。 這確保如果請求中有一個身份驗證 cookie,那么它將用於對用戶進行身份驗證,無論您是否要訪問授權路由。

一旦中間件運行,僅使用[Authorize]屬性保護的操作也將起作用,因為 cookie 方案的身份驗證已經發生(因為它是默認方案)。

否則,如果默認情況下不調用中間件,則需要確保在需要訪問用戶信息時始終顯式調用身份驗證方案。 這就是[Authorize(AuthenticationSchemes = "scheme-name")]所做的:在授權運行之前,它將嘗試對指定的方案進行身份驗證。 – 如果您使用身份驗證中間件並具有正確的默認方案,則可以跳過此步驟,因為該方案將默認進行身份驗證。

在您的原始代碼中,沒有運行身份驗證,這也為您解釋了您被重定向的原因:由於沒有運行身份驗證方案來對用戶進行身份驗證,因此沒有登錄用戶(即使用戶有 cookie) . 所以當用戶被授權時,沒有用戶在那里,你被重定向到登錄頁面。

為什么重定向到/Account/Login

cookie 身份驗證方案是在需要身份驗證(例如通過[Authorize]屬性)但用戶還沒有身份驗證 cookie 時將用戶重定向到登錄頁面所涉及的方案。 在這種情況下,身份驗證將受到“挑戰”,這對於 cookie 方案意味着用戶將被重定向到他們應該登錄的登錄頁面。

默認情況下,登錄頁面的路由配置為/Account/Login 當您使用 ASP.NET 核心標識時,此默認值與默認行為相匹配。 您可以通過更改CookieAuthenticationOptions.LoginPath輕松配置此路由以匹配您的實際登錄頁面。 例如,您可以使用AddCookie()調用來做到這一點:

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(options =>
    {
        options.LoginPath = "/Auth/Login"; // using the AuthController instead
    });

現在,當用戶受到挑戰時,他們將被重定向到您的AuthController.Login操作,而不是他們應該登錄的地方。

請注意,cookie 方案將向登錄操作添加請求參數ReturnUrl ,其中包含用戶最初嘗試訪問的頁面的路徑。 例如,當訪問您的搜索操作時,它們將被重定向到/Auth/Login?ReturnUrl=%2FClients%2Fsearch 因此,您應該接受此路由參數並在登錄完成后返回該路由,例如:

[HttpPost]
public async Task<IActionResult> Login(Credentials pCredentials, string returnUrl)
{
    // do login

    return LocalRedirect(returnUrl);
}

您還可以通過更改CookieAuthenticationOptions.ReturnUrlParameter將參數ReturnUrl的名稱更改為您喜歡的任何名稱。

您將被重定向到“登錄頁面”或 returnURL,因為您的身份驗證無法正常工作並且您正在獲得未經授權。 默認情況下,ASP.Net Core 在驗證失敗時會重定向您,而不是返回 401 代碼。

確保按照https://docs.microsoft.com/es-es/aspnet/core/security/authentication/identity?view=aspnetcore-3.1&tabs=visual-studio中所述的正確方式實施它。

不要忘記在 Startup.cs class 的 Configure 方法中添加以下行以添加 auth 中間件:

app.UseAuthentication();
app.UseAuthorization();

請檢查您的順序是否正確。(順序很重要,因為您首先進行身份驗證,然后檢查您的角色)。

它們還必須放在app.UseRouting()app.UseEndpoints()調用之間。

我自己得到了它,使用[Authorize(AuthenticationSchemes = AuthSchemes)] fpr 我在 controller 中的操作。 這是代碼:

[Route("[controller]")]
[ApiController]
public class ClientsController : ControllerBase
{          
    private const string AuthSchemes = CookieAuthenticationDefaults.AuthenticationScheme;

    [HttpGet("search")]
    [Authorize(AuthenticationSchemes = AuthSchemes)]
    public ActionResult<List<Shared.Client>> Search(Shared.Client.SearchProperty pProperty, string pText)
    {
        // [...]
    }
}

您可以在此處閱讀有關此主題的更多信息: https://docs.microsoft.com/de-de/aspnet/core/security/authorization/limitingidentitybyscheme?view=aspnetcore-3.1

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM