Cors跨域(二):实现跨域Cookie共享的三要素(下)

简介: Cors跨域(二):实现跨域Cookie共享的三要素(下)

代码模拟跨域Cookie共享


前端页面:发送跨域请求,为了方便模拟这里发送跨域的简单请求即可(还不知道什么叫简单请求?戳这里


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Cookie交互机制(跨域)</title>
    <!--导入Jquery-->
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
</head>
<body>
<button id="btn">Cookie交互机制(跨域)</button>
<div id="content"></div>
<script>
    $("#btn").click(function () {
        $.get("http://localhost:8080/corscookie");
    });
</script>
</body>
</html>


前端页面托管在本地的63342端口上:http://localhost:63342/...


后端代码:后端接口托管在8080端口上:http://localhost:8080/...


这就是最简单的一个跨域场景,两个域具有相同的domain,因此才有共享Cookie的可能。


/**
 * 在此处添加备注信息
 *
 * @author YourBatman. <a href=mailto:yourbatman@aliyun.com>Send email to me</a>
 * @site https://yourbatman.cn
 * @date 2021/6/9 10:36
 * @since 0.0.1
 */
@Slf4j
@WebServlet(urlPatterns = "/corscookie")
public class CorsCookieServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String requestURI = req.getRequestURI();
        String method = req.getMethod();
        String originHeader = req.getHeader("Origin");
        log.info("收到请求:{},方法:{}, Origin头:{}", requestURI, method, originHeader);
        // 读取Cookie
        List<Cookie> myCookies = new ArrayList<>();
        if (req.getCookies() != null) {
            myCookies = Arrays.stream(req.getCookies()).filter(c -> c.getName().equals("name") || c.getName().equals("age")).collect(toList());
        }
        if (myCookies.isEmpty()) { // 种植Cookie
            Cookie cookie = new Cookie("name", "YourBatman");
            // cookie.setDomain("baidu.com");
            cookie.setMaxAge(3600);
            resp.addCookie(cookie);
            cookie = new Cookie("age", "18");
            cookie.setMaxAge(3600);
            resp.addCookie(cookie);
        } else {
            myCookies.stream().forEach(c -> {
                log.info("name:{} value:{} domain:{} path:{} maxAge:{} secure:{}", c.getName(), c.getValue(), c.getDomain(), c.getPath(), c.getMaxAge(), c.getVersion(), c.getSecure());
            });
        }
        setCrosHeader(resp);
        resp.getWriter().write("hello cookie...");
    }
    private void setCrosHeader(HttpServletResponse resp) {
        resp.setHeader("Access-Control-Allow-Origin", "http://localhost:63342");
    }
}


点击按钮,发送请求:


image.png


image.png



注意看,服务端代码虽然resp.addCookie(cookie);添加了Cookie,但是Response响应里并没有Set-Cookie这个头哦。查看浏览器发现木有Cookie:


image.png


也许你会说,当然没有啦,因为Response里没有Set-Cookie头嘛,但我们代码里明明已经addCookie了呀。


这半截理论当然没问题,现在我在服务端程序里补充一个响应头:

 private void setCrosHeader(HttpServletResponse resp) {
     resp.setHeader("Access-Control-Allow-Origin", "http://localhost:63342");
     resp.setHeader("Access-Control-Allow-Credentials", "true");
 }


重启服务端应用),再次发送请求,响应如下:


image.png


可以看到响应中已经有Set-Cookie响应头了,再次查看Cookie是否已被浏览器保存,同样的比比脸还干净:



image.png


浏览器没有存储Cookie。What?难道翻车了?No,下面教你如何解释以及怎么破?


跨域Cookie共享的关键点


这里要讨论的是跨域中Cookie的存储问题:默认情况下,浏览器是不会去为你保存下跨域请求响应的Cookie的。具体现象是:跨域请求的Response响应了即使有Set-Cookie响应头(且有值),浏览器收到后也是不会保存此cookie的。


要实现Cookie的跨域共享,有3个关键点:


  1. 服务端负责在响应中将Set-Cookie发出来(由Access-Control-Allow-Credentials响应头决定)
  2. 浏览器端只要响应里有Set-Cookie头,就将此Cookie存储(由异步对象的withCredentials属性决定)
  3. 浏览器端发现只要有Cookie,即使是跨域请求也将其带着(由异步对象的withCredentials属性决定)


为了满足这三个关键点,在实施层面就有三要素来指导我们开发来解决此类问题。


跨域Cookie共享的三要素


首先确保服务端能正确的在响应中有Set-Cookie响应头,这由Access-Control-Allow-Credentials: true来保证。因此服务端只需要做多加这一步即可:


resp.setHeader("Access-Control-Allow-Credentials", "true");


Access-Control-Allow-Credentials该头是可选的,是个bool值,它若为true就有两个作用:


  • 在跨域请求的响应中允许Set-Cookie响应头
  • 浏览器收到响应后,浏览器根据此头判断是否让自己的withCredentials属性生效


所以就来到了第二个要素:XMLHttpRequest对象的withCredentials属性。该属性是一个Boolean类型,它指示了是否该使用类似cookies,authorization headers(头部授权)或者TLS客户端证书这一类资格证书来创建一个跨站点访问控制(cross-site Access-Control)请求。


var xhr = new XMLHttpRequest();
...
xhr.withCredentials = true;


Jquery的Ajax写法与此不同,但底层原理一样


官方的语言理解起来总是那么晦涩,翻译成人话:当异步对象设置了withCredentials=true时,浏览器会保留下响应的Cookie等信息,并且下次发送请求时将其携带。因此要指示浏览器存储Cookie并且每次跨域请求都携带,仅需加上此参数即可:


$.ajax({
    url: "http://localhost:8080/corscookie",
    type: "GET",
    xhrFields: {
        withCredentials: true
    },
    crossDomain: true
});


以上两个要素完成后,影响“结果”的还有最后一个要素。这个要素比较隐晦,也是很多同学/文章忽略的点。


服务端的Access-Control-Allow-Origin这个响应头的值不能是通配符*,而只能是具体的值。否则出现报错:



image.png



换句话讲:浏览器端跨域请求对象一旦开启withCredentials=true属性,服务端跨域Origin将不能再用*通配符,否则CORS error!


三要素都满足后(Access-Control-Allow-Credentials:true;Access-Control-Allow-Origin:http://localhost:63342;withCredentials=true),再次点击发送请求,结果如下:


image.png


image.png


image.png


完美。


总结


上篇文章对Cors进行了全面介绍,本文以跨域Cookie共享为场景,很好的对跨域知识点进行了补充,并且也补足了Cors里一个重要的响应头Access-Control-Allow-Credentials的解释,相信通过本文同学你能加深对Web中Cookie的了解,以及跨域情况下Cookie信息如何共享。


本系列下篇将着眼于跨域请求解决方案的阐述,欢迎关注。


本文思考题

本文已被https://yourbatman.cn收录。所属专栏:点拨-Cors跨域,后台回复“专栏列表”即可查看详情。


看完了不一定懂,看懂了不一定会。来,3个思考题帮你复盘:


  1. Access-Control-Allow-Origin值设置为通配符*是万金油吗?
  2. 如何通过Cookie技术实现SSO单点登录?
  3. 实现跨域Cookie共享的三要素是什么?
相关文章
|
1月前
|
存储 缓存 安全
oss跨域资源共享(CORS Configuration)
oss跨域资源共享(CORS Configuration)
52 4
|
2月前
|
前端开发 API 数据安全/隐私保护
Web前端开发中的跨域资源共享(CORS)解决方案
【2月更文挑战第5天】在Web前端开发中,跨域资源共享(CORS)是一个常见的挑战。本文将探讨CORS的概念和原理,并介绍一些常用的解决方案,包括服务器端配置和前端处理方法,帮助开发者更好地应对跨域请求问题。
115 4
|
2月前
|
前端开发 开发者
前端开发中的跨域资源共享(CORS)解决方案探讨
【2月更文挑战第2天】跨域资源共享(CORS)是前端开发中常见的问题,本文将深入探讨CORS的原理及解决方案,包括简单请求、预检请求以及常用的CORS解决方案,为前端开发者提供深入的理解和应对CORS问题的有效方法。
35 1
|
2月前
|
Java
springboot+cors跨域处理
springboot+cors跨域处理
26 0
|
2月前
|
前端开发 JavaScript API
探索前端开发中的跨域资源共享(CORS)
【2月更文挑战第3天】在前端开发中,跨域资源共享(CORS)是一个至关重要的话题。本文将深入探讨CORS的概念、工作原理以及如何在前端项目中正确配置和处理跨域请求,帮助开发者更好地理解和应用CORS技术。
28 7
|
2月前
|
前端开发 安全 JavaScript
前端开发中的跨域资源共享(CORS)机制
【2月更文挑战第3天】 在前端开发中,跨域资源共享(CORS)机制是一个重要的安全性问题。本文将介绍CORS的概念、原理和实现方式,并探讨在前端开发中如何处理跨域资源请求,以及如何提高网站的安全性。
|
1月前
|
JavaScript 安全 前端开发
js开发:请解释什么是跨域请求(CORS),以及如何解决跨域问题。
CORS是一种W3C标准,用于解决浏览器同源策略导致的跨域数据访问限制。它通过服务器在HTTP响应头添加标志允许特定源进行跨域请求。简单请求无需预检,而预检请求(OPTIONS)用于询问服务器是否接受非简单请求。服务器端配置响应头如`Access-Control-Allow-Origin`等实现CORS策略,客户端JavaScript则正常发起请求。若配置不当,浏览器将阻止跨域访问,保障安全。
23 2
|
1月前
|
前端开发 安全 开发者
前端开发中的跨域资源共享(CORS)问题及解决方案探讨
在前端开发中,跨域资源共享(CORS)是一个常见且重要的问题。本文将深入探讨CORS的原理、影响以及解决方案,帮助开发者更好地应对跨域请求问题。
|
2月前
|
前端开发 数据安全/隐私保护 UED
探索前端开发中的跨域资源共享(CORS)
【2月更文挑战第3天】在当今Web开发中,跨域资源共享(CORS)扮演着至关重要的角色。本文将深入探讨CORS在前端开发中的作用和实践经验,带你解锁跨域访问的奥秘。
|
3月前
|
前端开发 JavaScript
CORS跨域资源共享及解决方案
CORS跨域资源共享及解决方案
32 0