javaweb开发(七):cookie和session
cookie简介
# 浏览器发送request请求到服务器,服务器除了返回请求的response之外,还给请求分
配⼀个唯⼀标识ID和response⼀并返回给浏览器
# 服务器在本地创建⼀个map结构,专⻔以key-value存储这个ID标识和浏览器的关系
# 当浏览器的第⼀次请求后已经分配⼀个ID,当第⼆次访问时会⾃动带上这个标识ID,服
务会获取这个标识ID去map⾥⾯找上⼀次request的信息状态且做对应的更新操作 服务
端⽣成这个全局的唯⼀标识,传递给客户端⽤于标记这次请求就是cookie; 服务器创建
的那个map结构就是session
# cookies由服务端⽣成,⽤于标记客户端的唯⼀标识,在每次⽹络请求中,都会被传
送
# session服务端⾃⼰维护的⼀个map数据结构,记录key-Object上下⽂内容状态
核⼼:它⽤于告知服务端两个请求是否来⾃同⼀浏览器,如保持⽤户的登录状态
# Cookie使基于⽆状态的HTTP协议记录稳定的状态信息成为了可能。 浏览器查看多个站
点的cookie
- cookie的属性
Name : 名称
Value : 值
Domain:表示当前cookie所属于哪个域或⼦域下⾯
Expires/Max-age:表示了cookie的有效期,是⼀个时间,过了这个时间,该cookie就失效了
Path:表示cookie的所属路径。
size: ⼤⼩,多数浏览器都是4000多个字节
http-only: 表示这个cookie不能被客户端使⽤js读取到,是不公开的cookie,(chrome调试器的console中输⼊document.cookie将得不到标记为HttpOnly的字段)
Secure: 标记为 Secure 的Cookie只应通过被HTTPS协议加密过的请求发送给服务端, 从 Chrome 52 和 Firefox 52 开始,不安全的站点(http:)⽆法使⽤Cookie的 Secure标记
SameSite(特有的,可以忽略)
- cookie缺陷
cookie会被附加在每个HTTP请求中,增加了流量。
在HTTP请求中的cookie是明⽂传递的,所以安全性成问题,除⾮⽤HTTPS
Cookie的⼤⼩有限制,对于复杂的存储需求来说不满⾜
- 浏览器允许每个域名所包含的cookie数量
多数浏览器允许最多是50个,部分浏览器是30或者20;
满后会有多种剔除策略,⽐如LRU,权重等
cookie实战
客户端第1次请求服务端时,服务端会返回cookie和response
客户端将cookie存储起来
客户端第2次及以后每次访问服务端都会带上cookie
- 获取第1次请求的cookie
@WebServlet("/get_cookie")
public class GetCookieServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Cookie[] cookies = request.getCookies();
for(Cookie cookie : cookies){
System.out.println(cookie.getDomain());
System.out.println(cookie.getName());
System.out.println(cookie.getValue());
}
}
}
- 测试,控制台清空后访问,访问后返回cookie
http://localhost:8080/get_cookie
# 控制台输出
null
JSESSIONID
FF39D4A8A5EBC89F25969E1BD4FC602A
- 自定义cookie并返回给前端
@WebServlet("/gene_cookie")
public class GeneCookieServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 创建cookie对象
Cookie cookie = new Cookie("token","sfwerawefewadaewfafewafa");
//20秒过期时间,过期后不会自动携带过去
cookie.setMaxAge(20);
// 返回时,返回cookie
response.addCookie(cookie);
// 转发页面
request.getRequestDispatcher("/index.jsp").forward(request,response);
}
}
- 测试
http://localhost:8080/gene_cookie
- session简介
# 浏览器第⼀次发送request请求到服务器,服务器除了返回请求的response之外,还给请求
分配⼀个唯⼀标识sessionId和response⼀并返回给浏览器
# 服务器在本地创建⼀个map结构,专⻔以key-value存储这个sessionId和浏览器的关系
# 当浏览器的第⼀次请求后已经分配⼀个sessionId,当第⼆次访问时会⾃动带上这个标识
sessionId
# 服务器通过查找这个sessionId就知道⽤户状态了,并更新sessionId的最后访问时间
注意: Session是有时限性的:⽐如如果30分钟内某个session都没有被更新,服务器就会删
除这个它
- cookie与session的关系
服务端⽣成这个全局的唯⼀标识,传递给客户端⽤于标记这次请求就是cookie
服务器创建的那个map结构就是session
cookies由服务端⽣成,⽤于标记客户端的唯⼀标识,在每次⽹络请求中,都会被传送。
session服务端⾃⼰维护的⼀个map数据结构,记录key-Object上下⽂内容状态
总⾔之cookie是保存在客户端,session是存在服务器,session依赖于cookie
cookie⾥⾯存储的就是JSESSIONID
- 拓展
# session是存储在服务端的内存中,在javaweb⾥⾯叫HttpSession也是⼀个作⽤域
# PageContext(⻚⾯)->ServletRequest(请求)->【HttpSession】(会话)->ServletContext(⼀个
应⽤)
# 是可以存储很多key-value的,作⽤域⽐较⼴,所以也不能存储过多内容,因为内存是有限制
的,互联⽹企业使⽤⽐较少,传统IT公司使⽤⽐较多
- 创建sessionid
# 创建SessionServlet
@WebServlet("/session")
public class SessionServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 创建session对象
HttpSession session = request.getSession();
//获取sessionid,java里面叫jsessionid
System.out.println("sessionid="+session.getId());
//创建时间戳,毫秒
System.out.println("getCreationTime="+session.getCreationTime());
//是否是初次创建,记得情况浏览器的cookie,验证sessionid
System.out.println("isNew="+session.isNew());
//往session存储东西
session.setAttribute("name","goudan");
}
}
- 启动项目测试
- 清空session
- 第1次访问,返回sessionid
# 控制台,表示初次创建
sessionid=8BFC3D3140B3539B18DF1348EBC369ED
getCreationTime=1649860447633
isNew=true
- 第2次访问
# 控制台打印如下,表示不是第一次创建
sessionid=8BFC3D3140B3539B18DF1348EBC369ED
getCreationTime=1649860447633
isNew=false
- session实现登录
# 编写LoginServlet
@WebServlet("/loginServlet")
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 获取参数
String name = req.getParameter("name");
String pwd = req.getParameter("pwd");
// 如果用户名和密码正确,则将用户信息存入session
if(name.equals("user") && pwd.equals("123")){
User user = new User();
user.setId(121);
user.setName(name);
user.setHost("xdclass.net");
req.getSession().setAttribute("loginUser",user);
// 登录成功后,转发到user.jsp
req.getRequestDispatcher("/WEB-INF/user.jsp").forward(req,resp);
}else{
// 登录失败后,返回错误信息存入领域对象中,并转发到login.jsp
req.setAttribute("msg","账号密码错误");
req.getRequestDispatcher("/login.jsp").forward(req,resp);
}
}
}
# 编写LogoutServlet
@WebServlet("/logout_servlet")
public class LogoutServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 退出登录时,销毁session,并转发到login.jsp
HttpSession session = request.getSession();
session.invalidate();
request.getRequestDispatcher("/login.jsp").forward(request,response);
}
}
# 编写登录成功的页面,user.jsp
<body>
id:${loginUser.id}
<br>
name:${loginUser.name}
<a href="/logout_servlet">退出</a>
</body>
# 编写登录页面,login.jsp
<body>
<form action="<%=request.getContextPath()%>/loginServlet" method="post">
名称:<input type="text" name="name"/>
<br/>
密码:<input type="password" name="pwd"/>
<input type="submit" value="登录">
消息提示 ${msg}
</form>
</body>
# web.xml中设置session超时时间
<session-config>
<session-timeout>30</session-timeout>
</session-config>
-
启动项目测试
-
登录成功
-
退出登录,销毁sessionid,生成新的sessionid
-
个人理解
# 客户端首次访问服务器时,服务器生成sessionid,将sessionid保存在cookie中发送个客户端;服务端则将sessionid保存在session中,记录了这个请求与服务端的关系
# 客户端再次访问服务端时,就会带上cookie,服务端拿到cookie中的sessionid,与session中id比较,一致则允许访问
# 当服务端的session失效时,则会生成新的sessionid返回给客户端