Java Web 内幕学习系列 十、深入理解Session与Cookie
一、理解Cookie
Cookie的作用简单来讲就是用户访问服务器之后,服务器会将一些key/value键值对返回给客户浏览器,并给这些数据加上一些限制条件,在条件符合时,用户下次访问的时候,会将这些数据返回给服务器。
因为HTTP是无状态的协议,服务器无法区分用户的访问是不是和上次访问是同一个用户,Cookie的作用就是帮助服务器区分访问的用户。
1.1 Cookie的属性项
Cookie常用属性项
NAME-VALUE不能使用中文,否则会出现乱码,可以编码之后使用。
使用Cookie 根据不同的浏览器版本,会有不同的Cookie数量以及总大小限制。
当服务器添加多个Cookie时,每个Cookie都会在响应头中返回给浏览器。
1.2 Cookie 常见使用代码
public Cookie getCookie(Cookie[] cookies, String cookieName){
if(cookies != null){
for (Cookie cookie : cookies){
if(cookie.getName().equals(cookieName)){
return cookie;
}
}
}
return null;
}
public void doGet(HttpServletRequest request, HttpServletResponse response){
Cookie[] cookies = request.getCookies();
Cookie userName = getCookie(cookies, "userName");
if(userName == null){
Cookie cookie = new Cookie("userName","ceshi");
//可以设置cookie 的相关属性,例如设置有效期,设置有效域名或者路径
response.addCookie(cookie);
}
}
二、理解Session
Cookie可以解决我们区分访问客户的功能,但是每次浏览器都要传递这些Cookie,如果Cookie很多的时候,就增加了浏览器与服务器之前的传递数据量,Session正好解决了这个问题。
同一个客户端与服务端交互时,不再传递所有Cookie ,只要传递一个ID,这个ID是客户端第一次访问服务端时生成,而且时唯一的。这个ID的NAME为JESSIONID的Coolkie。
2.1 Session 与Cookie
Cookie保存在浏览器,Session保存在服务端
Cookie相对容易被攻击,Session相对安全
Session需要基于一个NAME为JESSIONID的Cookie工作。
如果浏览器不支持Cookie,浏览器会采用URL重写的方式,将NAME为JESSIONID的Cookie加到url中。
注意这个JESSIONID名称不是不可以修改的,可以在webl,xml中添加session-config的配置项,其配置项下面的name属性,就是对应的JESSIONID,可以自定义,一般不建议更改。
2.2 Session 的用法
代码示例
public void doGet1(HttpServletRequest request, HttpServletResponse response){
HttpSession session = request.getSession();
Object userName = (String)session.getAttribute("userName");
if (userName == null){
session.setAttribute("userName","ceshi");
}
}
Session 生命周期是默认时间30分钟,过期失效,服务器关闭时,会将Session持久化到本地磁盘。
三、解决Session和Cookie存在的问题
3.1 多终端共享Session
多终端贡献Session的关键在于服务端必须使用统一的会话架构,统一存储Session。
3.2 多应用单点登录SSO
单点登录也即多个应用使用同一套登录系统,关键在于多应用共享Session。有两种情况,一是多个应用都在统一的顶级域名下面,可以按照多终端共享Session的方式设计,实现相对简单。另外一种情况是多个应用都是独立的顶级域名,这个时候,我们除了要解决共享Session以外,还要解决Cookie跨域名的问题。
3.3 表单重复提交
防止表单重复提交需要标识用户的每一次访问,使得用户每一次访问都是唯一确定的。实现方式如下,用户访问表单页面时,会在服务器生成一个token,传递到表单页面隐藏域,用户提交表单时会校验token是否和服务端的token一致,如果一致,清除服务端token 。这样即便用户出现重复提交,由于token只能校验一次,所以也只能一次的表单提交是有效的。
3.4 多终端登录 扫码登录
3.5 防止Session和Cookie伪造
Cookie会存储用户的一些私密信息,这时如果出现Cookie泄漏,可能会造成用户信息泄漏的危险,因此,在使用Cookie时,我们应尽量避免使用Cookie存储用户的私密信息,如果必须要存储,需要对相关信息进行加密,同时也可以设置Cookie的httpOnly属性,可以防止Cookie被客户端JS等查看。
对于Seesion的安全,我们可以在用户登录的时候,生成一个唯一的Session签名,作为用户唯一的合法登录状态,用户每次访问服务器时,我们都要校验这个签名和服务器重新生成的签名是否一致,如果不一致,让用户重新登录。