何为会话跟踪?举个简单的例子,比如登陆到某购物网站后,在一定时间内无论你在这个网站中切换到任意的网页,只要不执行退出操作,一直保持着你账号的登录状态。

  那么在Java Web中我们应当如何去实现这一操作呢?这里给大家介绍三种技术:cookie、session和URL重写技术。

  首先是cookie技术,cookie在平时我们的使用时经常可以在安全设置中看到,它其实是服务器段在客户端本地保存的一些数据,同之前我们学到的Arribute一样,也是由key-value结构组成的。它是一种在客户端保持绘画跟踪的解决方案。在用户第一次访问服务器时,由服务器通过响应头的方式发送给客户端浏览器;当用户再次向服务器发送请求时会附带上这些文本信息。通过cookie,服务器在手收到来自客户端浏览器的请求时,能够通过分析请求头的内容而得到客户端特有的信息,从而动态的生成与该客户端相对应的内容,比如在很多网站登录时我们会看到类似“记住我”的选项,其实选中了就是把你的登陆信息保存在本地了,下次访问网站时自然而然的就附带了上次的登陆信息,从而达到免再次登陆的功能。

  cookie在javax.servlet.http内的源码:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
// package javax.servlet.http; import java.io.Serializable;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Locale; public class Cookie implements Cloneable, Serializable {
private static final CookieNameValidator validation;
private static final long serialVersionUID = 1L;
private final String name;
private String value;
private int version = ;
private String comment;
private String domain;
private int maxAge = -;
private String path;
private boolean secure;
private boolean httpOnly; public Cookie(String name, String value) {
validation.validate(name);
this.name = name;
this.value = value;
} public void setComment(String purpose) {
this.comment = purpose;
} public String getComment() {
return this.comment;
} public void setDomain(String pattern) {
this.domain = pattern.toLowerCase(Locale.ENGLISH);
} public String getDomain() {
return this.domain;
} public void setMaxAge(int expiry) {
this.maxAge = expiry;
} public int getMaxAge() {
return this.maxAge;
} public void setPath(String uri) {
this.path = uri;
} public String getPath() {
return this.path;
} public void setSecure(boolean flag) {
this.secure = flag;
} public boolean getSecure() {
return this.secure;
} public String getName() {
return this.name;
} public void setValue(String newValue) {
this.value = newValue;
} public String getValue() {
return this.value;
} public int getVersion() {
return this.version;
} public void setVersion(int v) {
this.version = v;
} public Object clone() {
try {
return super.clone();
} catch (CloneNotSupportedException var2) {
throw new RuntimeException(var2);
}
} public void setHttpOnly(boolean httpOnly) {
this.httpOnly = httpOnly;
} public boolean isHttpOnly() {
return this.httpOnly;
} static {
boolean strictServletCompliance;
String propStrictNaming;
String propFwdSlashIsSeparator;
if (System.getSecurityManager() == null) {
strictServletCompliance = Boolean.getBoolean("org.apache.catalina.STRICT_SERVLET_COMPLIANCE");
propStrictNaming = System.getProperty("org.apache.tomcat.util.http.ServerCookie.STRICT_NAMING");
propFwdSlashIsSeparator = System.getProperty("org.apache.tomcat.util.http.ServerCookie.FWD_SLASH_IS_SEPARATOR");
} else {
strictServletCompliance = (Boolean)AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
public Boolean run() {
return Boolean.valueOf(System.getProperty("org.apache.catalina.STRICT_SERVLET_COMPLIANCE"));
}
});
propStrictNaming = (String)AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
return System.getProperty("org.apache.tomcat.util.http.ServerCookie.STRICT_NAMING");
}
});
propFwdSlashIsSeparator = (String)AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
return System.getProperty("org.apache.tomcat.util.http.ServerCookie.FWD_SLASH_IS_SEPARATOR");
}
});
} boolean strictNaming;
if (propStrictNaming == null) {
strictNaming = strictServletCompliance;
} else {
strictNaming = Boolean.parseBoolean(propStrictNaming);
} boolean allowSlash;
if (propFwdSlashIsSeparator == null) {
allowSlash = !strictServletCompliance;
} else {
allowSlash = !Boolean.parseBoolean(propFwdSlashIsSeparator);
} if (strictNaming) {
validation = new RFC2109Validator(allowSlash);
} else {
validation = new RFC6265Validator();
} }
}

从源码中我们可以看到cookie对象的构造函数是public Cookie(String name, String value),那么我们在Servlet中创建cookie也是根据这种构造方法来创建(这里命名为unameCookie):

  Cookie unameCookie = new Cookie("key","value");

创建对象后,我们服务器向客户端响应Cookie时需要这一函数:

  response.addCookie(unameCookie);

通过这两步后,我们便将名字为key,值为value的Cookie对象保存在了用户的客户机上,当我们要使用cookie内保存的数据时时需要通过以下方法获取并遍历:

  Cookie[] cookies = request.getCookie();

  String value = null;

  if(cookies != null){

    for(Cookie c: cookies){

      if(c.getName() .equal("key")){

        value = c.getValue();

      }

    }

  }

这里通过request.getCookie()得到响应头中的cookie内容,然后通过遍历cookie数组比较通过getName()得到的名字,再获取我们需要的值。

但是我们要注意,在默认情况下cookie只能被创建它的应用获取。Cookie的setPath()方法可以重新指定其访问路径,例如将其设置为在某个应用下的某个路径共享,或者在同一服务器内的所有应用共享:

  unameCookie.setPath("/chapter/jsp/");

这样就让unameCookie能在/chapter/jsp/目录下所有的应用共享,当然我们也可以通过以下方式让服务器下的所有应用共享:

  unameCookie.setPath("/");

Cookie有一定的存活时间,不会在客户端一直保存。默认情况下,Cookie保存在浏览器内存中,在浏览器关闭时失效,这种Cookie也成为临时Cookie,若要其长时间保存,我们需要通过setMaxAge()方法设置其存活时间(以秒为单位),时间若为正整数,表示其存活的秒数,若为负数,表示为临时Cookie,若为0,则通知浏览器删除相应的Cookie。

  unameCookie.setMaxAge(60*60);//保存一个小时的cookie

要注意,保存的Cookie仅限在同一个浏览器下且允许Cookie下访问来使用,cookie可能被禁用,可能被其他软件删除,它的大小和个数受限,单个不能超过4kb,很多浏览器都只允许一个站点最多保持20个Cookie,另外,它的安全性也不够高,是以纯文本的形势记录在文件中,最好在保存前加密处理一下。

  再一个就是最常用的Session技术,这是一种在服务器端保持会话跟踪的解决方案,使用了HttpSession对象,这个对象是javax.servlet.http.HttpSession接口的实例,也称为会话对象,该对象用来保存单个用户访问时的一些信息,是服务器在无状态的HTTP协议下用来识别和维护具体某个用户的主要方式。

  HttpSession对象会在用户第一次访问服务器时由容器创建(注意只是在访问JSP、Servlet等程序在会创建,访问静态资源并不会创建),当用户调用其失效方法(invalidate()方法)或超过其最大不活动时间时会失效。在此期间,来自同一客户端的用户与服务器之间的多次请求都属于同一会话。

  服务器在创建会话对象时,会为其分配一个唯一的会话标识:SessionId,以JSESSIONID的属性名保存在客户端Cookie中,在用户随后的请求中,服务器通过该Cookie中的JSESSIONID属性值来识别不同的用户。

  从这里我们看出,实际上通过读取存取临时Cookie我们就可以达到保持用户连接的功能,Session技术实际就是把这一功能规范化,但是数据是存储在服务器上,当访问量增多时会造成服务器性能负担加重,下面我们来看如何使用这一技术。

HttpSession源码:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
// package javax.servlet.http; import java.util.Enumeration;
import javax.servlet.ServletContext; public interface HttpSession {
long getCreationTime(); String getId(); long getLastAccessedTime(); ServletContext getServletContext(); void setMaxInactiveInterval(int var1); int getMaxInactiveInterval(); /** @deprecated */
@Deprecated
HttpSessionContext getSessionContext(); Object getAttribute(String var1); /** @deprecated */
@Deprecated
Object getValue(String var1); Enumeration<String> getAttributeNames(); /** @deprecated */
@Deprecated
String[] getValueNames(); void setAttribute(String var1, Object var2); /** @deprecated */
@Deprecated
void putValue(String var1, Object var2); void removeAttribute(String var1); /** @deprecated */
@Deprecated
void removeValue(String var1); void invalidate(); boolean isNew();
}

Session的使用方法如下:

  获取HttpSession对象:HttpSession session = request.getSession();

  存取会话值属性:

  存储:session.setAttribute("key","name");

  取出:String uanme = (String)session.getAttribute("key");

  移除:session.removeAttribute("key");

  这里实际上和存取Cookie差不多,这一会话在网站服务器路径下的应用中都保持一致,存储的value对象也不仅仅是String,是任意的对象(泛型),需要什么就存什么,只需要在取出是转化为当时存储的类型就好了,

  获取会话的最大不活动时间:

  int time = session.getMaxInactiveInterval();//单位为秒

  设置会话的最大不活动时间:

  session.setMaxInactiveInterval(600);

  设置会话立刻失效:

  session.invalidate();

  服务器在执行会话失效代码后,会立刻清除会话对象及其所有会话域属性,同时响应客户端浏览器清除Cookie中的JSESSIONID。在实际应用中此方法多用来实现系统的“安全退出”,使客户端和服务器彻底结束此次回话,清除所有会话相关信息,防止会话劫持等黑客攻击,

  此外,在多数情况下,Session需要借助Cookie才能正常工作,如果客户端完全禁止Cookie,Session将失效。

  URL重写技术主要是在不能确定客户端浏览器是否支持Cookie的情况下,使用URL重写技术可以对请求的URL地址追加会话标识,从而实现用户的会话跟踪功能。URL重写是指服务器程序对接收的URL请求重新写成网站可以处理的另一个URL过程,URL重写技术是实现动态网站会话跟踪的的重要保障。

  例如对于一个请求地址:http://localhost:8080/chapter/Servlet1

  经过重写后,地址格式变为:http://localhost:8080/chapter/Servlet1;jsessionid=5678978e7r9w7r8we7r8w7e89r7we9

  其中的jsessionid是不是在上一段中是不是很熟悉!!!这就是通过url追加的会话标识,服务器即通过它来识别跟踪某个用户的访问。

  URL重写的示例代码如下所示:

  1.encodeURL方法:out.Print("<a href=' " + response.encodeURL("Servlet1" + " ')'>链接请求</a>")

  2.encodeRedirectURL方法:response.sendRedirect(response.encodeRedirectURL("Servlet1"));

  在使用时,我们通常用一个String对象来获取encodeURL方法得到的链接来进行请求,用encodeRedirectURL方法来进行重定向来进行Session的保持。

  

  还用一种是通过form表单隐藏域来进行,但这种方法只能通过表单来传递标志信息,意义不大,这里不再叙述。

Java Web 学习与总结(三)会话跟踪的更多相关文章

  1. [原创]java WEB学习笔记31:会话与状态管理 session机制 概述(定义,session机制,session的声明周期,保存session的方式,Session的创建与删除)

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  2. [原创]java WEB学习笔记28: 会话与状态管理Cookie 机制

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  3. Java Web学习笔记之---JSP

    Java Web学习笔记之---JSP (一)JSP常用语法 (1)HTML注释 <!--所要注释的内容 --> 在客户端显示一个注释. (2)隐藏注释 <%--所要注释的内容--% ...

  4. JAVA Web学习笔记

    JAVA Web学习笔记 1.JSP (java服务器页面) 锁定 本词条由“科普中国”百科科学词条编写与应用工作项目 审核 . JSP全名为Java Server Pages,中文名叫java服务器 ...

  5. Java Web 学习路线

    实际上,如果时间安排合理的话,大概需要六个月左右,有些基础好,自学能力强的朋友,甚至在四个月左右就开始找工作了.大三的时候,我萌生了放弃本专业的念头,断断续续学 Java Web 累计一年半左右,总算 ...

  6. Java Web学习系列——Maven Web项目中集成使用Spring、MyBatis实现对MySQL的数据访问

    本篇内容还是建立在上一篇Java Web学习系列——Maven Web项目中集成使用Spring基础之上,对之前的Maven Web项目进行升级改造,实现对MySQL的数据访问. 添加依赖Jar包 这 ...

  7. Java Web学习系列——Maven Web项目中集成使用Spring

    参考Java Web学习系列——创建基于Maven的Web项目一文,创建一个名为LockMIS的Maven Web项目. 添加依赖Jar包 推荐在http://mvnrepository.com/.h ...

  8. Java web 学习之旅

    java web学习之旅 来公司十天了,感觉已经慢慢地融入了这个环境中,几个学长人都很好,都是在他们帮助下,我才能比较顺利的开始了学习java web的旅途. 来这里学习的第一个阶段是做一个简单的用户 ...

  9. [原创]java WEB学习笔记95:Hibernate 目录

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  10. [原创]java WEB学习笔记75:Struts2 学习之路-- 总结 和 目录

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

随机推荐

  1. eclipse中项目出现红色的!

    eclipse中项目出现红色的!的原因有二个:1.jdk不匹配    2.缺少jar包

  2. 使用heroku创建应用时报错 heroku does not appear to be a git repository

    在跟着heroku的官方教程创建python应用时,到deploy-the-app这一步,要上传代码到heroku 的git仓库时,报的这个错误: 网上一搜,相关的答案居然极少,首页只出现一篇(还好这 ...

  3. 可用于nodejs的SuperAgent(ajax API)

    简单示例: import request from 'superagent';//引用声明 request.post(api) .withCredentials()//跨域 .end((err, re ...

  4. centos7 ntp服务器配置

    一.ntp服务是什么 1. 定义 NTP是网络时间协议(Network Time Protocol),它是用来同步网络中各个计算机的时间的协议. 2. 发展 首次记载在Internet Enginee ...

  5. Cplus Overolad new and delete Operator

    思考:在C++类中,通过设计类的构造和析构函数,就已经把复杂的内存管理起来了. 及时是简单的结构体,也是有构造和析构函数的,而下面这种情况,可以在非结构中使用. /** Operator Overlo ...

  6. 我的border能自定义四角之border-radius : 左上角,右上角,左下角,右下角。

    1 边框:border: 1px solid #0081df; 2 想要单独加上四个圆角: border-bottom-left-radius: 5px; border-top-left-radius ...

  7. UVa 10603 Fill (暴力BFS+优先队列)

    题意:给定4个数,a,b,c,d,分别代表空杯子容积为a,b,一个盛满水的杯子容积为c,让你不断倒水,找一个dd,是不是存在某个时刻, 某个杯子里的水dd,和d相同,或者无限接近.让求最少的倒水量和d ...

  8. 日志文件(关于#IRSA_MDPS_RDM软件 密码登录事项 7月26号)

    1.登录:sqlplus 用户名:scott 口令:123 qweas.. //2018-7-16号更改密码 2.查看该用户(已登录)下有几个表:select table_name from user ...

  9. swift -pop的简单动画

    //1.新建空文件  命名Podfile //2.写入 pod ‘pop’,’~>1.0’  保存 //3.打开终端,进入项目路径 执行pod install //4.新建桥接头文件 导入#im ...

  10. 23 DesignPatterns学习笔记:C++语言实现 --- 2.4 Composite

    23 DesignPatterns学习笔记:C++语言实现 --- 2.4 Composite 2016-07-22 (www.cnblogs.com/icmzn) 模式理解