我在登录控制器上使用以下代码将用户JWT访问令牌存储在响应cookie 中
var returnedJwtToken = authenticationResponse.Content;
try
{
//Store a WebAPI JWT accesstoken in an FormsAuthenticationTicket userData
var ticket = new FormsAuthenticationTicket( 1,
login.UserName,
DateTime.Now,
DateTime.Now.Add(TimeSpan.FromSeconds(returnedJwtToken.ExpiresIn)),
login.RememberMe,
returnedJwtToken.AccessToken,
FormsAuthentication.DefaultUrl);
//Encrypt it
string encryptedTicket = FormsAuthentication.Encrypt(ticket);
//Add it to Response.Cookies
var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket) {
Domain = FormsAuthentication.CookieDomain,
Path = FormsAuthentication.FormsCookiePath,
HttpOnly = true,
Secure = FormsAuthentication.RequireSSL };
Response.Cookies.Add(cookie);
然后,我使用自定义的MVC AuthorizeAttribute来恢复访问令牌,并将其放在请求头中,这样就可以在控制器上重试,将经过身份验证的请求发送到WebAPI。它还为我的MVC应用程序控制器提供了授权。
public class SiteAuthorizeAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
// var tokenHandler = new JwtSecurityTokenHandler();
HttpCookie authCookie =httpContext.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
//Extract the forms authentication cookie
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
HttpContext.Current.Request.Headers["AccessKey"] = authTicket.UserData;
// Create the IIdentity instance
IIdentity id = new FormsIdentity(authTicket);
// Create the IPrinciple instance
IPrincipal principal = new GenericPrincipal(id, null);
// Set the context user
httpContext.User = principal;
}
var accessKey= httpContext.Request.Headers["AccessKey"];
return (!string.IsNullOrWhiteSpace(accessKey));
}
}
此外,我在帖子表单中使用MVC ValidateAntiForgeryToken过滤器来防止CSRF攻击。
我想知道这个解决方案是否足够安全?
如果是,我如何从令牌中检索角色和声明,并在控制器上的授权过滤器中使用它们?
当我第一次必须将一个新的Web API集成到遗留应用程序中时,我必须创建一些自定义的auth函数。我试着遵循这本书中的指导方针:
Pro ASP.NET Web API安全性:确保ASP.NET Web API的安全(.NET中的专家语音)
Badrinarayanan Lakshmiragavan
https://www.amazon.com/Pro-ASP-NET-Web-API-Security/dp/1430257822/ref=sr_1_3?keywords=securing+.net+web+api&qid=1565367785&s=网关&sr=8-3
根据我对这本书的记忆,在处理客户端令牌时,以下是需要记住的要点(我相信这是对Garg先生的文章的扩展):
1) 使用安全的HttpOnly cookie(防止MIM或XSS劫持令牌)
2) 创建一个不同于cookie的令牌,该cookie也随每个请求一起提交(防止XRSF伪造)。不同意味着,即使恶意脚本要从localStorage获取未受保护的令牌,也无法使用所有必要的身份验证数据生成请求。
3) 令牌将在服务器上生成,并进行强加密和签名。对于.NET Framework,本书为此使用了一个AuthenticatedAesCng库。这可以防止用户在读取数据的同时盲目篡改数据
MVC很可能遵循这些原则,ValidateAntiForgeryToken听起来就像是在完成上面的第2点。
一段时间以来,我确实尝试在.NET Framework和其他源中使用所提供的身份验证方法。然而,我从来没有适应过他们中的任何一个,也不认为他们满足我的需求。所以我不太熟悉你的具体情况,但我希望这会有所帮助。
目前,我发现使用.NET Core DataProtection API来保护我自己的客户端令牌并实现我自己的auth MiddleWare组件非常简单。这可能是"危险的",但所有的加密/解密都由比我聪明的人负责,在我最新的项目中,我一直在使用传统的自定义权限方案;因此,这种方法在一定程度上是值得的。
链接上有一个很好的解释
它建议将令牌存储在web应用程序的cookie(HttpOnly+Secure+Encrypted)中,因为它们提供了额外的安全性。此外,由于使用现代web框架保护CSRF的简单性。HTML5 Web存储易受XSS攻击,攻击面更大,成功攻击后会影响所有应用程序用户。