Cookie
- cookie都是字符串型的键值对,即cookie的键
- 每一次请求cookie都会自动被携带进请求体
- 可以存在同名cookie,但是域和路径不能相同
际上,Servlet提供的HttpSession本质上就是通过一个名为JSESSIONID的Cookie来跟踪用户会话的。除了这个名称外,其他名称的Cookie我们可以任意使用。
返回Cookie
cookie
位于HttpServletResponse
中,方法接收HttpServletResponse
即可获取cookie- 浏览器application中貌似只显示路径为
/
的cookie,这之外路径的cookie得在请求体中才能看到 - cookie不设置过期时间时,默认为离开浏览器即清除。
- 貌似还有一种持久cookie,会保存于硬盘中,不会随浏览器关闭而清除
defaultValue
还不清楚
- 浏览器application中貌似只显示路径为
- 修改、删除Cookie时,新建的Cookie除value、maxAge之外的所有属性,例如name、path、domain等,都要与原Cookie完全一样。否则,浏览器将视为两个不同的Cookie不予覆盖,导致修改、删除失败。
- 浏览器根据此前缀决定是否发送Cookie。如果一个Cookie调用了setPath(“/user/“),那么浏览器只有在请求以/user/开头的路径时才会附加此Cookie
- Cookie有一个secure属性,设置了secure时必须以https访问。
| 属性 | 描述 | | —- | —- | | 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规范 |@GetMapping("/change-username")
public String setCookie(HttpServletResponse response) {
// 创建一个 cookie,传入键与值,键即cookie的name,都是字符串型
Cookie cookie = new Cookie("username", "rzd");
//设置 cookie过期时间
cookie.setMaxAge(7 * 24 * 60 * 60); //7天
//必须设置路径,否则不生效
cookie.setPath("/");
//添加到 response 中
response.addCookie(cookie);
return "Username is changed!";
}
获取Cookie
spring框架提供了一个
@CookieValue
注解以获取特定的Cookie值必须设置一个键值(value参数;即cookie的key),如果该键值不存在则报错
@GetMapping("/")
public String readCookie(@CookieValue(value = "username", defaultValue = "Atta") String username) {
return "Hey! My username is " + username;
}
获取所有的Cookie
```powershell @GetMapping(“/all-cookies”) public String readAllCookies(HttpServletRequest request) { Cookie[] cookies = request.getCookies(); if (cookies != null) { return Arrays.stream(cookies)
.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具有局限性,所以浏览器在发展过程中提供了2种新的本地缓存
localStorage是持久化的本地存储,除非是通过js删除,或者清除浏览器缓存,否则数据是永远不会过期的
sessionStorage
sessionStorage用于本地存储一个会话中的数据,这些数据只有在同一个会话中的页面才能访问,并且当会话结束后,数据也随之销毁。
跨域请求伪造CSRF
别人拿到一个用户的cookie中保存的
Sessionid
,伪装成用户去访问系统。比如插入攻击链接,让用户误点攻击链接去访问系统(如攻击链接中的请求是转账)可以通过Token认证的方式避免csrf,token类似于cookie,一般会选择存放在 localStorage (浏览器本地存储)。然后我们在前端通过某些方式会给每个发到后端的请求加上这个 Token,这样就不会出现 CSRF 漏洞的问题,因为非法的链接不会给加上token
跨站脚本攻击XSS
xss是用各种方式将恶意代码注入到其他用户的页面中。就可以通过脚本盗用信息比如
Cookie
,不一定是拿cookie去伪造合法请求- 无论是cookie还是token,都无法避免
xss