Http Only Cookie保护AccessToken

前言

JWT认证方式目前已被广泛使用,一直以来我们将token放在请求头中的Authorization中,若通过此种方式,一旦token被恶意窃取,攻击者可肆意对用户可访问资源进行任意索取,我们大多都是通过登录成功后,响应AccessToken,然后由前端将token存储在相关Storage中,然后每次将其放请求头而认证请求,由于token是极其敏感信息,所以我们不能将其交由前端去处理,而应由后台获取对前端不可见。对安全有较高要求的平台,我们通过Http Only Cookie来解决token恶意窃取问题

Http Only Cookie

Http Only Cookie简言之则是将相关信息响应时存储在Cookie中,而客户端脚本无法访问,每次请求时,则将自动携带所有信息到服务器。例如,京东存储相关信息

接下来我们看看在.NET Core中如何将AccessToken以Http Only方式存储在Cookie中

复制代码
[AllowAnonymous]
[HttpGet("api/test/get")]
public IActionResult Get()
{
    Response.Cookies.Append("x-access-token", GenerateToken(),
      new CookieOptions()
      {
        Path = "/",
        HttpOnly = true
      });

    return Ok();
}
复制代码

如上,我们模拟登录成功,并不返回AccessToken,而是将其写入到响应头中,上述Cookie选项HttpOnly为true即表示客户端脚本不可访问

此时我们来访问如下需认证接口

[HttpGet("api/test/say")]
public string Say()
{
   return "Hello World";
}

用过JWT的童鞋都知道,标准模式则是将AccessToken写入到Authorization中,即请求头【Authorization: Bearer ......】,那么上述是如何认证成功而请求到接口的呢?当我们添加JWT认证时,每次请求在其对应事件OnMessageReceived中将自动获取请求头Authorization中的值,将其赋值给context.Token

复制代码
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
   ......
   options.Events = new JwtBearerEvents
    {
        OnMessageReceived = context =>
        {
          //Bearer Token
          context.Token = "";  
          return Task.CompletedTask;
        }
    };
});
复制代码

你问我是怎么知道的,我是猜的吗,当然不是,丢出官方源码就知道了,直接找到JWT如何处理认证则一目了然

复制代码
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
    string token = null;

    // Give application opportunity to find from a different location, adjust, or reject token
    var messageReceivedContext = new MessageReceivedContext(Context, Scheme, Options);

    // event can set the token
    await Events.MessageReceived(messageReceivedContext);
    if (messageReceivedContext.Result != null)
    {
      return messageReceivedContext.Result;
    }

    // If application retrieved token from somewhere else, use that.
    token = messageReceivedContext.Token;

    if (string.IsNullOrEmpty(token))
    {
      string authorization = Request.Headers[HeaderNames.Authorization];

      // If no authorization header found, nothing to process further
      if (string.IsNullOrEmpty(authorization))
      {
        return AuthenticateResult.NoResult();
      }
    }
   ....... 
}
复制代码

到这里我们知道了自动获取Token的原理,我们修改了Token存储方式,照葫芦画瓢就好,如此将覆盖默认标准模式,如下:

复制代码
OnMessageReceived = context =>
{
   var accessToken = context.Request.Cookies["x-access-token"];

   if (!string.IsNullOrEmpty(accessToken))
   {
      context.Token = accessToken;
   }

   return Task.CompletedTask;
}
复制代码

从分析自动获取Token原理,我们也可知道,若与第三方对接,依然可以使用请求头Authorization标准模式认证,因为Cookie为空,再次获取Authorization值。注意:发现若将前端未置于wwwroot下,即完全前后分离,涉及到跨域的情况下,比如使用的是axios封装请求,那么应该必须在请求头中添加【withCredentials:true 】,否则使用Http Only将无效,出现401

 

额外意外发现一个很有意思的问题,未深入研究,这里当做小知识了解下就好,或许是我自以为发现新大陆了呢。

 

当我们创建AccessToken时,都会设置一个过期时间,我们知道此过期时间肯定不会设置过长,但是若在比如移动端微信小程序中,若设置时间不长,必然要考虑刷新Token问题,为了懒一点,我们将Token设置为永不过期,那么JWT支持吗?

 

当然支持,只不过根据我刚好尝试了几次,找到了JWT永不过期的上限,最大只能是16年,若超过此临界点,比如17年,如下:

将会出现401,具体错误如下:

总结

好了,本节我们暂时讨论到这里,再会啦~~~~ 


为了方便大家在移动端也能看到我分享的博文,现已注册个人公众号,扫描上方左边二维码即可,欢迎大家关注,有时间会及时分享相关技术博文。

感谢花时间阅读此篇文章,如果您觉得这篇文章你学到了东西也是为了犒劳下博主的码字不易不妨打赏一下吧,让楼主能喝上一杯咖啡,在此谢过了!
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!
本文版权归作者和博客园共有,来源网址:http://www.cnblogs.com/CreateMyself)/欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
posted @   Jeffcky  阅读(1725)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
历史上的今天:
2015-10-09 EntityFramework之原始查询如何查询未映射的值,你又知道多少?
点击右上角即可分享
微信分享提示