首页 文章

ASP.Net Core,Angular2和基于令牌的身份验证

提问于
浏览
2

我正在编写一个使用ASP.NET核心作为后端/服务和Angular2作为前端的Web应用程序,并使用带有身份验证/授权的麻烦 .

在ASP.NET核心中,我只有一个html页面和控制器,带有索引的HomeController允许匿名访问([AllowAnonymous]) . 此单页面将angular2-app提供给客户端 .

所有其他通信都使用ApiControllers(在ASP.NET核心中只是普通的控制器,但这些控制器上的操作期望并发送JSON数据 . 对于身份验证/授权,我想使用jwt令牌 . 用户,角色,声明等存储在使用EF核心的IdentityDbContext中 .

我发现的大多数教程都已过时,不完整或引用第三方OAuth解决方案 . 我不是在寻找OAuth,我只是想要一个带有用户名/密码的页面并使用令牌保持登录,因为我正在使用所有API来获取后端来回的数据 . 我阅读了很多教程,尝试了一些有用的库,但仍然对如何为基于令牌的安全性设置中间件链感到困惑 . 据我所知,我需要添加身份服务,因为我想使用IdentityDbContext:

public void ConfigureServices(IServiceCollection services)
{
  [...]
  services.AddIdentity<IdentityUserEntity, IdentityRoleEntity>()
    .AddEntityFrameworkStores<ApplicationDbContext, long>()
    .AddDefaultTokenProviders();
  [...]
}

但是我需要在Configure中设置哪些中间件?我需要app.UseIdentity()还是app.UseJwtBearerAuthentication(o)?在JwtBearer检查Tokens之前,不会使用UseIdentity快捷方式进行身份验证吗?

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
  [...]
  app.UseIdentity();
  [...]
  app.UseJwtBearerAuthentication(jwtOptions);
  [...]
}

我问,因为客户端在我的TokenController之后自动进行了身份验证,我执行了对_signInManager.PasswordSignInAsync(...)的调用,即使我的客户端从未收到过jwt . 所以ASP.NET身份管理在某种程度上找到了一些在登录后识别我的用户的方法,这当然不应该发生 .

// simplified controller
public class TokenController : Controller
{
  [HttpPost("[action]")]
  [AllowAnonymous]
  public async Task<JsonResult> Login([FromBody]LoginViewModel loginRequest)
  {
    var signin = await _signInManager.PasswordSignInAsync(loginRequest.Username, loginRequest.Passwort, true, true);
  }

  // this will work even though I don't handle any Tokens in the Client yet, so some other authentication mechanism is at work:
  [HttpGet("test")]
  [Authorize]
  public IActionResult Get()
  {
    return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
  }

}

那么我该如何实现基于令牌的身份验证呢?

[UPDATE]

我猜我需要拦截Cookie身份验证事件并拒绝主体来禁用Cookie身份验证(请参阅https://stackoverflow.com/a/38893778/7021):但由于某种原因,我的事件处理程序永远不会被调用 .

app.UseCookieAuthentication(new CookieAuthenticationOptions()
  {
    Events = new CookieAuthenticationEvents
    {
      OnValidatePrincipal = ValidateAsync
    }
  });

public static async Task ValidateAsync(CookieValidatePrincipalContext context)
{
  context.RejectPrincipal();
  await context.HttpContext.Authentication.SignOutAsync("BsCookie");
}

关于身份验证,Cookie和令牌的更多好读物:

1 回答

  • 3

    MS提供了基于jwt令牌的基本身份验证库,你可以在这里看到如何使用它:

    https://code.msdn.microsoft.com/How-to-achieve-a-bearer-9448db57

    在startup.cs中,首先配置Jwt Beare

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            app.UseJwtBearerAuthentication(new JwtBearerOptions()
              {
                  TokenValidationParameters = new TokenValidationParameters()
                {
                    IssuerSigningKey = TokenAuthOption.Key,
                    ValidAudience = TokenAuthOption.Audience,
                    ValidIssuer = TokenAuthOption.Issuer,
                    // When receiving a token, check that we've signed it.
                    ValidateIssuerSigningKey = true,
                    // When receiving a token, check that it is still valid.
                    ValidateLifetime = true,
                    // This defines the maximum allowable clock skew - i.e. provides a tolerance on the token expiry time 
                    // when validating the lifetime. As we're creating the tokens locally and validating them on the same 
                    // machines which should have synchronised time, this can be set to zero. Where external tokens are
                    // used, some leeway here could be useful.
                    ClockSkew = TimeSpan.FromMinutes(0)
                }
            });
    

    现在您可以添加到服务

    public void ConfigureServices(IServiceCollection services)
        {
             services.AddAuthorization(auth =>
              {
                auth.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
                    .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme‌​)
                    .RequireAuthenticatedUser().Build());
            });
    

    最后,在控制器中使用它,只需添加[授权(“承载”)]

    [Route("api/[controller]")]
       public class ValuesController : Controller
       {
          [HttpGet("GetStaff")]
          [Authorize("Bearer")]
           public IActionResult GetStaff()
          {
              List<string> model = new List<string>();
              foreach (User user in UserStorage.Users ){
               model.Add(user.Username);
              }
              return Json(model);
          }
        }
    

    在这里查看完整的详细信息:https://github.com/Longfld/ASPNETcoreAngularJWT

相关问题