AuthorizeAttribute with JWT Token- .NET Core 2.0 中的身份验证

Posted

技术标签:

【中文标题】AuthorizeAttribute with JWT Token- .NET Core 2.0 中的身份验证【英文标题】:AuthorizeAttribute with JWT Token- Authentication in .NET Core 2.0 【发布时间】:2018-03-24 09:53:49 【问题描述】:

我在运行 .net core 2.0 的 Web-API 中实现了 JWT Bearer Token-Authentication。 现在我创建了另一个与我的 Web-API 对话的网站。检索令牌有效,我将其添加到 cookie 中,当我调试时,我可以看到我的 cookie(名称是“身份”)具有正确的值。

在项目模板中有控制器HomeController 和动作。我将Contact 用于我的目的,并使用AuthorizeAttribute 对其进行注释:

[Authorize]
public IActionResult Contact()

    ViewData["Message"] = "Your contact page.";

    return View();

现在我(作为匿名用户)导航到 /home/contact - 完美:它会将我重定向到我需要登录的 /home/login

当我尝试登录时,我收到以下错误消息:

没有配置 IAuthenticationSignInHandler 来处理方案的登录:Bearer

我猜令牌配置是错误的——我猜这里还有几件事我做错了。

首先,这是我的 Startup.cs(我没有删除任何内容,因为订单有依赖关系):

public void ConfigureServices(IServiceCollection services)

    services.AddDistributedMemoryCache();

    services.AddSession(options =>
    
        options.IdleTimeout = TimeSpan.FromMinutes(30);
        options.Cookie.HttpOnly = true;
    );

    services.AddAuthentication(options =>
    
        options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    )
    .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
    

        options.TokenValidationParameters = new TokenValidationParameters
        
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("mysupersecret_secretkey!123")),
            ValidateIssuer = true,
            ValidIssuer = "ExampleIssuer",
            ValidateAudience = true,
            ValidAudience = "ExampleAudience",
            ValidateLifetime = true,
            ClockSkew = TimeSpan.Zero,
            SaveSigninToken = true
        ;
        options.Events = new JwtBearerEvents
        
            OnTokenValidated = context =>
            
                JwtSecurityToken accessToken = context.SecurityToken as JwtSecurityToken;
                if (accessToken != null)
                
                    ClaimsIdentity identity = context.Result.Principal.Identity as ClaimsIdentity;
                    identity?.AddClaim(new Claim("access_token", accessToken.RawData));
                

                return Task.CompletedTask;
            
        ;
     )
    .AddCookie(
           o =>
           
               o.Cookie.Name = "beareridentity";
               o.LoginPath = new PathString("/Home/Login/");
               o.AccessDeniedPath = new PathString("/Home/Login/");
           );

    services.AddMvc();

    services.AddTransient<IAccountService, AccountService>();
    services.AddTransient(typeof(ISession), serviceProvider =>
    
        var httpContextAccessor = serviceProvider.GetService<IHttpContextAccessor>();
        return httpContextAccessor.HttpContext.Session;
    );



public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)

    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

    if (env.IsDevelopment())
    
        app.UseDeveloperExceptionPage();
        app.UseBrowserLink();
    
    else
    
        app.UseExceptionHandler("/Home/Error");
    

    app.UseSession();
    app.UseStaticFiles();
    app.UseAuthentication();


    app.UseMvc(routes =>
    
        routes.MapRoute(
            name: "default",
            template: "controller=Home/action=Index/id?");
    );

这是我的登录操作:

[HttpPost]
public async Task<IActionResult> Login(LoginData data)

    var loginresult = (await _accountService.GetLoginToken(data.Username, data.Password));

    if (!loginresult.Success)
        return RedirectToAction("Login");

    Response.Cookies.Append("identity", loginresult.Token, new CookieOptions  Expires = DateTimeOffset.Now.Add

    int id = await _getIdFromToken(loginresult);

    ApplicationUser user;
    await _signin(user = await _accountService.GetUserAsync(id));
    _session.SetData("actualuser", user);

    return RedirectToAction("Index");


private async Task _signin(ApplicationUser c)

    var claims = new List<Claim>
    
        new Claim(ClaimTypes.MobilePhone, c.Phone??""),
        new Claim(ClaimTypes.Name, c.UserName)
    ;
    var userIdentity = new ClaimsIdentity();
    userIdentity.AddClaims(claims);
    ClaimsPrincipal userPrincipal = new ClaimsPrincipal(userIdentity);

    try
    
        await HttpContext.SignInAsync(
            JwtBearerDefaults.AuthenticationScheme,
            userPrincipal,
            new Microsoft.AspNetCore.Authentication.AuthenticationProperties
                
                    ExpiresUtc = DateTime.UtcNow.AddMinutes(20),
                    IsPersistent = true,
                    AllowRefresh = true,
                    IssuedUtc = DateTimeOffset.Now
                );
    
    catch (Exception e)
    
        throw;
    

【问题讨论】:

你读过这个:JWT Token Authentication with Cookies in ASP.NET Core?我没有尝试过,但看起来这就是你想要做的。 @FrankFajardo 感谢您提供此链接。我将它实现到我的应用程序中,它现在可以工作。 AYCS 只有虚拟数据,所以我现在需要将虚拟数据切换为生产数据(来自我的服务/api)。 所以我认为这回答了你的问题。 AYCS 是什么意思? 在某种程度上它回答了我的问题。我还没有解决它,但链接有帮助,是的。 '如你所见':D @FrankFajardo 在你的帮助下(你的链接)我终于明白了 - 谢谢!您介意将其发布在简短的答案中吗? (创建该 cookie 和登录方法是问题) 【参考方案1】:

这是一篇关于如何在 ASP.NET Core 2.0 上使用 cookie 作为 JWT 的传递机制的博文,这正是您正在尝试做的事情: JWT Token Authentication with Cookies in ASP.NET Core

我没有尝试过,但它可以指导您了解哪里可能做错了。

【讨论】:

【参考方案2】:

默认方案不匹配任何处理程序(在本例中为 cookie)。如果可以,请尝试将其放入您的代码中(这可能是 .net core 2 特定的):

services.AddAuthentication("YourSchemeNameHere")
.AddCookie("YourSchemeNameHere", options => 

    ...
);

如果这不起作用,请更改 cookie 选项中的 AuthenticationScheme 属性以匹配身份验证选项中的 DefaultAuthenticateScheme。

【讨论】:

登录时仍然出现同样的错误(我想我需要 JwtBearerDefaults.AuthenticationScheme 作为方案,因为我使用的是 JWT)。另外,当我设置AddAuthentication(JwtBearerDefaults.AuthenticationScheme) 并导航到Home/Contact 时,我得到一个没有任何内容的白页。 (调试模式在动作方法中设置断点,但它从未命中它)【参考方案3】:

我遇到了类似的问题。 请检查Web.config并检查您是否有类似的节点或检查是否有用于身份验证的节点,可能是这个原因,或者配置不正确。

我正在开发一个 mvc 5 应用程序,我的网络配置是这样的

  <modules>
  <remove name="FormsAuthentication" />
  <remove name="ApplicationInsightsWebTracking" />
  <add name="ApplicationInsightsWebTracking" 
   type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, 
   Microsoft.AI.Web" preCondition="managedHandler" />
   </modules>
<authentication mode="None" />

我正在使用预构建的 asp.net 身份验证模块及其 db

【讨论】:

以上是关于AuthorizeAttribute with JWT Token- .NET Core 2.0 中的身份验证的主要内容,如果未能解决你的问题,请参考以下文章

扩展AuthorizeAttribute

自定义AuthorizeAttribute

创建 AuthorizeAttribute - 我需要知道啥?

自定义AuthorizeAttribute未实现

如何绕过 System.Web.Http.AuthorizeAttribute.IsAuthorized

仅针对一项操作覆盖控制器 AuthorizeAttribute