cookie setSecure详解

2023-05-16

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         // 创建cookie
 3         Cookie cookie = new Cookie("key", "value");
 4         // 关键地方:cookie设为false
 5         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         // 创建cookie
 3         Cookie cookie = new Cookie("key", "value");
 4         // 关键地方:cookie设为false
 5         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. Defaults

    Cookie 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 NPE
        if (scc.getDomain() != null) {
            cookie.setDomain(scc.getDomain());
        }
    } else {
        cookie.setDomain(context.getSessionCookieDomain());
    }

    // Always set secure if the request is secure
    if (scc.isSecure() || secure) {
        cookie.setSecure(true);
    }

    // Always set httpOnly if the context is configured for that
    if (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 /foobar
        if (!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 string
        if (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属性 - 画水 - 博客园

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

cookie setSecure详解 的相关文章

随机推荐

  • Redis实战—黑马点评(一) 登录篇

    Redis实战 黑马点评 xff08 一 xff09 登录篇 来自黑马的redis课程的笔记 黑马程序员Redis入门到实战教程 xff0c 深度透析redis底层原理 43 redis分布式锁 43 企业解决方案 43 黑马点评实战项目
  • tigerVNC的简单使用教程(CentOS的远程桌面连接)

    tigerVNC的简单使用教程 xff08 CentOS的远程桌面连接 xff09 1 环境和软件准备 1 CentOS 6 3下 root 64 localhost rpm q tigervnc tigervnc server tiger
  • Redis实战—黑马点评(二)缓存篇

    Redis实战 黑马点评 xff08 二 xff09 缓存篇 目录 Redis实战 黑马点评 xff08 二 xff09 缓存篇1 什么是缓存1 1 缓存的作用和成本 2 添加 Redis 缓存3 缓存更新策略3 1 三种更新策略3 1 1
  • Reids实战—黑马点评(三)秒杀篇

    Reids实战 黑马点评 xff08 三 xff09 秒杀篇 来自黑马的redis课程的笔记 黑马程序员Redis入门到实战教程 xff0c 深度透析redis底层原理 43 redis分布式锁 43 企业解决方案 43 黑马点评实战项目
  • RT-Thread Stm32f103开启UART2(中断接收及轮询发送) 使用RT-Thread Studio

    RT Thread Stm32f103开启UART2 使用RT Thread Studio 1 使用RT Thread Studio新建RT Thread项目 2 修改dricer gt doard h 增加UART2的宏定义设置gpio接
  • 串口收发数据

    1 1 字符串接收函数 发送方结束标志是你接收方判断的依据 xff0c 也可以说是属于协议的一部分 我们这里使用串口助手数据发送自动添加了 r n xff0c 所以我们将它们看成结束标志 1 2 数据传输方式 计算机与外部进行沟通只有并行和
  • VsCode Studio的C/C++代码自动补全

    关于VsCode Studio的C C 43 43 代码自动补全 第一步 xff1a 需要下载VsCode中的C C 43 43 插件 如图 xff1a 插件下载后 xff0c 最好是重新启动一下VS 第二步 xff1a 找到设置 在输入框
  • Nginx lua设置Cookie,及学习Cookie

    网上看到这篇文章 xff0c 很喜欢这种分析思路 xff0c 这里学习记录一下 最近小了解了下cookie 以前觉得cookie无非就是一连串键值对 在深入了解之后发现 远没自己想的那么简单 自己果真太肤浅了 好吧 这里主要探讨一下以下几个
  • nginx中不同client设置User-Agent与user_agent的坑

    最近发现nginx内部用lua获取user agent xff0c 得到的是一个table值 xff0c 很奇怪 xff0c 自己测试记录一下 xff1a 1 nginx配置 location zcy hello set by lua re
  • Nginx - request_time和upstream_response_time详解

    网上查了查资料 xff0c 这里记录一下 前言 最近分析服务器性能 xff0c 考虑到nginx在前面做反向代理 xff0c 这里查一下nginx日志来反应服务器处理时间的问题 注 xff1a 本文提到的所有变量 xff0c 如果需要区分
  • Spring Boot 2.3.0 Redis拓扑动态感应,使用Lettuce拓扑刷新

    背景 关于 Redis 在生产中我们一般情况下都会选择 redis cluster 高可用架构部署 xff0c 既能保证数据分片并且实现节点的故障自动转移 基本部署拓扑如下 xff1a 创建测试集群 这里通过我封装的 pig4cloud r
  • Country Codes and Language Codes

    ISO 3166 Country Codes and ISO 639 Language Codes 1 ISO 3166 Country Codes Table 20 1 ISO 3166 Country Codes Country ISO
  • SIP 注册过程

    SIP协议包含两种类型的消息 xff0c 一种是请求行用于发出邀请 xff0c 而另一种则是状态行 xff0c 用于标明当前通信的状态 请求行和状态行军包含三部分 xff0c 其中每一部分以空格隔开 xff0c 不论是请求行还是状态行均以C
  • UUID原理,以及JAVA生成短8位UUID

    最近需要生成短uuid xff0c 网上查了查资料 xff0c 这里整理记录一下 xff0c 供大家参考 1 前言 UUID xff0c 全名叫做 Universally Unique Identifier xff0c 也就是通用唯一标识符
  • user agent查询(iPhone/ Android/ iPad/ Windows Phone/ Macintosh)

    这里分享一个查询user agent的网站 xff0c 里面可以搜索各个平台的user agent 1 网页 例如 xff1a iPhone的user agent https www plus a net tools user agent
  • 跨源资源共享(CORS)

    转自 https developer mozilla org zh CN docs Web HTTP CORS 跨源资源共享 CORS xff08 或通俗地译为跨域资源共享 xff09 是一种基于HTTP 头的机制 xff0c 该机制通过允
  • 工业软件CAD、CAE、CAM介绍

    最近看了一篇文章介绍工业软件CAD CAE CAM xff0c 这里记录分享一下 自从上世纪八十年代工业软件出现后 xff0c 设计师们终于不用通过手绘来完成图纸的设计了 xff0c 转而在电脑上完成 xff0c 设计效率极大提高 那么工业
  • 502 bad gateway原因、解决方法

    nbsp 网上查了查资料 这里记录一下 nbsp nbsp nbsp 在当今时代 每个人都使用互联网 通常 在使用 Internet 和访问网页时 计算机和网站之间可能会出现连接问题 这些连接问题会产生某些错误代码 称为 nbsp HTTP
  • Lombok详解

    网上看到这篇文章 xff0c 这里记录学习一下 用 x1f336 Lombok xff0c 让 Java 更简洁 ENCODE the WORLD 零 历史 一个标准的 Java bean 一个典型的 Java bean 一般具有几个属性
  • cookie setSecure详解

    1 前言 最近项目用Sparrow Health System检测漏洞 xff0c 发现存在一个setSecure安全漏洞问题 xff0c 于是网上搜索了一下 xff0c 这里记录一下 2 问题 在cas中或其他web开发中 xff0c 会