Cookie

  • cookie都是字符串型的键值对,即cookie的键
  • 每一次请求cookie都会自动被携带进请求体
  • 可以存在同名cookie,但是域和路径不能相同
  • 际上,Servlet提供的HttpSession本质上就是通过一个名为JSESSIONID的Cookie来跟踪用户会话的。除了这个名称外,其他名称的Cookie我们可以任意使用。

    返回Cookie

  • cookie位于HttpServletResponse中,方法接收HttpServletResponse即可获取cookie

    • 浏览器application中貌似只显示路径为/的cookie,这之外路径的cookie得在请求体中才能看到
    • cookie不设置过期时间时,默认为离开浏览器即清除。
      • 貌似还有一种持久cookie,会保存于硬盘中,不会随浏览器关闭而清除
    • defaultValue还不清楚
  • 修改、删除Cookie时,新建的Cookie除value、maxAge之外的所有属性,例如name、path、domain等,都要与原Cookie完全一样。否则,浏览器将视为两个不同的Cookie不予覆盖,导致修改、删除失败。
  • 浏览器根据此前缀决定是否发送Cookie。如果一个Cookie调用了setPath(“/user/“),那么浏览器只有在请求以/user/开头的路径时才会附加此Cookie
  • Cookie有一个secure属性,设置了secure时必须以https访问。
    1. @GetMapping("/change-username")
    2. public String setCookie(HttpServletResponse response) {
    3. // 创建一个 cookie,传入键与值,键即cookie的name,都是字符串型
    4. Cookie cookie = new Cookie("username", "rzd");
    5. //设置 cookie过期时间
    6. cookie.setMaxAge(7 * 24 * 60 * 60); //7天
    7. //必须设置路径,否则不生效
    8. cookie.setPath("/");
    9. //添加到 response 中
    10. response.addCookie(cookie);
    11. return "Username is changed!";
    12. }
    | 属性 | 描述 | | —- | —- | | name | Cookie的名称,Cookie一旦创建,名称便不可更改 | | value | Cookie的值。如果值为Unicode字符,需要为字符编码。如果值为二进制数据,则需要使用BASE64编码 | | maxAge | Cookie失效的时间,单位秒。如果为正数,则该Cookie在maxAge秒之后失效。如果为负数,该Cookie为临时Cookie,关闭浏览器即失效,浏览器也不会以任何形式保存该Cookie。如果为0,表示删除该Cookie。默认为-1。 | | secure | 该Cookie是否仅被使用安全协议传输。安全协议。安全协议有HTTPS,SSL等,在网络上传输数据之前先将数据加密。默认为false。 | | path | Cookie的使用路径。如果设置为“/sessionWeb/”,则只有contextPath为“/sessionWeb”的程序可以访问该Cookie。如果设置为“/”,则本域名下contextPath都可以访问该Cookie。注意最后一个字符必须为“/”。 | | domain | 可以访问该Cookie的域名。如果设置为“.google.com”,则所有以“google.com”结尾的域名都可以访问该Cookie。注意第一个字符必须为“.”。 | | comment | 该Cookie的用处说明,浏览器显示Cookie信息的时候显示该说明。 | | version | Cookie使用的版本号。0表示遵循Netscape的Cookie规范,1表示遵循W3C的RFC 2109规范 |

获取Cookie

  • spring框架提供了一个@CookieValue注解以获取特定的Cookie值

    • 必须设置一个键值(value参数;即cookie的key),如果该键值不存在则报错

      1. @GetMapping("/")
      2. public String readCookie(@CookieValue(value = "username", defaultValue = "Atta") String username) {
      3. return "Hey! My username is " + username;
      4. }

      获取所有的Cookie

      ```powershell @GetMapping(“/all-cookies”) public String readAllCookies(HttpServletRequest request) { Cookie[] cookies = request.getCookies(); if (cookies != null) { return Arrays.stream(cookies)

      1. .map(c -> c.getName() + "=" + c.getValue()).collect(Collectors.joining(", "));

      }

      return “No cookies”; }

<a name="Maw2G"></a>
# Session

- session必须通过`HttpServletRequest`获取
   - **session中保存的也是键值对,但是只有键是String型,值任意**
   - `getParameter(String)`得到的是get/post携带的数据,返回类型为String
   - `getAttribute(String)`得到的是session中的数据
   - `removeAttribute(String);`移除一个数据
   - `sendRedirect("/");` 重定向
- 使用Session时,由于服务器把所有用户的Session都存储在内存中,如果遇到内存不足的情况,就需要把部分不活动的Session序列化到磁盘上,这会大大降低服务器的运行效率,因此,放入Session的对象要小,通常我们放入一个简单的User对象就足够了:
- session是一个网站会话只能有一个session,所有用户共享一个session。不同标签页还是一个Session
<a name="b0QQa"></a>
## 使用Session
```java
@GetMapping("/test")
    public String readAllCookies(HttpServletRequest request) {
        HttpSession session = request.getSession();
         String name = req.getParameter("name");  //获取从前端传来的数据
        session.setAttribute("user", name);//添加一个键值对数据到session对象中

        return "No cookies";
    }

Cookie与Session的联系

  • 服务器每一次生成session都会自动生成一个对应的唯一id,即sessionid
  • 一般是通过 Cookie 来保存 SessionID ,假如你使用了 Cookie 保存 SessionID 的方案的话, 如果客户端禁用了 Cookie,那么 Session 就无法正常工作

    • 如果禁用了Cookie,还可以前端生成一个唯一标识,也叫sessionid,通过url返回给后端。但是安全与体验感降低。(当然也可以将该唯一标识加密后传输)

      浏览器本地缓存

  • cookie具有局限性,所以浏览器在发展过程中提供了2种新的本地缓存

    • 有的浏览器限定一个域名只能有几十个cookie,如果达到上限后会清除较少使用的cookie以存新cookie,或者是随机清除。
    • cookie存储大小只有4kb
    • 每一次请求都会自动携带cookie,影响效率,特别是cookie很大时
    • 需要自己封装获取、设置、删除cookie的方法;

      localStorage

  • localStorage是持久化的本地存储,除非是通过js删除,或者清除浏览器缓存,否则数据是永远不会过期的

    sessionStorage

  • sessionStorage用于本地存储一个会话中的数据,这些数据只有在同一个会话中的页面才能访问,并且当会话结束后,数据也随之销毁。

    跨域请求伪造CSRF

  • 别人拿到一个用户的cookie中保存的Sessionid,伪装成用户去访问系统。比如插入攻击链接,让用户误点攻击链接去访问系统(如攻击链接中的请求是转账)

  • 可以通过Token认证的方式避免csrf,token类似于cookie,一般会选择存放在 localStorage (浏览器本地存储)。然后我们在前端通过某些方式会给每个发到后端的请求加上这个 Token,这样就不会出现 CSRF 漏洞的问题,因为非法的链接不会给加上token

    跨站脚本攻击XSS

  • xss是用各种方式将恶意代码注入到其他用户的页面中。就可以通过脚本盗用信息比如 Cookie,不一定是拿cookie去伪造合法请求

  • 无论是cookie还是token,都无法避免xss