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

Posted

技术标签:

【中文标题】ASP.Net Core、Angular2 和基于令牌的身份验证【英文标题】:ASP.Net Core, Angular2 and token based authentication 【发布时间】:2017-05-19 07:48:55 【问题描述】:

我正在编写一个使用 ASP.NET 核心作为后端/服务和 Angular2 作为前端的 Web 应用程序,并且在身份验证/授权方面遇到了问题。

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

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

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

public void ConfigureServices(IServiceCollection services)

  [...]
  services.AddIdentity<IdentityUserEntity, IdentityRoleEntity>()
    .AddEntityFrameworkStores<ApplicationDbContext, long>()
    .AddDefaultTokenProviders();
  [...]

但是我需要在 Configure 中设置什么中间件?我需要 app.UseIdentity() 还是 app.UseJwtBearerAuthentication(o) 足够?在 JwtBearer 开始检查令牌之前,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 );
  

 

那么我该如何实现基于令牌的身份验证而不是别的

[更新]

我猜我需要拦截 Cookie 身份验证事件并拒绝主体以禁用 Cookie 身份验证(请参阅https://***.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 和令牌的好读物: - http://andrewlock.net/exploring-the-cookieauthenticationmiddleware-in-asp-net-core/ - https://stormpath.com/blog/token-authentication-asp-net-core

【问题讨论】:

ASP.NET Core 不再有 OAuth/OpenID 服务器,因此您不能使用它来创建 JWT 令牌。 ASP.NET Core 仅附带 OAuth 身份验证提供程序(用于流行的服务,例如 google、facebook、microsoft 或通用 jwt 身份验证中间件)。要创建 jwt 令牌,您需要第三方库,身份服务器 4 或 ASOS (AspNet.Security.OpenIdConnect.Server) 我不需要通过 Google/Facebook/...登录,我不能以某种方式签署自己的令牌吗? 你错过了我的问题:即使我还没有处理令牌,身份验证仍然有效 "...我不能以某种方式签署自己的令牌吗?" 不,你不能,这就是我刚才在评论中所说的。作为 ASP.NET Core 的一部分,不再有没有身份验证服务器。为此,您需要一个 3rd 方库。只有身份验证提供程序是 ASP.NET Core 的一部分,不是身份验证服务器 要明确一点:来自 ASP.NET 4 / MVC 5 的 app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions() ... ) 调用在 ASP.NET Core 中不可用,它在旧版 ASP.NET 中用于创建令牌 【参考方案1】:

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());
        );

最后在controller中使用,只需添加[Authorize("Bearer")]

   [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

【讨论】:

以上是关于ASP.Net Core、Angular2 和基于令牌的身份验证的主要内容,如果未能解决你的问题,请参考以下文章

将文件从 ASP.NET Core Web api 发布到另一个 ASP.NET Core Web api

如何在ASP.NET 5上搭建基于TypeScript的Angular2项目

无法在 ASP.NET Core 1.0 中启用跨域请求 (CORS)

ASP.NET Core和Angular 2双剑合璧

在 Visual Studio 的 ASP.NET Core + Angular 2 模板上设置图像路径

基于Asp.net 的NewLife.Cube和基于Asp.net core的NewLife.CubeNC的区别