Asp.net mvc 将WebAPI JWT访问令牌作为加密表单存储在Response.Cookies中的身份验证票证(在asp.net mvc中)是否安全

Asp.net mvc 将WebAPI JWT访问令牌作为加密表单存储在Response.Cookies中的身份验证票证(在asp.net mvc中)是否安全,asp.net-mvc,asp.net-web-api,authorization,access-token,jwt,Asp.net Mvc,Asp.net Web Api,Authorization,Access Token,Jwt,我在登录控制器处使用下面的代码在响应cookie中存储用户JWT访问令牌 var returnedJwtToken = authenticationResponse.Content; try { //Store a WebAPI JWT accesstoken in an FormsAuthenticationTicket userData var ticket = new FormsAut

我在登录控制器处使用下面的代码在响应cookie中存储用户JWT访问令牌

  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 authorized属性来恢复访问令牌,并将其放入请求头中,以便可以在控制器上检索以向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));
    }
}
我还在post表单中使用MVC ValidateAntiForgeryToken过滤器来防止CSRF攻击

我想知道这个解决方案是否足够安全


如果是,我如何从令牌检索角色和声明,并在控制器上的授权筛选器中使用它们?

一个非常好的解释正在进行中


它建议将令牌存储在web应用程序的Cookie(HttpOnly+安全+加密)中,因为它们提供了额外的安全性。另外,由于现代web框架可以简单地防止CSRF。HTML5 Web存储易受XSS攻击,并且具有更大的攻击表面积,成功的攻击会影响所有应用程序用户。

当我第一次必须将新的Web API集成到遗留应用程序中时,我必须创建一些自定义身份验证函数。我试图遵循本书中的指导原则:

Pro ASP.NET Web API安全:保护ASP.NET Web API(专家在.NET中的声音)

作者:Badrinarayanan Lakshmiraghavan

根据我对这本书的记忆,在处理客户端代币时要记住以下要点(我相信这是对Garg先生文章的扩展):

1) 使用安全、仅HttpOnly cookie(防止MIM或XSS劫持令牌)

2) 创建一个不同于cookie的令牌,该令牌也随每个请求一起提交(防止XRSF伪造)。不同意味着即使恶意脚本要从本地存储获取未受保护的令牌,也无法使用所有必需的身份验证数据生成请求

3) 令牌将在服务器上生成,并进行强加密和签名。对于.NET Framework,本书为此使用了一个经过身份验证的AESCNG库。这可以防止用户在读取数据的同时盲目篡改数据

MVC最有可能遵循这些原则,ValidateAntiForgeryToken听起来像是实现了上述第2点

我曾尝试在.NET框架和其他源代码中使用提供的auth方法。然而,我从来没有对它们中的任何一个感到舒服,也不认为它们满足了我的需要。所以我对你的具体情况不太熟悉,不过我希望这会有所帮助


目前,我发现使用.NET Core DataProtection API来保护我自己的客户端令牌和实现我自己的auth中间件组件相当简单。这可能是“危险的”,但所有的加密/解密都是由比我聪明的人负责的,在我最近的项目中,我一直在使用传统的自定义权限方案;因此,这种方法是值得的。

将其存储在会话中如何?您提供给客户机存储的任何内容都可以在发送之前进行修改。将它放在会话中,您仍然可以访问它的服务器端以传递到您的WebAPI。您的意思是我应该在会话中存储cookie吗?如下所示:
Session.Add(“AccessKey”,cookie)
不是整个cookie,只是
returnedJwtToken.AccessToken
。例如,
Session.Add(“AccessKey”,returnedJwtToken.AccessToken)
如何检索声明和角色?使用FormsAuthenticationTicket是否有问题?我需要使用它的过期时间,记住我对此有点困惑。它声明来自您域的JS可以读取auth cookie,以便使用头复制它(双重提交令牌CSRF保护)。但是,如果cookie是HttpOnly,那么客户端上的JS在浏览器中运行时应该无法访问它。那么,框架如何使用HttpOnly cookie实现这一点呢?