Servlet与JSP核心编程(三)

时间:2022-08-10 21:03:29

8、cookie管理

  1. cookie是小段的文本信息,web服务器将它发送到浏览器,之后,在访问同一网站或域时,浏览器又将它原封不动地返回。通过让服务器读取它之前发送给客户程序的信息,站电可以为访问者提供诸多便利,比如按照访问者之前的定制呈现该站点,或让身份可以验证的访问者可以不需要再次输入密码进入
  2. cookie优点
    • 在电子商务会话中标识用户:servlet甚至提供专门用于会话跟踪的API
    • 记录用户名和密码:用户注册后,就会收到包含一个唯一用户ID的cookie。客户重新连接时,这个ID自动返回,服务器对它进行检查,确定它是否为注册用户且选择了自动登录
    • 定制站点:记录用户的偏好
    • 定向广告:记录哪些主题引起特定用户的兴趣,显示相关广告
  3. cookie从不会以任何方式得到解释或执行,因而也就不能插入病毒或攻击用户的系统。此外,由于浏览器一般对每个站点只接受20个cookie,总共不超过300个,同时每个cookie限制在4K,因此cookie不能用来填满某人的硬盘或启动其他拒绝服务(denial-of-service,DoS)攻击。但是可能对隐私造成极大的威胁!应该避免用cookie存储特别敏感的信息。
  4. response.addCookie将cookie插入到HTTP响应报头中;读取输入的cookie,用request.getCookies返回Cookie对象的数组,循环处理这个数组,调用每个cookie的getName方法,直到找到名称与查找的名称相匹配的cookie为止,然后调用getValue方法,检查相关联的值。
  5. 向客户程序发送cookie:例子:Cookie userCookie = newCookie("user", "uid123"); userCookie.setMaxAge(60*60*24*365); // Store cookie for 1 year response.addCookie(userCookie);
    1. 创建Cookie对象:调用Cookie的构造函数,给出cookie的名称和值,二者都是字符串,且都不应该含有空格或这些字符[ ] ( ) = , " / ? @ : ;;Cookie c = new Cookie("CookieName","CookieValue");
    2. 设置最大时效:如果希望浏览器将cookie存储在磁盘上(默认情况下cookie是会话级别的,存储在内存,退出浏览器后被删除),在cookie发送到客户程序之前,使用setMaxAge指定多长时间(秒)内cookie是合法的;c.setMaxAge(60*60*24*7); // One week
    3. 将Cookie放入到HTTP响应报头(前两步只是操作服务器内存中的数据结构,并没有实际向浏览器发送任何内容,对客户程序没有任何影响):必须显示地用response.addCookie,缺少的话,cookie不会发送给浏览器;要记住,响应报头必须在任何文档内容发送到客户端之前设置。
  6. 从客户端读取cookie

    String cookieName = "userID";
    Cookie[] cookies = request.getCookies();
    if(cookies != null) {
    for (int i=0; i<cookies.length; i++) {
    Cookie cookie = cookies[i];
    if(cookieName.equals(cookie.getName())) {
    doSomethingWith(cookie.getValue());
    }
    }
    }
    1. 调用request.getCookies
    2. 对数组进行循环,调用每个cookie的getName方法,直到找到需要的cookie为止,调用getValue以应用程序特有的方式使用这个值。
  7. 属性是从服务器发送到浏览器的报头的一部分,但他们不属于由浏览器返回给服务器的报头。因而,除了名称和值外,cookie属性只适用于从服务器输入到客户端的cookie;因而,不要期望通过request.getCookies得到属性。每次都必须调用setMaxAge,还要将Cookie传递给response.addCookie
  8. 属性cookie属性的方法
    • public void setComment(String comment)
      public String getComment()
      :相关注释,存在于服务器,并不发送给客户程序
    • public void setDomain(String domainPattern)
      public String getDomain()
      :设置或读取cookie适用的域,domainPattern必须以点号开始
    • public void setMaxAge(int lifetime)
      public int getMaxAge()
      :多久过期,负值(默认值)标明cookie仅用于当前浏览会话,指定零值则是指示浏览器删除该cookie
    • public String getName():读取cookie的名称,由于名称是提供给Cookie的构造函数的,因此没有setName方法
    • public void setPath(String path)
      public String getPath()
      :cookie所适用的路径;如果没有指定一个路径,浏览器只将该cookie返回给发送cookie的页面所在目录中或之下的URL;cookie.setPath(“/”)指定服务器的所有页面都应该受到该cookie
    • public void setSecure(boolean secureFlag)
      public boolean getSecure()
      :表明cookie是否只能通过加密连接(即SSL)发送,默认值是false,表示cookie适用于所有的连接
    • public void setValue(String cookieValue)
      public String getValue()
      :setValue方法指定与该cookie相关联的值,getValue找出这个值
    • public void getVersion(int version)
      public int getVersion()
      :cookie协议版本,默认值版本0
  9. 周期性修改cookie的值:要替换cookie之前的值,需要发送相同的cookie名称,但使用不同cookie值。只调用setValue是没有效果的,不要忘记调用response.addCookie、setMaxAge、setPath等,重新应用所有的相关cookie属性;要指示浏览器删除一个cookie,只需setMaxAge(0)
  10. 使用cookie记录用户的偏好,对于简单的用户设置,可以直接将用户的偏好存储在cookie中,对于更为复杂的应用,一般在cookie中存储唯一的用户标识,而将实际的偏好存储在数据库中。

9、会话跟踪

  1. HTTP是“无状态”协议:客户程序每次读取Web页面,都代开web服务器的单独的连接,并且,服务器也不自动维护客户的上下文信息。对于上下文信息的缺失存在三种典型的解决方案:
    1. cookie:处理会话时最常使用的方式
    2. URL重写:客户程序在每个URL的尾部添加一些额外数据,标识当前的会话,服务器将这个标识符与它存储的用户相关数据关联起来;不能有任何静态HTML页面,至少静态页面中不能有任何链接到站点动态页面的链接。
    3. 隐藏的表单域<input type="hidden" name="session" value="a1234">在提交表单时,将指定的名称和值自动包括在GET或POST数据中。仅当每个页面都是由表单提交而动态生成时才能使用;不能支持通常的会话跟踪,只能用于特定的操作,如在线商店的结账过程。
  2. servlet提供了一种出色的会话跟踪解决方案:HttpSession API;所有服务器都需要支持cookie的会话跟踪。
  3. 会话跟踪4个基本步骤
    1. 访问与当前请求相关联的会话对象:HttpSession session = request.getSession();存储任意用户对象的散列表;只能在发送任何文档内容到客户程序之前调用request.getSession
    2. 查找与会话相关联的信息:SomeClass value = (SomeClass)session.getAttribute("someIdentifier");在调用与会话相关联的对象的方法之前,一定要检查它是否为null
    3. 存储会话中的信息:session.setAttribute("someIdentifier", value);setAttribute会替换掉任何之前设定的值,如果想要在不提供任何替代的情况下移除某个值,使用removeAttribute
    4. 废弃会话数据
      • 只移除自己编写的servlet创建的数据:removeAttribute(“key”)
      • 删除整个会话(在当前Web应用中):调用invalidate
      • 将用户从系统中注销并删除所有属于它的会话:logout
  4. HttpSession类的方法汇总
    • public Object getAttribute(String name):从会话对象提取之前存储的值,若没有值与name关联,返回null
    • public Enumeration getAttributeNames():返回会话中所有属性名
    • public void setAttribute(String name, Object value):将值和名称关联
    • public void removeAttribute(String name):移除与name关联的任何值
    • public void invalidate():会话作废,释放所有与之相关联的对象
    • public void logout():将客户从Web服务器注销,并将相关会话全部作废
    • public String getId():返回每个会话对应的唯一标识符
    • public boolean isNew():若会话尚未和客户程序发生任何联系,返回true,避免使用
    • public long getCreationTime():返回会话首次构建的时间
    • public long getLastAccessedTime():返回会话最后被客户程序访问的时间
    • public int getMaxInactiveInterval()
    • public void setMaxInactiveInterval(int seconds):读取或设置在没有访问的情况下,会话在被自动废弃之前应该保持多长时间,以秒为单位。负值表示会话从不超时。超时由服务器来维护,它不同于cookie的失效日期。
  5. 默认地,servlet容器使用cookie作为会话跟踪的底层机制;如果你使用URL重写进行会话跟踪来代替cookie,你的大部分或全部页面都必须动态生成,你站点上的任何静态HTML页面都不能含有指向自身站点动态页面的链接。
  6. Integer是一种immutable(不可修改)的数据结构:构建后就不能更改,这意味着每个请求都必须分配新的Integet对象,之后使用setAttribute来替代老的对象;对于可修改的数据结构,如数组、List、Map或含有实例变量的应用程序专有数据结构,仅当会话中不存在这种对象时才分配对象并调用setAttribute,除非首次分配对象,每个改变对象的内容,会话维护队一个对象的引用。