1.只有两个服务
如果您的系统只有两个服务(前端和后端),您可以将 Cookie 用于前端的所有身份验证方案,并使用您的 api 进行用户验证。
在您的 Web 应用程序中实现登录页面,并从您的登录操作方法(发布)调用后端端点(您的 api)验证用户,您可以在其中根据您的数据库验证凭据。请注意,您不需要在 Internet 上发布此端点。
配置服务:
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.LoginPath = "/auth/login";
options.LogoutPath = "/auth/logout";
});
AuthController:
[HttpPost]
public IActionResult Login([FromBody] LoginViewModel loginViewModel)
{
User user = authenticationService.ValidateUserCredentials(loginViewModel.Username, loginViewModel.Password);
if (user != null)
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.UserName),
new Claim(ClaimTypes.Role, user.Role),
new Claim(ClaimTypes.Email, user.Email)
};
var identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
var principal = new ClaimsPrincipal(identity);
await HttpContext.SignInAsync(principal);
return Redirect(loginViewModel.ReturnUrl);
}
ModelState.AddModelError("LoginError", "Invalid credentials");
return View(loginViewModel);
}
2。 OAuth2 或 OpenId Connect 专用服务器
但是,如果您想实现自己的授权服务或身份提供程序,可以由您的所有应用程序(正面和背面)使用,我建议您使用 OAuth2 或 OpenId 等标准创建您自己的服务器。此服务应专门用于此目的。
如果您的服务是网络核心,您可以使用IdentityServer。它是一个通过 OpenIdConnect 认证的中间件,非常完整和可扩展。您拥有大量文档,并且对于 OAuth2 和 OpenId 都很容易实现。您可以添加您的 dbContext 以使用您的用户模型。
您的 Web 应用 ConfigureServices:
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
options.SignInScheme = "Cookies";
options.Authority = "https://myauthority.com";
options.ClientId = "client";
options.ClientSecret = "secret";
options.SaveTokens = true;
options.Scope.Clear();
options.Scope.Add("myapi");
// ...
}
您的身份提供者配置服务:
services.AddIdentityServer()
.AddInMemoryClients(Config.GetClients())
.AddInMemoryApiResources(Config.GetApis())
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseSqlServer(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
})
.AddDeveloperSigningCredential();
通过这种方式,您的前台将请求访问访问 api 所需的范围。前端将收到具有此范围的访问令牌(如果允许此客户端用于请求的范围)。这些 api 又可以使用如下验证中间件验证访问令牌:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = "https://myauthority.com";
options.Audience = "myapi";
});
3.自定义远程处理程序
如果您仍然喜欢自己实现远程功能,您可以实现自定义RemoteAuthenticationHandler。此抽象类可帮助您重定向到远程登录服务(您的 api),并使用 Web 应用程序中的授权结果处理回调重定向的结果。此结果用于填充用户 ClaimsPrincipal,如果您以这种方式配置 Web 应用身份验证服务,则可以在 Cookie 中维护用户会话:
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = "CustomScheme";
})
.AddCookie()
.AddRemoteScheme<CustomRemoteAuthenticationOptions, CustomRemoteAuthenticationHandler>("CustomScheme", "Custom", options =>
{
options.AuthorizationEndpoint = "https://myapi.com/authorize";
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.SaveTokens = true;
options.CallbackPath = "/mycallback";
});
您可以查看远程处理程序 OAuthHandler 或 OpenIdConnectHandler 作为实施您的指南。
实现您自己的处理程序(和处理程序选项)可能既麻烦又不安全,因此您应该考虑第一个选项。