我有两个.net core 2.2项目;第一个是MVC项目,类似于用户可以登录的表示层,另一个是用于处理数据库操作的Web API。我想在Web API中处理登录请求,并使用MVC Core Identity将登录结果返回到MVC项目。我的DbContext在Web API项目中。反正有根据Web API请求的结果创建身份cookie的问题?
答案 0 :(得分:2)
在这种情况下,应该使用访问令牌而不是cookie处理身份验证。
对于您的Web API,借助 IdentityServer 4 库,实现 OAuth2协议的资源所有者密码凭证授予类型。最后,您应该可以从API获取访问令牌以交换登录凭据。
对于您的MVC项目,创建一个表来存储令牌-sessid对,因此当MVC应用程序在会话期间从API获取访问令牌时,会将其保存在表中。对于后续请求,MVC应用程序将从表中获取令牌(通过使用sessid),并使用它来访问Web API。
答案 1 :(得分:0)
首先是服务器端MVC的启动类 添加->
<tr>
<td align="left" valign="top">
<div style="height: 33px; line-height: 33px; font-size: 31px;"> </div><div style="height: 75px; line-height: 75px; font-size: 73px;"> </div>
<div style="text-align:center;float: left;display: inline-block;margin-left: 10px;font-family: arial,sans,sans-serif"><table border=1><tr><td>Locked Proxy</td><td>Fail</td><tr><td>Final Proxy</td><td>Fail</td><tr><td>Final Script</td><td>Fail</td><tr><td>PM</td><td>Fail</td></tr></table></div><span><div style="text-align:center;float: left;display: inline-block;margin-left: 10px;font-family: arial,sans,sans-serif"><table border=1><tr><td>ME</td><td>Fail</td></tr></table></div><span><div style="text-align:center;float: left;display: inline-block;margin-left: 10px;font-family: arial,sans,sans-serif"><table border=1><tr><td>Locked Script</td><td>Fail</td></tr></table></div><span>
</td>
</tr>
然后在您的MVC登录控制器中
services.AddAuthentication(options => {
options.DefaultScheme = "Cookies";
}).AddCookie("Cookies", options => {
options.Cookie.Name = "auth_cookie";
options.Cookie.SameSite = SameSiteMode.None;
options.Events = new CookieAuthenticationEvents
{
OnRedirectToLogin = redirectContext =>
{
redirectContext.HttpContext.Response.StatusCode = 401;
return Task.CompletedTask;
}
};
});
请注意,我们引用的是Startup.cs中定义的“ Cookies”身份验证方案。
然后在您的网络api->
[HttpPost]
public async Task<IActionResult> Login(string username, string password)
{
if (!IsValidUsernameAndPasswod(username, password))
return BadRequest();
var user = GetUserFromUsername(username);
var claimsIdentity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, user.Username),
//...
}, "Cookies");
var claimsPrincipal = new ClaimsPrincipal(claimsIdentity);
await Request.HttpContext.SignInAsync("Cookies", claimsPrincipal);
return NoContent();
}
这应该有助于您完成任务。当然可以根据您的要求更改值,但是代码将是一个很好的参考点。
还添加所需的代码以从Web api应用程序设置cookie。 希望对您有帮助!
答案 2 :(得分:0)
1。只有两项服务
如果您的系统只有两个服务(正面和背面),则可以使用Cookies进行正面的所有身份验证方案,并使用api进行用户验证。
在您的Web应用程序中实现登录页面,并通过调用后端端点(您的api)的登录操作方法(发布)验证用户,您可以在其中验证数据库的凭据。请注意,您不需要在Internet中发布此终结点。
ConfigureServices:
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");
// ...
}
您的身份提供者ConfigureServices:
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作为实施您的指南。
实现自己的处理程序(和处理程序选项)可能既麻烦又不安全,因此您应该考虑第一个选项。
答案 3 :(得分:0)
我不确定是否完全了解您的问题陈述。我假设您正在采用某种机制,使用户能够将其身份从网络客户端一直传递到您的DbContext。 我还假设您然后实际上不对MVC应用程序上的用户进行身份验证,并且基本上将他们的请求代理到WebAPI上。
如果是这样,您可能要考虑制作一个JWT(最好是已签名)令牌作为WebAPI响应,然后将其存储在客户端上(我想cookie是一种足够好的机制)。
然后,MVC项目自然会借助会话状态获得令牌,而您要做的就是将它与您提出的每个WebAPI请求一起传递。