
【解决方案】跨域共享cookie
发布日期:2021-05-06 19:58:40
浏览次数:30
分类:精选文章
本文共 5292 字,大约阅读时间需要 17 分钟。
【解决方案】跨域共享信息
层级关系的域名的cookie共享
首先,我们需要知道cookie的作用的域名是domain本身及domain下的所有子域名。
以test.la
,login.test.la
,article.test.la
为例,login.test.la
,article.test.la
作为test.la
的子域名,在跨域共享信息的时候,我们只需要将需要共享的信息放置于test.la
域名下即可。
譬如共享登录信息,在通过login.test.la
域名登录后,将登录信息置于test.la
下,访问article.test.la
,前端通过从test.la
域下拿cookie信息,从而达到共享的目的。
/** * * @param name cookie的key * @param value cookie的value */ public static Cookie buildCookie(String name, String value, String domain) { Cookie cookie = new Cookie(name, value); // 设置时间 cookie.setMaxAge(); cookie.setDomain(domain); // 设置路径 cookie.setPath("/"); return cookie; }
这里需要注意一下cookie时间和路径的设置,cookie存储在本地内存里,maxAge默认值为-1,此时只要关闭浏览器,cookie就会消失。设置为0,表示从内存中删除此cookie。
浏览器会将maxAge为正数的Cookie持久化,即写到对应的Cookie文件中。无论客户关闭了浏览器还是电脑,只要还在maxAge秒之前,登录网站时该Cookie仍然有效。(其设置的最大保存时长也是有限制的)
第二个注意的地方是路径,cookie默认设置的路径是当前访问的路径,如果不指明设置在根路径下,有时会出现明明设置成功了,但却一直读取不到的情况。
无层级关系的域名的cookie共享
两个完全不同的域名,如test.la
、test.com
,如何共享cookie?这里有本人实践过的两种解决方案。
- 譬如在
test.la
登陆后,后端设置cookie,前端将cookie保存至Storage中,然后访问test.com
时,以jsonp的方式(test.la
域名)进行请求接口A,后端的接口A将会拿到test.la
域下的cookie,并以jsonp形式返回,实现test.com
域名下也能共享该cookie。
@RequestMapping("/getLoginInfo") public void getLoginInfo(HttpServletRequest request, HttpServletResponse response) { // 这里是封装的一个cookie获取类,可以自己获取对应的cookie String accessToken = CookieUtil.getValue("access_token", request); response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Methods", "POST,GET,OPTIONS,DELETE,HEAD,PUT,PATCH"); response.setHeader("Access-Control-Max-Age", "36000"); response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept,Authorization,authorization"); response.setHeader("Access-Control-Allow-Credentials","true"); JsonObject jsonObject = new JsonObject(); jsonObject.addProperty("access_token", accessToken); String callBack = request.getParameter("callback"); // jsonp形式返回 try { if (StringUtils.isBlank(callBack)) { response.getWriter().append(new Gson().toJson(jsonObject)); } else { response.getWriter().append(callBack + "(" + new Gson().toJson(jsonObject) + ")"); } return; } catch (IOException e) { LOGGER.error("跨域失败 :" + e); } }
- 另一种方法,在
test.la
登陆后,设置cookie到test.la
下,然后由前端发起一个js请求
接口A(https://test.la/A
),后端接口A做redirect重定向到后端接口B(https://test.com/B
),在B接口设置cookie到test.com
。
@RequestMapping("/redirect") // 参数t为域名, 如例子中的test.com public String redirect(String t, HttpServletRequest request) { if (StringUtils.isBlank(t)) { throw new BusinessException("域名参数不能为空"); } // 截取域名后3段, 判断是否合法 String target = getRealDomain(t); if (!defaultDomain(target)) { throw new BusinessException("域名不合法" + t); } // 结合例子,这里我们就从`test.la`获取cookie, 然后作为参数 String value = CookieUtil.getValue("access_token", request); LOGGER.info("浏览器跨域请求 : {}, {}", t, value); return "redirect:https://youli." + t + "/api/user/web/set?t=" + value; } private String getRealDomain(String domain) { String[] array = domain.split("\\."); if (array.length <= 3) { return domain; } StringBuilder builder = new StringBuilder(); for (int i = 1; i < array.length; i++) { builder.append(".").append(array[i]); } return builder.substring(1); } private boolean defaultDomain(String target) { String[] array = domains.split(","); for (String domain : array) { if (domain.equals(target)) { return true; } } return false; } @RequestMapping("/set") @ResponseBody public ResultData set(String t, HttpServletRequest request, HttpServletResponse response) throws URISyntaxException { if (StringUtils.isBlank(t)) { throw new BusinessException("cookie参数不能为空"); } // 截取域名后3段, 判断是否合法 URI uri = new URI(request.getRequestURL().toString()); String domain = StringUtils.substring(uri.getHost(),StringUtils.indexOf(uri.getHost(),".") + 1); LOGGER.info("设置的域名:" + domain); String target = getRealDomain(domain); LOGGER.info("设置的target:" + domain); if (!defaultDomain(target)) { throw new BusinessException("域名不合法" + t); } response.setHeader("Access-Control-Allow-Credentials","true"); response.setHeader("p3p","CP=\"CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR\""); response.setContentType("text/javascript;charset=UTF-8"); ResponseCookie cookie = ResponseCookie.from("access_token", target) // key & value .httpOnly(true) // 禁止js读取 .secure(true) // 在http下也传输 .domain(domain) // 域名 .path("/") // path .maxAge(DateTimeUtil.getSecondTimestamp() + 3600 * 24 * 360 * 10) .sameSite("None") .build() ; response.addHeader("Set-Cookie", cookie.toString()); return new ResultData<>(); }
发表评论
最新留言
关注你微信了!
[***.104.42.241]2025年03月26日 15时47分41秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
基于单片机可控音乐流水灯控制设计-全套资料
2019-03-05
基于单片机简易信号误差分析设计-全套资料
2019-03-05
基于单片机简易脉搏测量仪系统设计-毕设课设资料
2019-03-05
Javascript中String支持使用正则表达式的四种方法
2019-03-05
【Tool】如何使用 Uniflash 烧写 WIFI 芯片 CC3200
2019-03-05
纯客户端页面关键字搜索高亮jQuery插件
2019-03-05
Java温故而知新-反射机制
2019-03-05
eclipse引用sun.misc开头的类
2019-03-05
Servlet2.5的增删改查功能分析与实现------删除功能(四)
2019-03-05
Session验证码的实现(2018-7-3)
2019-03-05
spring启动错误:Could not resolve placeholder
2019-03-05
选择性估算器绕过行安全策略漏洞
2019-03-05
对PostgreSQL数据库结构的宏观理解
2019-03-05
查询某表格上次进行vacuum的时间
2019-03-05
invalid byte sequence for encoding
2019-03-05
聊一聊那些应该了解的大佬(飞控,人工智能方向)
2019-03-05
redis向数组中添加值并查看数组长度
2019-03-05
JS编写一个函数,计算三个不同数字的大小,按从小到大顺序打印(穷举法)
2019-03-05
sqlplus的基本使用
2019-03-05
Oracle删除主表数据
2019-03-05