前几天在调试第三方支付接口时碰到一个session失效问题,用了几天时间才搞明白,现在回想一下,主要还是由于cookie和session这一块的一些基本概念没有搞清楚,现总结一下。
浏览器使用HTTP协议作为应用层协议,而HTTP协议是一个无状态协议,但是通常web站点希望能够识别用户,可能是因为服务器希望限制用户的访问,或者因为它希望把内容与用户身份联系起来。这就需要将浏览器与web服务器之间多次交互当作一个整体来处理,并且将多次交互所涉及的数据及状态保存下来,通常有两种方案:cookie和session。
cookie
服务器为了识别用户身份而临时存放在浏览器端的少量数据。浏览器器访问服务器时,服务器将一些数据以Cookie消息头的形式发送给浏览器(由程序指定),浏览器会将这些数据保存下来;当浏览器再次访问服务器时,会将这些数据以Cookie消息头的方式发送给服务器。
使用Cookie
//添加Cookie Cookie c = new Cookie(String name,String value); response.addCookie(c); //读取Cookie Cookie[] request.getCookies(); String cookie.gtName() String cookie.getValue()
Cookie编码问题
cookie只能存放合法的ascii字符,如果要存放中文,可以将中文转换成合法的asscii字符形式,通过如下方式进行编解码,编码后的字符串可以存到cookie中,读取时再进行解码。
String URLEncoder.encode(String str,String charset); //编码 String URLDecoder.decode(String str,String charset); //解码
Cookie生存时间问题
可以通过cookie.setMaxAge(int seconds)来设置:
seconds>0,浏览器会将cookie保存在硬盘上,超过指定时间cookie失效;
seconds<0,默认值,浏览器会将cookie存在内存中,关闭浏览器后cookie失效;
seconds=0,删除cookie;
Cookie的路径问题
浏览器端保存的cookie内容主要包括:名字,值,过期时间,路径和域名。
浏览器在访问服务器上的某个地址时,会比较Cookie的路径与该路径是否匹配,浏览器只会将路径匹配的Cookie发送给服务器。cookie的默认路径为添加该cookie的web组件的路径,比如/servlet/addCookie.jsp添加了一个cookie,则浏览器端保存该cookie对应的默认路径为:/servlet。
在浏览器端一般会保存多个cookie,当浏览器要访问服务器时如何决定要将哪个cookie添加至消息头中呢?
匹配规则如下:
要访问的地址必须是cookie的路径或其子路径,而且域名需一致。
比如浏览器端保存的cookie的路径是/servlet/work/,当访问/servlet/buy.jsp这个页面时是不会将该cookie放入消息头中的,而当访问/servlet/work/buy.jsp或/servlet/work/flow/buy.jsp两者之一时,浏览器是会将前面的cookie放入消息头之中的。
cookie的限制
a.cookie不安全
b.cookie可以被用户禁止
c.cookie只能保存少量数据,4k左右
d.浏览器保存的cookie的数量也有限制(大约几百个)
e.cookie只能保存字符串
session(会话)
服务器端为了保存状态而创建的一个特殊的对象。
浏览器访问服务器时,服务器会创建一个特殊对象session(由程序指定,该对象有一个唯一的id,本文称之为sessionId),服务器会将sessionId以cookie形式发送给浏览器;当浏览器再次访问服务器时,会在消息头中带有包含sessionId的cookie消息头,服务器端可以利用这个sessionId找到相应的对象,来保存一些状态值。
使用session
//方式一
HttpSession session = request.getSession(boolean flag); //当flag为true时,先查看请求当中有没有sessionId,如果有,则依据该sessionId查找对应的session对象,找到则返回,找不到则创建新session对象;如果请求当中没有,则直接创捷session对象;
//当flag为false,与true类似,只是在没有找到session对象时返回空
//方式二
HttpSession session = request.getSession(); //等价于request.getSession()
session超时
服务器会将空闲时间过长的session对象删除掉,这样做是为了节省内存空间的占用。服务器默认的超时时间一般是30分钟。可以通过setMaxInactiveInterval(int seconds)来设置两次请求之间的最大时间间隔,也可看成是失效时间,如果超过这个失效时间,则服务器会销毁这个session对象。
使用session场景
比如登陆控制,在登陆成功后,将一些数据绑定到session对象上,如:
session.setAttribute("user",user);
当用户请求要保护的资源(只有登陆成功才能访问的资源)时候,进行session验证:
Object obj = session.getAttribute("user"); if(obj == null){ //没有登陆,重定向到登陆页面response.sendRedirect("login.jsp)"; }
注:以上关于session和cookie的demo是在tomcat容器下测试的