不同浏览器版本关于referer的问题

4,700 阅读2分钟

背景

微信的鉴权需要判断原域名为可校验的域名,而这一判断是通过跳转地址的referer来判断的,正常情况下浏览器会取当前页面的地址为其referer,我们可也可以通过修改document.referer来进行获取。

但在chrome较高版本以及部分ua情况下,其策略发生了改变,在地址跳转时,不会再添加referer域名以外的参数。这样就会直接导致鉴权失败。

在部分业务场景下,我们可能做了这样的判断,在code无效的情况下会发生302跳转,去重新鉴权,这样就会导致重复鉴权的死循环,问题更为严重。

那么这个问题应该如何解决呢?

referer的理解

一句话描述:在跳转地址后,追加该字段可用来判断页面来源的字段,该字段不仅仅可用于页面跳转还可以用于资源类的请求。

chrome高版本(85)带来的问题

原本默认的 referer 策略(policy)是no-referrer-when-downgrade,即允许referer带上来源页面地址上的请求参数,Chrome85将策略修改为strict-origin-when-cross-origin,即如果请求地址与请求页面非同源,将只携带请求的域名,不会再带上来源页面地址的请求参数。

那么为什么chrome要修改为这样的策略呢?增强隐私

如何主动开启这个策略(低版本下)

如果我们也有这个期望,那么我们可以如何主动开启呢 ?

前端的设置:

<meta name="referrer" content="strict-origin-when-cross-origin" />

服务端的请求:

Referer Policy: strict-origin-when-cross-origin

如何关闭这个策略

前端的设置:

<meta name="referrer" content="no-referrer-when-downgrade"" /> 
<!-- 对某个特定资源设置 referer 策略 --> 
<img src="…" referrerpolicy="no-referrer-when-downgrade" />

后端的设置:

服务端将Referer Policy设置为no-referrer-when-downgrade

回到问题

我们需要将方案调整为关闭即可 。

但如果直接设置为关闭,在低版本时会有相应的兼容问题 ,所以最终的技术方案如下 :

1 低版本时不做处理

2 chrome高版本,或者指定ua增加指定的meta标签

具体代码如下:仅供参考 :

  <!-- 针对不同版本的内核,设置referrer属性 -->
    <script script type="text/javascript">
      var chromeVersionMatch = window.navigator.userAgent.match(/Chrome/(\d*)/);
      var version = chromeVersionMatch && chromeVersionMatch[1];
      if (version > 84) {
        var meta = document.createElement('meta');
        meta.content='no-referrer-when-downgrade';
        meta.name = 'referrer';
        document.getElementsByTagName('head')[0].appendChild(meta);
      }
    </script>

更多

因为这个策略暂时没有相应的语法可以直接判断,所以建议在相应的问题上进行数据跟踪,不断追加需要兼容的ua名单和版本。如果你有更好的方案欢迎联系我更新。