做单点登录cookie无法写入的问题,虚拟机的nginx代理到win10的idea ,跨域

作为一个从不笔笔记的人,今天*记一个笔记
今天再学习springCloud +nginx 的时候做单点登陆,出现cookie无法写入问题
先交代一下环境
win10 idea
centos7 nginx 1.10.0

org.springframework.boot
spring-boot-starter-parent
2.0.2.RELEASE


如图:{
做单点登录cookie无法写入的问题,虚拟机的nginx代理到win10的idea ,跨域
做单点登录cookie无法写入的问题,虚拟机的nginx代理到win10的idea ,跨域

做单点登录cookie无法写入的问题,虚拟机的nginx代理到win10的idea ,跨域

做单点登录cookie无法写入的问题,虚拟机的nginx代理到win10的idea ,跨域
使用本地访问cookie浏览器是可以收到cookie的
而我在www.xxx.com下用api.xxx.com是接收不到这个cookie的,
后来我查阅资料发现要设置domain属性
domain 可以访问该Cookie的域名。如果设置为“.google.com”,则所有以“google.com”结尾的域名都可以访问该Cookie。注意第一个字符必须为“.”。

}
例如:
document.cookie = “username=Darren;path=/;domain=.csdn.net
做单点登录cookie无法写入的问题,虚拟机的nginx代理到win10的idea ,跨域
我在 设置domain为.csdn.net,那么我在blog.csdn.net 他的二级域名下就能拿到cookie,

总结:domain表示的是cookie所在的域,默认为请求的地址,如网址为www.study.com/study,那么domain默认为www.study.com。而跨域访问,如域A为t1.study.com,域B为t2.study.com,那么在域A生产一个令域A和域B都能访问的cookie就要将该cookie的domain设置为.study.com;如果要在域A生产一个令域A不能访问而域B能访问的cookie就要将该cookie的domain设置为t2.study.com。注意:一般在域名前是需要加一个".“的,如"domain=.study.com”。

作者:longgege001
来源:CSDN
原文:https://blog.csdn.net/longgege001/article/details/81274088
版权声明:本文为博主原创文章,转载请附上博文链接!

OK,那么原因就找到了,我需要设置domain属性,我们可以看我开头发的图片。但我用localhost访问的时候我的domain是localhost
package com.leyou.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;

/**

  • Cookie 工具类
    */
    @Slf4j
    public final class CookieUtils {

    /**

    • 得到Cookie的值, 不编码
    • @param request
    • @param cookieName
    • @return
      */
      public static String getCookieValue(HttpServletRequest request, String cookieName) {
      return getCookieValue(request, cookieName, null);
      }

    /**

    • 得到Cookie的值,
    • @param request
    • @param cookieName
    • @return
      */
      public static String getCookieValue(HttpServletRequest request, String cookieName, String charset) {
      Cookie[] cookieList = request.getCookies();
      if (cookieList == null || cookieName == null) {
      return null;
      }
      String retValue = null;
      try {
      for (int i = 0; i < cookieList.length; i++) {
      if (cookieList[i].getName().equals(cookieName)) {
      if (charset != null && charset.length() > 0) {
      retValue = URLDecoder.decode(cookieList[i].getValue(), charset);
      } else {
      retValue = cookieList[i].getValue();
      }
      break;
      }
      }
      } catch (UnsupportedEncodingException e) {
      log.error(“Cookie Decode Error.”, e);
      }
      return retValue;
      }

    public static CookieBuilder newBuilder(HttpServletResponse response) {
    return new CookieBuilder(response);
    }

    public static class CookieBuilder {
    private HttpServletRequest request;
    private HttpServletResponse response;
    private Integer maxAge;
    private String charset;
    private boolean httpOnly = false;

     public CookieBuilder(HttpServletResponse response) {
         this.response = response;
     }
    
     public CookieBuilder request(HttpServletRequest request) {
         this.request = request;
         return this;
     }
    
     public CookieBuilder maxAge(int maxAge) {
         this.maxAge = maxAge;
         return this;
     }
    
     public CookieBuilder charset(String charset) {
         this.charset = charset;
         return this;
     }
    
     public CookieBuilder httpOnly() {
         this.httpOnly = true;
         return this;
     }
    
     public void build(String cookieName, String cookieValue) {
         try {
             if (StringUtils.isBlank(charset)) {
                 charset = "utf-8";
             }
    
             if (cookieValue == null) {
                 cookieValue = "";
             } else if (StringUtils.isNotBlank(charset)) {
                 cookieValue = URLEncoder.encode(cookieValue, charset);
             }
             Cookie cookie = new Cookie(cookieName, cookieValue);
             if (maxAge != null && maxAge > 0)
                 cookie.setMaxAge(maxAge);
             if (null != request)// 设置域名的cookie
                 //todo
                 cookie.setDomain(getDomainName(request));
             cookie.setPath("/");
    
             cookie.setHttpOnly(httpOnly);
             response.addCookie(cookie);
         } catch (Exception e) {
             log.error("Cookie Encode Error.", e);
         }
     }
    
     /**
      * 得到cookie的域名
      */
     private String getDomainName(HttpServletRequest request) {
         String domainName = null;
    
         String serverName = request.getRequestURL().toString();
         if (serverName == null || serverName.equals("")) {
             domainName = "";
         } else {
             serverName = serverName.toLowerCase();
             serverName = serverName.substring(7);
             final int end = serverName.indexOf("/");
             serverName = serverName.substring(0, end);
             final String[] domains = serverName.split("\\.");
             int len = domains.length;
             if (len > 3) {
                 // www.xxx.com.cn
                 domainName = domains[len - 3] + "." + domains[len - 2] + "." + domains[len - 1];
             } else if (len <= 3 && len > 1) {
                 // xxx.com or xxx.cn
                 domainName = domains[len - 2] + "." + domains[len - 1];
             } else {
                 domainName = serverName;
             }
         }
    
         if (domainName != null && domainName.indexOf(":") > 0) {
             String[] ary = domainName.split("\\:");
             domainName = ary[0];
         }
         return domainName;
     }
    

    }
    }

做单点登录cookie无法写入的问题,虚拟机的nginx代理到win10的idea ,跨域

这是我用localhost访问时候的domain=localhost,
然后我换成域名访问

String serverName = request.getRequestURL().toString();
做单点登录cookie无法写入的问题,虚拟机的nginx代理到win10的idea ,跨域
我这个值怎么变成127.0.0.1.8087了???? 讲道理应该是http://api.leyou.com 这样的

原因是我用了nginx反向代理的原因,它把我的url代理成了我win10下面的
做单点登录cookie无法写入的问题,虚拟机的nginx代理到win10的idea ,跨域
加了个
proxy_set_header Host $host

这里先埋个伏笔,因为api网关也有问题
我们还是先把nginx问题解决吧

这样转发的时候就会带上本身的host=api.leyou.com
做单点登录cookie无法写入的问题,虚拟机的nginx代理到win10的idea ,跨域
结果还是不对
这是啥玩意儿呢??????黑人问号????
原因是我的小学zuul 做了代理

我们debug 我们的网关源码查看一下正确性
zuul有很多过滤器,都继承自ZuulFilter我们来看看PreDecorationFilter 前置过滤器
做单点登录cookie无法写入的问题,虚拟机的nginx代理到win10的idea ,跨域
在此处打上断点
做单点登录cookie无法写入的问题,虚拟机的nginx代理到win10的idea ,跨域
zuul网关在此处居然是false,那么我的微服务肯定收不到正确的host了。
OK,问题找到了
做单点登录cookie无法写入的问题,虚拟机的nginx代理到win10的idea ,跨域
这是zuul的默认配置我们改一下就ojbk了
做单点登录cookie无法写入的问题,虚拟机的nginx代理到win10的idea ,跨域
我加了个*

add-host-header: true

好的我们再次debug
做单点登录cookie无法写入的问题,虚拟机的nginx代理到win10的idea ,跨域
进去了,哈哈哈哈, 卧槽?????
做单点登录cookie无法写入的问题,虚拟机的nginx代理到win10的idea ,跨域
还是不对,你mmb是睿智吧直接开喷不解释好吧,因为这是zuul的bug,
RibbonRoutingFilter在这个类下有如下代码
做单点登录cookie无法写入的问题,虚拟机的nginx代理到win10的idea ,跨域

做单点登录cookie无法写入的问题,虚拟机的nginx代理到win10的idea ,跨域
我们跟踪到 isIncludedHeader下
做单点登录cookie无法写入的问题,虚拟机的nginx代理到win10的idea ,跨域
它应该是根据header的hashcode值来判断是不是包含了这些头如果包含了一个就return false
ok我们看buildZuulRequestHeaders这个方法的isIncludedHeader
做单点登录cookie无法写入的问题,虚拟机的nginx代理到win10的idea ,跨域
这不是完蛋了吗,??我要用的host被包含进去了而且spring把代码写死了。这不是扯淡吗,吓得我赶紧换个版本,吃把鸡压压惊
public boolean isIncludedHeader(String headerName) {
String name = headerName.toLowerCase();
RequestContext ctx = RequestContext.getCurrentContext();
if (ctx.containsKey(“ignoredHeaders”)) {
Object object = ctx.get(“ignoredHeaders”);
if (object instanceof Collection && ((Collection)object).contains(name)) {
return false;
}
}

    byte var5 = -1;
    switch(name.hashCode()) {
    case -1132779846:
        if (name.equals("content-length")) {
            var5 = 2;
        }
        break;
    case -905826493:
        if (name.equals("server")) {
            var5 = 3;
        }
        break;
    case -775651618:
        if (name.equals("connection")) {
            var5 = 1;
        }
        break;
    case 3208616:
        if (name.equals("host")) {
            var5 = 0;
        }
        break;
    case 1050906973:
        if (name.equals("x-application-context")) {
            var5 = 5;
        }
        break;
    case 1274458357:
        if (name.equals("transfer-encoding")) {
            var5 = 4;
        }
    }

    switch(var5) {
    case 0:
        if (this.addHostHeader) {
            return true;
        }
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
        return false;
    default:
        return true;
    }
}

这是最新版的isIncludedHeader方法,这回应该没问题了
还是有问题
这是zuul的默认配置
private Set sensitiveHeaders = new LinkedHashSet(Arrays.asList(“Cookie”, “Set-Cookie”, “Authorization”));
原来它把写cookie给禁用了,我们把它设为空就完事了熬
我哭了,你们呢