1. 前言

最近项目用Sparrow Health System检测漏洞,发现存在一个setSecure安全漏洞问题,于是网上搜索了一下,这里记录一下。

2. 问题

在cas中或其他web开发中,会碰到安全cookie的概念,因为CAS中TGT是存放在安全cookie中的。下面是安全cookie 的理解:

  • Set-Cookie 的 secure 属性就是处理这方面的情况用的,它表示创建的 cookie 只能在 HTTPS 连接中被浏览器传递到服务器端进行会话验证,如果是 HTTP 连接则不会传递该信息,所以绝对不会被窃听到。

在setSecure(true); 的情况下,只有https才传递到服务器端。http是不会传递的。

    setSecure(true)意味着"指示浏览器仅通过 HTTPS 连接传回 cookie。这可以确保 cookie ID 是安全的,且仅用于使用 HTTPS 的网站。如果启用此功能,则 HTTP 上的会话 Cookie 将不再起作用。"

j2ee servlet的接口中也定义了Cookie对象,也有其方法setSecue(false);

关于setSecure的问题,在http连接下:

  • 当setSecure(true)时,浏览器端的cookie会不会传递到服务器端?
  • 当setSecure(true)时,服务器端的cookie会不会传递到浏览器端?
  • 答案:1)不会 ; 2)会

原理:服务器端的Cookie对象是java中的对象,请不要和浏览器端的cookie文件混淆了。服务器端的Cookie对象是方便java程序员包装一个浏览器端的cookie文件。一旦包装好,就放到response对象中,在转换成http头文件。在传递到浏览器端。这时就会在浏览器的临时文件中创建一个cookie文件。 
     但我们再次访问网页时,才查看浏览器端的cookie文件中的secure值,如果是true,但是http连接,这个cookie就不会传到服务器端。当然这个过程对浏览器是透明的。其他人是不会知道的。

总结如下:cookie的secure值为true时,在http中是无效的;在https中才有效

3. Cookie设置

实际上,Servlet提供的HttpSession本质上就是通过一个名为JSESSIONID的Cookie来跟踪用户会话的。除了这个名称外,其他名称的Cookie我们可以任意使用。

如果我们想要设置一个Cookie,例如,记录用户选择的语言,可以编写一个LanguageServlet

@WebServlet(urlPatterns = "/pref")
public class LanguageServlet extends HttpServlet {private static final Set<String> LANGUAGES = Set.of("en", "zh");protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String lang = req.getParameter("lang");if (LANGUAGES.contains(lang)) {// 创建一个新的Cookie:Cookie cookie = new Cookie("lang", lang);// 该Cookie生效的路径范围:cookie.setPath("/");// 该Cookie有效期:cookie.setMaxAge(8640000); // 8640000秒=100天// 将该Cookie添加到响应:resp.addCookie(cookie);}resp.sendRedirect("/");}
}

创建一个新Cookie时,除了指定名称和值以外,通常需要设置setPath("/"),浏览器根据此前缀决定是否发送Cookie。如果一个Cookie调用了setPath("/user/"),那么浏览器只有在请求以/user/开头的路径时才会附加此Cookie。通过setMaxAge()设置Cookie的有效期,单位为秒,最后通过resp.addCookie()把它添加到响应。

如果访问的是https网页,还需要调用setSecure(true),否则浏览器不会发送该Cookie。

因此,务必注意:浏览器在请求某个URL时,是否携带指定的Cookie,取决于Cookie是否满足以下所有要求:

  • URL前缀是设置Cookie时的Path;
  • Cookie在有效期内;
  • Cookie设置了setSecure(true)时必须以https访问。

我们可以在浏览器看到服务器发送的Cookie:

如果我们要读取Cookie,例如,在IndexServlet中,读取名为lang的Cookie以获取用户设置的语言,可以写一个方法如下:

private String parseLanguageFromCookie(HttpServletRequest req) {// 获取请求附带的所有Cookie:Cookie[] cookies = req.getCookies();// 如果获取到Cookie:if (cookies != null) {// 循环每个Cookie:for (Cookie cookie : cookies) {// 如果Cookie名称为lang:if (cookie.getName().equals("lang")) {// 返回Cookie的值:return cookie.getValue();}}}// 返回默认值:return "en";
}

可见,读取Cookie主要依靠遍历HttpServletRequest附带的所有Cookie。

4. setSecure测试

下面我自己再实验一下:

4.1 http访问测试

我自己的电脑用的Tomcat,首先,把cookie-secure的值设为false,创建一个session:

 1 public void service(HttpServletRequest request, HttpServletResponse response) {2         // 创建cookie3         Cookie cookie = new Cookie("key", "value");4         // 关键地方:cookie设为false5         cookie.setSecure(false);6         response.addCookie(cookie);7         // 从request中取得cookie,并输出8         Cookie[] cookies = request.getCookies();9         for (Cookie c : cookies) {
10             System.out.println(c.getValue());
11         }
12         RequestDispatcher dispatcher = request
13                 .getRequestDispatcher("index.jsp");
14         try {
15             dispatcher.forward(request, response);
16         } catch (ServletException e) {
17             e.printStackTrace();
18         } catch (IOException e) {
19             e.printStackTrace();
20         }
21     }

好,我们访问一下这个地址:http://localhost:8080/servlet/index.do

用Fiddler来看一下客户端发出的信息:

好,我们再访问一下前面的地址:

这个时候我们可以看到客户端发出的cookie里面,有key=value,说明客户端把cookie发给了服务器端。

4.2 https访问测试

那如果我们在服务器端设置cookie.setSecure(true)呢?

先上代码:

 1 public void service(HttpServletRequest request, HttpServletResponse response) {2         // 创建cookie3         Cookie cookie = new Cookie("key", "value");4         // 关键地方:cookie设为false5         cookie.setSecure(true);
 6         response.addCookie(cookie);7         // 从request中取得cookie,并输出8         Cookie[] cookies = request.getCookies();9         if (cookies != null) {
10             for (Cookie c : cookies) {
11                 System.out.println(c.getValue());
12             }
13         }
14         RequestDispatcher dispatcher = request
15                 .getRequestDispatcher("index.jsp");
16         try {
17             dispatcher.forward(request, response);
18         } catch (ServletException e) {
19             e.printStackTrace();
20         } catch (IOException e) {
21             e.printStackTrace();
22         }
23     }

第一次http访问:

这是request的信息。

服务器的返回信息如下:

我们可以看到服务器发给客户端的信息中有这么一行:Set-Cookie:key=value; Secure

多了一个Secure。

第二次http访问:

我们发现key=value这个cookie已经没有了。

第三次https访问:

那我们用https协议头来试着访问一下看看:

我们看到key=value又发给了服务器端了。

5. 另外

cookie中的数据通常会包含用户的隐私数据,首先要保证数据的保密性,其次要保证数据不能被伪造或者篡改,基于这两点,我们通常需要对cookie内容进行加密,加密方式一般使用对称加密(单密钥,如DES)或非对称加密(一对密钥,如RSA),密钥需要保存在服务器端一个安全的地方,这样,别人不知道密钥时,无法对数据进行解密,也无法伪造或篡改数据。

另外,像上文提到的,重要的cookie数据需要设置成HttpOnly的,避免跨站脚本获取你的cookie,保证了cookie在浏览器端的安全性

还有我们可以设置cookie只作用于安全的协议(https),JavaEE中可以通过Cookie类的setSecure(boolean flag)来设置,设置后,该cookie只会在https下发送,而不会再http下发送,保证了cookie在服务器端的安全性,

6. 例子

import javax.servlet.http.Cookie; //導入方法依賴的package包/類
/*** Creates a new session cookie for the given session ID** @param context     The Context for the web application* @param sessionId   The ID of the session for which the cookie will be*                    created* @param secure      Should session cookie be configured as secure*/
public static Cookie createSessionCookie(Context context,String sessionId, boolean secure) {SessionCookieConfig scc =context.getServletContext().getSessionCookieConfig();// NOTE: The priority order for session cookie configuration is://       1. Context level configuration//       2. Values from SessionCookieConfig//       3. DefaultsCookie cookie = new Cookie(SessionConfig.getSessionCookieName(context), sessionId);// Just apply the defaults.cookie.setMaxAge(scc.getMaxAge());cookie.setComment(scc.getComment());if (context.getSessionCookieDomain() == null) {// Avoid possible NPEif (scc.getDomain() != null) {cookie.setDomain(scc.getDomain());}} else {cookie.setDomain(context.getSessionCookieDomain());}// Always set secure if the request is secureif (scc.isSecure() || secure) {cookie.setSecure(true);}// Always set httpOnly if the context is configured for thatif (scc.isHttpOnly() || context.getUseHttpOnly()) {cookie.setHttpOnly(true);}String contextPath = context.getSessionCookiePath();if (contextPath == null || contextPath.length() == 0) {contextPath = scc.getPath();}if (contextPath == null || contextPath.length() == 0) {contextPath = context.getEncodedPath();}if (context.getSessionCookiePathUsesTrailingSlash()) {// Handle special case of ROOT context where cookies require a path of// '/' but the servlet spec uses an empty string// Also ensure the cookies for a context with a path of /foo don't get// sent for requests with a path of /foobarif (!contextPath.endsWith("/")) {contextPath = contextPath + "/";}} else {// Only handle special case of ROOT context where cookies require a// path of '/' but the servlet spec uses an empty stringif (contextPath.length() == 0) {contextPath = "/";}}cookie.setPath(contextPath);return cookie;
}
/*** 往客戶端寫入Cookie* @param name cookie參數名* @param value cookie參數值* @param maxAge 有效時間,int(單位秒),0:刪除Cookie,-1:頁麵關閉時刪除cookie* @param path 與cookie一起傳輸的虛擬路徑* @param domain 與cookie關聯的域* @param isSecure 是否在https請求時才進行傳輸* @param isHttpOnly 是否隻能通過http訪問*/
public void addCookie(String name, String value, int maxAge, String path, String domain, boolean isSecure, boolean isHttpOnly)
{Cookie cookie = new Cookie(name, value);cookie.setMaxAge(maxAge);cookie.setPath(path);if(maxAge > 0 && domain != null){cookie.setDomain(domain);}cookie.setSecure(isSecure);try{Cookie.class.getMethod("setHttpOnly", boolean.class);cookie.setHttpOnly(isHttpOnly);}catch(Exception e){System.out.println("MyCookie ignore setHttpOnly Method");}response.addCookie(cookie);
}

参考

cookie setSecure详解_wangyunpeng0319的博客-CSDN博客_cookie.setsecure

使用Session和Cookie - 廖雪峰的官方网站

COOKIE的SECURE属性 - 画水 - 博客园

cookie setSecure详解相关推荐

  1. 安全cookie setSecure详解

    http://www.coin163.com/java/docs/201304/d_2775029502.html 在cas中或其他web开发中,会碰到安全cookie的概念,因为CAS中TGT是存放 ...

  2. php的cookie教程,PHP4之COOKIE支持详解

    PHP4之COOKIE支持详解 发布时间:2016-06-17 来源: 点击: 次 PHP4之COOKIE支持详解 建立商业站点或者功能比较完善的个人站点,常常需要记录访问者的信息,在PHP中提供了两 ...

  3. cookie 操作详解 (asp.net javascript)

    (1)ASP.NET cookie 操作详解|cookie 写入.读取.修改.删除2008年10月18日     //写入     protected void Button2_Click(objec ...

  4. python获取登录后的cookie_python爬虫使用cookie登录详解

    前言: 什么是cookie? Cookie,指某些网站为了辨别用户身份.进行session跟踪而储存在用户本地终端上的数据(通常经过加密). 比如说有些网站需要登录后才能访问某个页面,在登录之前,你想 ...

  5. Cookie用法详解

    cookie简介 1. 定义 cookie是由服务器发送给客户端(浏览器)的小量信息. 2. 作用 cookie是键值对形式存储的少量信息,那它有什么作用呢? 我们知道,平时上网时都是使用无状态的HT ...

  6. php 中 app cookie管理,详解iOS App开发中Cookie的管理方法

    一.何为Cookie Cookie是网站为了便是终端身份,保存在终端本地的用户凭证信息.Cookie中的字段与意义由服务端进行定义.例如,当用户在某个网站进行了登录操作后,服务端会将Cookie信息返 ...

  7. 关于登录记住密码使用cookie的详解

    下面是我看的一篇文章引用过来,很易懂 设置cookie 每个cookie都是一个名/值对,可以把下面这样一个字符串赋值给document.cookie: document.cookie="u ...

  8. Javascript cookie使用详解

    2019独角兽企业重金招聘Python工程师标准>>> 设置cookie每个cookie都是一个名/值对,可以把下面这样一个字符串赋值给document.cookie: docume ...

  9. HTTP Session、Cookie机制详解

    一.什么是http session,有什么用 HTTP协议本身是无状态的,本身并不能支持服务端保存客户端的状态信息,于是,Web Server中引入了session的概念,用来保存客户端的状态信息. ...

最新文章

  1. 在CentOS 6.9 x86_64上从源码安装xz命令的方法
  2. pytorch元素相乘_PyTorch – 变量和张量之间的元素乘法?
  3. 多语言切换jquery.i18n.min.js
  4. C# 用户控件之温度计
  5. CTO下午茶: 没有安全,一切创新都是套路
  6. ./dmitry -p ip或者域名 -f -b
  7. DEV GridView嵌套
  8. Docker Compose 项目
  9. Oracle全文索引之五 测试
  10. python机器学习彩票_Python机器学习及实战kaggle从零到竞赛PDF电子版分享
  11. C语言枚举类型(Enum)
  12. Pytorch——计算机视觉工具包:torchvision
  13. Monkey压力测试
  14. centos7安装python开发环境(python3_postgresql_sublime_supervisor)
  15. Spring Cloud Netflix 服务注册与发现 — Eureka 入门案例
  16. u盘的大小在计算机无法显示,U盘格式化后插入电脑打不开,不显示U盘大小怎么解决?...
  17. photoshop图层解锁及不能解锁的原因
  18. uni-app app平台微信支付
  19. 油管613万播放的星巴克3小时背景音乐无广告纯享版下载
  20. Ubuntu Server 12.04 搭建 hadoop 集群版环境——基于VirtualBox

热门文章

  1. 解决远古VOD注入漏洞
  2. KMPLAYER绿色单文件深度专版
  3. 5G NR SIB1介绍
  4. 位是存储在计算机中的最小单位,在计算机中信息存储的最小单位是什么?
  5. 【技术分享】 ​IE浏览器漏洞利用技术的演变 ( 二 )
  6. XP系统上出现的“你可能是盗版软件受害者”的解决方法
  7. php拒绝式服务漏洞防御,PHPYUN最新版SQL注入(绕过防御)
  8. 小心系统入侵之八——招吸星大法(转)
  9. 基于容积卡尔曼滤波(CubatureKalmam Filter, CKF)的车辆状态观测器 Carsim与Simulink联合 可生成C代码
  10. 【已解决】‘node‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件 / 全新安装node