大家好,我是IT修真院郑州分院第十期学员,一枚正直纯洁善良的JAVA程序员。
今天给大家分享一下,修真院官网JAVA任务五,扩展思考中的知识点——什么是cookie?什么是session?
一、背景介绍
HTTP是一种无状态的协议,为了分辨链接是谁发起的,需自己去解决这个问题。不然有些情况下即使是同一个网站每打开一个页面也都要登录一下。而Session和Cookie就是为解决这个问题而提出来的两个机制。
二、知识剖析
1.cookie的主要内容
主要包括:名字,值,过期时间,路径和域。
域:其中域可以指定某一个域比如.google.com,也可以指定一个域下的具体某台机器比如www.google.com或者froogle.google.com。可以在java中通过cookie.setDomain(".soncookie.com"); 设置,这个参数必须以“.”开始。
路径:就是跟在域名后面的URL路径。
路径与域合在一起就构成了cookie的作用范围。
过期时间:如果不设置过期时间,则表示这个cookie的生命期为浏览器会话期间,只要关闭浏览器窗口,cookie就消失了。这种cookie被称为会话cookie。会话cookie是保存在内存里,当然这种行为并不是规范规定的。如果设置了过期时间,浏览器就会把cookie保存到硬盘上,关闭后再次打开浏览器,这些cookie仍然有效直到超过设定的过期时间。
2.session的主要内容:名字,值,失效时间等。
3.Session和Cookie的主要区别:
(1) Cookie是把用户的数据写给用户的浏览器;
(2)Session技术把用户的数据写到用户独占的session中;
(3)Session对象由服务器创建,开发人员可以调用request对象的getSession方法得到session对象。
4.Session和Cookie的应用场景
(1)登录网站,今输入用户名密码登录了,第二天再打开很多情况下就直接打开了。这个时候用到的一个机制就是cookie。
(2)session一个场景是购物车,添加了商品之后客户端处可以知道添加了哪些商品,而服务器端如何判别呢,所以也需要存储一些信息就用到了session。
三、常见问题(详见编码实战)
1.cookie如何完成"增删改查";
2.session如何完成"增删改查"。
四、编码实战
1.目录结构;
2.cookie练习;
(1)cookie.jsp;
<body>
<FONT color="red">${addCookie}</FONT>
<form action="/cookies/addCookie" method="get">
<table>
<tr>
<td>账号</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>密码</td>
<td><input type="text" name="password"></td>
</tr>
<tr>
<td colspan="2"><button type="submit">添加cookie</button></td>
</tr>
</table>
</form>
<hr/>
<FONT color="red">${showCookies}</FONT>
<a href="/cookies/showCookies">查看cookie</a>
<hr/>
<FONT color="red">${editCookie}</FONT>
<form action="/cookies/editCookie" method="get">
<table>
<tr>
<td>想要修改的cookie的name</td>
<td><input type="text" name="name"></td>
</tr>
<tr>
<td>修改后的cookie的value</td>
<td><input type="text" name="value"></td>
</tr>
<tr>
<td colspan="2"><button type="submit">修改指定cookie</button></td>
</tr>
</table>
</form>
<hr/>
<FONT color="red">${deleteCookie}</FONT>
<form action="/cookies/deleteCookie" method="get">
<table>
<tr>
<td>想要删除的cookie的name</td>
<td><input type="text" name="name"></td>
</tr>
<tr>
<td colspan="2"><button type="submit">删除指定cookie</button></td>
</tr>
</table>
</form>
</body>
(2)cookie.jsp;
@Controller
@RequestMapping("/cookies")
public class CookieController {
@RequestMapping(value = "/addCookie")
public String addCookie(Model model,String username,String password, HttpServletResponse response){
model.addAttribute("addCookie","添加cookie成功");
Cookie cookie1 = new Cookie("username", username);
Cookie cookie2 = new Cookie("password", password);
cookie1.setMaxAge(2 * 60);// 设置为1min
cookie2.setMaxAge(10 * 60);// 设置为10min
cookie1.setPath("/");
cookie2.setPath("/cookies");
response.addCookie(cookie1);
response.addCookie(cookie2);
return "cookie";
}
@RequestMapping(value = "/showCookies")
public String showCookies(Model model, HttpServletRequest request){
Cookie[] cookies = request.getCookies();//这样便可以获取一个cookie数组
if (null==cookies) {
model.addAttribute("showCookies","没有cookie信息");
} else {
model.addAttribute("showCookies","成功显示cookie信息");
for(Cookie cookie : cookies){
System.out.println("name:"+cookie.getName()+",value:"+ cookie.getValue());
}
}
return "cookie";
}
@RequestMapping(value = "/editCookie")
public String editCookie(Model model,String name,String value, HttpServletRequest request,HttpServletRes ponse response){
Cookie[] cookies = request.getCookies();
if (null==cookies) {
model.addAttribute("editCookie","没有cookie信息");
} else {
for(Cookie cookie : cookies){
if(cookie.getName().equals(name)){
System.out.println("原值为:"+cookie.getValue());
cookie.setValue(value);
cookie.setPath("/cookies");
cookie.setMaxAge(10 * 60);// 设置为30min
System.out.println("被修改的cookie名字为:"+cookie.getName()+",新值为:"+cookie.getValue());
response.addCookie(cookie);
model.addAttribute("editCookie","成功修改指定cookie信息");
break;
}else {
model.addAttribute("editCookie","没有找到指定cookie");
}
}
}
return "cookie";
}
@RequestMapping(value = "/deleteCookie")
public String deleteCookie(Model model,String name, HttpServletRequest request,HttpServletResponse respo nse){
Cookie[] cookies = request.getCookies();
if (null==cookies) {
model.addAttribute("deleteCookie","没有cookie信息");
} else {
for(Cookie cookie : cookies){
if(cookie.getName().equals(name)){
cookie.setValue(null);
cookie.setMaxAge(0);// 立即销毁cookie
cookie.setPath("/cookies");
System.out.println("被删除的cookie名字为:"+cookie.getName());
response.addCookie(cookie);
model.addAttribute("deleteCookie","指定cookie删除成功");
break;
}else {
model.addAttribute("deleteCookie","没有找到指定cookie");
}
}
}return "cookie";
}
}
(3)展示;
1)输入账号密码,点击添加cookie之后,将添加两个cookie,分别为("username","德玛西亚")和("password","123"),并显示cookie添加成功;
2)点击查看cookie,控制台输出遍历cookie,并显示,成功显示cookie信息(第一个、第四个是刚才添加的),第三个是sessionID,第二个不知道是什么,应该跟浏览器有关;
3)输入要修改的cookie的name以及修改后的value成功修改cookie值(这个其实不能叫修改,是覆盖);
再次查看,这时发现username没有了,因为超时了,可以回头看看上面设置的时间2min;
4)输入要删除的cookie的name,删除cookie;
重新查看,没有了。
3.session练习。
(1)session.jsp;
<body>
<FONT color="red">${addSession}</FONT>
<form action="/session/addSession" method="get">
<table>
<tr>
<td>账号</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>密码</td>
<td><input type="text" name="password"></td>
</tr>
<tr>
<td colspan="2"><button type="submit">添加session</button></td>
</tr>
</table>
</form>
<hr/>
<FONT color="red">${showSession}</FONT>
<a href="/session/showSession">查看session</a>
<hr/>
<FONT color="red">${removeSession}</FONT>
<a href="/session/removeSession">删除创建成功session提示</a>
<hr/>
<FONT color="red">${invalidateSession}</FONT>
<a href="/session/invalidateSession">删除所有session</a>
</body>
(2)sessionController;
@Controller
@RequestMapping("/session")
public class SessionController {
@RequestMapping(value = "/addSession")
public String addCookie(String username, String password, HttpSession session) {
session.setAttribute("username",username);
session.setAttribute("password",password);
session.setAttribute("addSession","session创建成功");
return "session";
}
@RequestMapping(value = "/showSession")
public String showSession( HttpServletRequest request) {
HttpSession session =request.getSession();
System.out.println(session.getAttribute("username"));
System.out.println(session.getAttribute("password"));
System.out.println(session.getId());
session.setAttribute("showSession","展示session成功");
return "session";
}
@RequestMapping(value = "/removeSession")
public String removeSession( HttpSession session) {
session.removeAttribute("addSession");
session.setAttribute("removeSession","addSession提示信息删除成功");
return "session";
}
@RequestMapping(value = "/invalidateSession")
public String invalidateSession( HttpSession session) {
session.invalidate();
return "session";
}
}
(3)展示;
1)输入账号密码,点击添加session之后,将添加两个session,分别为("username","德玛西亚")和("password","123"),并显示session添加成功;
2)点击查看session,控制台打印刚才添加的session信息和session,可以发现这个sessionID和上面cookie的sessionId一致。
3)点击“删除创建成功session提示”,这个有点拗口,观察创建session的接口代码,会发现还创建了一个“session.setAttribute("addSession","session创建成功") ”这句话作为提示信息,由于session在打开浏览器中会一直存在,所以1)中图片红色字“session创建成功”会一直存在,当点击“删除创建成功session提示”这个链接时,session会移除addSession这个attribute,对应红色字会消失;
4)点击删除所有session会调用session.invalidate(),所有session会消失(包括所有提示信息),同时查看会发现sessionID改变。
五、扩展思考
1. session在何时被创建?
一个常见的误解是以为session在有客户端访问时就被创建,然而事实是直到某server端程序调用HttpServletRequest.getSession这样的语句时才被创建。
2.session何时被删除?
(1)程序调用HttpSession.invalidate();
(2)距离上一次收到客户端发送的session id时间间隔超过了session的超时设置;
(3)服务器进程被停止(非持久session)。
3.如何做到在浏览器关闭时删除session?
严格的讲,做不到这一点。可以做一点努力的办法是在所有的客户端页面里使用javascript代码window.oncolose来监视浏览器的关闭动作,然后向服务器发送一个请求来删除session。但是对于浏览器崩溃或者强行杀死进程这些非常规手段仍然无能为力。
六、参考文献
本文主要摘自
https://blog.csdn.net/fangaoxin/article/details/6952954和https://www.cnblogs.com/lonelydreamer/p/6169469.html。
七、更多讨论
1.cookie的httpOnly方法有什么作用?
如果您在cookie中设置了HttpOnly属性,那么通过js脚本将无法读取到cookie信息,这样能有效的防止XSS攻击。
2.如果浏览器禁用cookie怎么办,session怎么用?
这个时候,就需要用到URL重写了,这种方法让服务器收到的每个请求中都带有sessioinId。
URL重写的具体方法是:在每个页面中的每个链接和表单中都添加名为jSessionId的参数,值为当前sessionid。当用户点击链接或提交表单时也服务器可以通过获取jSessionId这个参数来得到客户端的sessionId,找到sessoin对象,来看看具体的例子:
使用response.encodeURL()更加“智能”,它会判断客户端浏览器是否禁用了Cookie,如果禁用了,那么这个方法在URL后面追加jsessionid,否则不会追加。
所以说,建议使用方法二。
3.session集群下如何共享?
(1)粘性session
粘性session是指Ngnix每次都将同一用户的所有请求转发至同一台服务器上,即将用户与服务器绑定。
(2)服务器session复制
即每次session发生变化时,创建或者修改,就广播给所有集群中的服务器,使所有的服务器上的session相同。
(3)session共享
缓存session,使用redis, memcached。
(4)session持久化
将session存储至数据库中,像操作数据一样才做session。