• home > tools > webServer > nginx >

    cookie跨域传输cookie问题:nginx跨域代理之proxy_cookie_domain

    Author:zhoulujun Date:

    通过设置cookie Domain 只能解决主域名相同的 跨子域名的跨域问题。设置http头cors配置项可以解决跨域问题。但是需要前后端一同设置。通过nginx转发,只是host、端口转换,则cookie不会丢失。如果路径也跟着变,需要设置proxy_cookie_

    cookie作为辨别用户身份、进行Session跟踪而储存在用户本地终端上的数据(通常经过加密),存储格式如下:

    Set-Cookie: NAME=VALUE(key1=value1&key2=value2);Expires=DATE;Path=PATH;Domain=DOMAIN_NAME;SECURE

    • Expires 限定本地数据缓存事件

    • Domain确定哪些域名可以访问该数据,默认为存储数据时相对应的域名。

    • Path限定哪些路径可以访问该数据,如果值为“/”,则Web服务器上所有的WWW资源均可读取该Cookie,默认为存储是对应路径

    • Secure 限定通信只有是加密协议时,才可读取本地数据。目前只有https。

    跨域传输cookie解决方案

    设置cookie Domain 

    通过设置cookie Domain 只能解决主域名相同的 跨子域名的跨域问题。例如将cookie的domain设置为.zlj.cn;name a.zlj.com b.zlj.cn等都能访问此cookie。

    但是此法无法解决跨主域名的的问题。

    设置http头解决跨域问题

    CORS为我们提供了跨域资源共享的解决方案,通过Access-Control-Allow-Origin Access-Control-Allow-Credentials Access-Control-Allow-Headers Access-Control-Allow-Methods Access-Control-Expose-Headers Access-Control-Max-Age Access-Control-Request-Headers Access-Control-Request-Method Origin

    Access-Control-Allow-Credentials 响应头表示是否可以将对请求的响应暴露给页面。返回true则可以,其他值均不可以。

    Credentials可以是 cookies, authorization headers 或 TLS client certificates

    前端跨域传输cookie到服务端,需要三个条件:

    1. Access-Control-Allow-Origin不能为*,应为具体域名

    2. 服务端Access-Control-Allow-Credentials应为true

    3. 客户端XMLHttpRequest 的 withCredentials=true

    在服务端,需要

    response.addHeader("Access-Control-Allow-Origin", "demo.zhoulujun.cn");

    response.addHeader("Access-Control-Allow-Credentials", "true");

    前端ajax操作

    $.ajax({  url : 'xxx',  xhrFields: {  withCredentials: true // 设置运行跨域操作  }}); //jquery
    axios(url, {  
      method: 'GET',  
      mode: 'no-cors',  
      headers: {  
        'Access-Control-Allow-Origin': '*',  
        'Content-Type': 'application/json',  
      },  
      withCredentials: true,  
      credentials: 'same-origin',  
    }).then(response => {  
    })

    这个比较麻烦,还是nginx代理比较方便

    chrome80 后跨域解决方案

    chrome80版本的声明


    20200608211502397978085.png

    大致就是说80以后的版本,cookie默认不可跨域,除非服务器在响应头里再设置same-site属性。因为默认属性不再是lax

    same-site属性设置

    same-site有3种值可以设置:strict,lax,none

    • Strict最为严格,完全禁止第三方 Cookie,跨站点时,任何情况下都不会发送 Cookie。换言之,只有当前网页的 URL 与请求目标一致,才会带上 Cookie。

      这个规则过于严格,可能造成非常不好的用户体验。比如,当前网页有一个 GitHub 链接,用户点击跳转就不会带有 GitHub 的 Cookie,跳转过去总是未登陆状态。

    • None,Cookie 只能通过 HTTPS 协议发送。必须同时设置Secure属性(Cookie 只能通过 HTTPS 协议发送),否则无效。

      Set-Cookie: widget_session=abc123; SameSite=None; Secure

    • Lax规则稍稍放宽,大多数情况也是不发送第三方 Cookie,但是导航到目标网址的 Get 请求除外

      导航到目标网址的 GET 请求,只包括三种情况:链接,预加载请求,GET 表单。详见下表。

      请求类型示例正常情况Lax
      链接<a href="..."></a>发送 Cookie发送 Cookie
      预加载<link rel="prerender" href="..."/>发送 Cookie发送 Cookie
      GET 表单<form method="GET" action="...">发送 Cookie发送 Cookie
      POST 表单<form method="POST" action="...">发送 Cookie不发送
      iframe<iframe src="..."></iframe>发送 Cookie不发送
      AJAX$.get("...")发送 Cookie不发送
      Image<img src="...">发送 Cookie不发送


    nginx使用proxy_pass反向代理时

    如果只是host、端口转换,则cookie不会丢失。浏览器的cookie内有jsessionid。再次访问时,浏览器会发送当前的cookie。

    如果路径也变化了,则需要设置cookie的路径转换,详细看了文档:http://nginx.org/en/docs/http/ngx_http_proxy_module.html?&_ga=1.161910972.1696054694.1422417685#proxy_cookie_path

    location /proxy_path {
        proxy_pass   http://zhoulujun.cn/project;
        proxy_cookie_path  /project /proxy_path;
        # proxy_cookie_domain b.zlj.com  a.zlj.com;#如果cookie没有设置domain,无需配置(一般情况没有配置)
    }

    经过后端中转,基本可以解决所有问题,但是也带来多余的消耗

    proxy_cookie_domain参数的作用是转换response的set-cookie header中的domain选项,由后端设置的域名domain转换成你的域名replacement,来保证cookie的顺利传递并写入到当前页面中,注意proxy_cookie_domain负责的只是处理response set-cookie头中的domain属性,仅此而已。


    参考文章: 

    Cookie 的 SameSite 属性 www.ruanyifeng.com/blog/2019/09/cookie-samesite.html


    转载本站文章《cookie跨域传输cookie问题:nginx跨域代理之proxy_cookie_domain》,
    请注明出处:https://www.zhoulujun.cn/html/tools/webServer/nginx/2020_0526_8439.html