【发布时间】: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://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 和令牌的好读物:
- 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 中用于创建令牌
标签: authentication asp.net-core jwt single-page-application