Cookie和Session的使用

一,Cookie

cookie的内容主要包括:名字,值,过期时间,路径,域

1.名字:name:cookie的名字不能唯一确定一个Cookie。因为cookie的路径可能不同。但是同一路径下的cookie名字不可重复,否则会覆盖内容。
2.值:value:储存中文要进行转码,防止乱码问题
要想在cookie中存储中文,那么必须使用URLEncoder类里面的encode(String s, String enc)方法进行中文转码

Cookie cookie = new Cookie("Name", URLEncoder.encode("存储的中文", "UTF-8"));
response.addCookie(cookie);

在获取cookie中的中文数据时,再使用URLDecoder类里面的decode(String s, String enc)进行解码

URLDecoder.decode(cookies[i].getValue(), "UTF-8")

3.路径:path:默认值是Cookie的访问路径
path就是当前创建cookie的资源(servlet)文件路径
客户端在访问服务器另外资源时,根据访问的路径来决定是否带着Cookie到服务器
当前访问的路径如果是以cookie的path开头的路径,浏览器就带Cookie,否则不带Cookie。
4.过期时间:maxAge:cookie的缓存时间。默认是-1(默认存在浏览器的内存中)。单位是秒。
负数:cookie的数据存在浏览器缓存中
0:删除。路径要保持一致,否则可能删错cookie。
正数:缓存(持久化到磁盘上)的时间
5.域
域可以指定某一个域,比如.google.com,相当于总公司,也可以指定一个域下的具体某台机器比如www.google.com或者froogle.google.com,相当于分公司。

Cookie代码实例

public class CookieDemo  extends HttpServlet{
//Cookie又称为客户端缓存技术
protected void doGet(HttpServletRequest request, HttpServletResponse response) 
throws ServletException, IOException {
        //response.setIntHeader("refresh", 1);//设置1秒钟刷新一次。
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
            //获取cookie
            Cookie[] cookies = request.getCookies();//获取客户端的所有Cookie对象
            for (int i = 0;cookies!=null && i < cookies.length; i++) {
                if("lastAccessTime".equals(cookies[i].getName())){//判断当前Cookie中的name是否是想要的cookie
                    long l = Long.parseLong(cookies[i].getValue());//如果是想要的Cookie,则把Cookie中的value取出
                    out.write("你的最后访问时间为:"+new Date(l).toString());//输出到浏览器,out.write只能输出字符串,out.print都可以输出

                }
            }
            //新建cookie
            Cookie ck = new Cookie("lastAccessTime",System.currentTimeMillis()+"");//创建cookie
            ck.setMaxAge(50);//设置cookie的有效时间,单位是秒
            ck.setPath("/");//设置cookie的path
            response.addCookie(ck);//把cookie信息写回到客户端
            /*
            //删除cookie
            Cookie ck = new Cookie("lastAccessTime", "");//创建一个Cookie对象
            ck.setPath("/");//要设置被删除Cookie的path,否则可能会删错对象
            ck.setMaxAge(0);//相当于删除
            response.addCookie(ck);//将ck写回客户端缓存
            */
    }
}

二,Session和Session会话

session是解决http协议无状态问题的服务端解决方案,它能让客户端和服务端一系列交互动作变成一个完整的事务,能使网站变成一个真正意义上的软件。

1、Session常用方法

把数据保存在HttpSession对象中,该对象是一个域对象,属于Session域。

void setAttribute(String name,Object value);
Object getAttribute(String name);
void removeAttribute(String name);
HttpSession.getId():
setMaxInactiveInterval(int interval)  设置session的存活时间
invalidate() 使此会话无效

2、在session对象中查找和设置key-value的方法

这个我们一般调用getAttribute/setAttribute方法:

session.getAttribute()方法很简单,就是根据key从map中获取value;
session.setAttribute()方法也很简单,就是向map中设置一个key-value;如果key已经存在,则覆盖value

setAttribute方法如果添加了一些事件监听(HttpSessionAttributeListener)的话,还要通知执行事件监听方法,如beforeSessionAttributeReplaced, afterSessionAttributeReplaced,beforeSessionAttributeAdded,afterSessionAttributeAdded 等事件监听方法。

你可以创建这样的listener去监控session的创建和销毁事件,使得在发生这样的事件时你可以做一些相应的工作。需要注意的是session的创建和销毁动作触发listener,而不是相反。

类似的与HttpSession有关的listener还有HttpSessionBindingListener,HttpSessionActivationListener和HttpSessionAttributeListener。

3、Session 的生命周期

1)Session在用户第一次访问服务器的时候自动创建。
只有访问JSP、Servlet等程序才会创建Session(访问到getSession()代码时)。
只访问 HTML、 等静态资源并不会创建Session。
如果尚未生成Session ,也可以使用request.getSession(true)强制生成。
2)Session生成后,只要用户继续访问,服务器就会更新Session 的最后访问时间,并维护该 Session 。用户每访问服务器一次,无论是否读写 Session ,服务器都认为该用户的 Session “活跃(active)”了一次。
3)关闭浏览器,不会让 Session 结束,Session 是服务器管理的,只有当 session.invalidate() 代码或者配置好的有效时间到了,Session 才会结束。
在web.xml中配置session的有效时间。单位:分钟。

<session-config>
    <session-timeout>30</session-timeout>   
<session-config>

3、服务器如何判断客户端发送过来的请求是属于同一个会话?

使用Session id区分,Session id相同的即认为是同一个会话,在Tomcat中Session id用JSESSIONID表示;

4、服务器、客户端如何获取Session id?Session id在其之间是如何传输的呢?

服务器第一次接收到请求时,开辟了一块Session空间(创建了Session对象),同时生成一个Session id,并通过响应头的Set-Cookie:“JSESSIONID=XXXXXXX”命令,向客户端发送设置cookie的响应;客户端收到响应后,在本机客户端设置了一个JSESSIONID=XXXXXXX的cookie信息,该cookie的过期时间为浏览器会话结束。

在接下来客户端每次向同一个网站发送请求时,请求头都会带上该cookie信息(包含Session id),服务器通过读取请求头中的Cookie信息,获取名称为JSESSIONID的值,得到此次请求的Session id。

服务器只会在客户端第一次请求响应的时候,在响应头上添加Set-Cookie:“JSESSIONID=XXXXXXX”信息,接下来在同一个会话的第二第三次响应头里,是不会添加Set-Cookie:“JSESSIONID=XXXXXXX”信息的;而客户端是会在每次请求头的cookie中带上JSESSIONID信息;只要浏览器未关闭,在访问同一个站点的时候,其请求头Cookie中的JSESSIONID都是同一个值,被服务器认为是同一个会话。

 response.getHeader("Set-Cookie");//可以查看响应头的Set-Cookie的信息
 session.getId(); //得到JSESSIONID

session保存的容器就是cookie,因此当我们完全禁掉浏览器的cookie的时候,服务端的session也会不能正常使用

5.客户端禁用Cookie后的会话数据保存问题

客户端禁用cookie:浏览器永远不会向服务器发送cookie的请求消息头,需要对所有的URL使用URL重写,包括超链接,form的action,和重定向的URL
解决方案:
方案一:在主页上给出提示:请不要禁用您的cookie。
方案二:URL重写。必须对网站的所有地址都重写,即通过get方式得到。
看浏览器有没有发送cookie请求消息头,没有就重写URL,有就不重写。

response.encodeURL(String url); //实现 URL 地址的重写。
response.encodeURL("/");  //进行所有URL重写
response.encodeRedirectURL("/");  //进行重定向 URL重写 
response.sendRedirect(response.encodeRedirectURL("/")); //重定向

这两个用法基本一致,只不过考虑特殊情况,要访问的链接可能会被Redirect到其他servlet去进行处理,
这样用上述方法带来的session的id信息不能被同时传送到其他servlet.这时候用encodeRedirectURL()方法就可以了,如果浏览器禁用cooke,api将自动追加session id ,如果没有禁用,api将不进行任何修改。
注意:如果浏览器禁用cookie,web项目的所有url都需进行重写。否则session将不能正常工作。

5、getSession的内部执行原理

HttpSession request.getSession(boolean create);//默认为true(可空)
如果设置为false,依然会根据客户端JSESSIONID的cookie的值,找对应的HttpSession对象
找不到返回null(不会创建新的,只是查询)

1、获取名称为JSESSIONID的cookie的值。
2、如果没有这样的cookie,创建一个新的HttpSession对象,分配一个唯一的SessionID,并且向客户端写了一个名字为JSESSIONID=sessionID的cookie
3、有这样的Cookie,获取cookie的值(即HttpSession对象的值),从服务器的内存中根据ID找那个HttpSession对象:找到了:取出继续为你服务;找不到:从2开始。

6.session存在的问题

1.安全性

session劫持 : 只要用户知道JSESSIONID,该用户就可以获取到JSESSIONID对应的session内容,用户可以进行修改

2.增加服务器压力

session是直接存储在服务器的内存中的;

3.如果存在多台服务器的话,还存在session同步问题

现在一般的应用都会用到多台tomcat服务器,通过负载均衡,同一个会话有可能会被分配到不同的tomcat服务器,因此很可能出现session不一致问题;解决session同步问题,实际上主要是保证能够抽离出一块共享空间存放session信息,且这块空间不同的tomcat服务器都可以访问到;一般这块共享的空间可以是数据库,或者某台服务器的内存空间,甚至硬盘空间,或者客户端的cookie也是可以的;session的存储应该独立于web容器,也要独立于部署web容器的服务器,最好的解决方案就是使用分布式缓存技术,例如:memcached和redis;将session信息的存储独立出来也是解决session同步问题的方法。

7. 如何做到在浏览器关闭时删除session :严格的讲,做不到这一点。

可以做一点努力的办法是在所有的客户端页面里使用javascript代码window.oncolose来监视浏览器的关闭动作,
然后向服务器发送一个请求来删除session。但是对于浏览器崩溃或者强行杀死进程这些非常规手段仍然无能为力。

三,Session 和 Cookie 的比较。

1、从存取方式上比较:

1)Cookie 中只能存ASCII字符串,其他需要编码。不能直接存 java 对象。
2)Session 中可以存取任何类型的数据,直接保存JavaBean。

2、从隐私安全上比较

1)Cookie存储在客户端,会存在风险。
所以一般一些敏感信息,如密码等尽量不要放入 Cookie,并且对Cookie 信息加密。提交到服务器再解密,保证安全性。
2)Session 存储在服务器,比较安全。

3、从有效期上比较

1)Cookie 的有效期只要设置Cookie 的maxAge即可。
2)Session 如果设置的有效期过长,会导致服务器累计的 Session 过多,导致内存溢出。

4、从对服务器负担上比较

1)Cookie无负担,所以比如大型的网站,电商等都会使用Cookie 追踪客户会话。
2)Session 过多就会影响服务器。

猜你喜欢

转载自blog.csdn.net/bestmy/article/details/81018010