首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么身份验证Cookie不针对[授权]属性工作?

为什么身份验证Cookie不针对[授权]属性工作?
EN

Stack Overflow用户
提问于 2020-07-31 08:31:14
回答 3查看 3.3K关注 0票数 2

我们试图通过Cookies在我们的Blazor-WebAssembly应用程序中实现身份验证。

控制器:设置8月饼干:

代码语言:javascript
复制
[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具有一个搜索-操作,并且应该通过添加授权属性来限制访问:

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

当我对/Clients?search=My Search Text执行HTTP时,边缘的开发人员工具告诉我,有一个对/Account/Login的请求。这让我很困惑,因为响应代码是200,但在我的项目中不存在Account-Controller。

为什么我的身份验证Cookie不针对[Authorize] 属性工作?

关于我的配置的一些更详细的信息:

Startup.cs (服务器端)

代码语言:javascript
复制
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");
        });
    }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-07-31 09:21:46

如果您看到在您使用cookie身份验证方案显式登录之后,在未来的请求中无法识别用户,那么这说明您没有正确地配置身份验证中间件。作为按照医生的说法,您不仅必须使用services.AddAuthentication(…)添加身份验证服务,而且还必须配置身份验证中间件以作为请求管道的一部分运行。这通常如下所示:

代码语言:javascript
复制
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()调用:

代码语言:javascript
复制
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(options =>
    {
        options.LoginPath = "/Auth/Login"; // using the AuthController instead
    });

现在,当用户受到挑战时,他们将被重定向到您的AuthController.Login操作,而不是他们应该登录的位置。

请注意,cookie方案将向登录操作添加一个请求参数ReturnUrl,其中包含用户最初试图访问的页面的路径。例如,当访问您的搜索操作时,它们将被重定向到/Auth/Login?ReturnUrl=%2FClients%2Fsearch。因此,您应该接受这个路由参数,并在登录完成后返回到该路由,例如:

代码语言:javascript
复制
[HttpPost]
public async Task<IActionResult> Login(Credentials pCredentials, string returnUrl)
{
    // do login

    return LocalRedirect(returnUrl);
}

还可以通过更改ReturnUrl,将参数CookieAuthenticationOptions.ReturnUrlParameter的名称更改为任何您喜欢的名称。

票数 6
EN

Stack Overflow用户

发布于 2020-07-31 10:09:57

您将被重定向到“登录页”(Login)或returnURL,因为您的身份验证工作不正常,而且未经授权。默认情况下,当ASP.Net核心无法验证而不是返回401代码时,它会重定向您。

确保您正在以正确的方式实现它,如https://learn.microsoft.com/es-es/aspnet/core/security/authentication/identity?view=aspnetcore-3.1&tabs=visual-studio中所述。

不要忘记在Startup.cs类中的配置方法中添加以下行来添加auth中间件:

代码语言:javascript
复制
app.UseAuthentication();
app.UseAuthorization();

请检查您是否有正确的顺序。(顺序很重要,因为您首先验证,然后它检查您的角色)。

它们还必须放在app.UseRouting()app.UseEndpoints()调用之间。

票数 1
EN

Stack Overflow用户

发布于 2020-07-31 11:41:29

我自己得到了它,使用[Authorize(AuthenticationSchemes = AuthSchemes)] fpr我在控制器中的动作。以下是代码:

代码语言:javascript
复制
[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://learn.microsoft.com/de-de/aspnet/core/security/authorization/limitingidentitybyscheme?view=aspnetcore-3.1

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63188383

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档