1.基础:
session信息是保存在服务器端,而cookie是保存在客户端(浏览器),这个是最基础的概念,如果你这一点都不知道,再去查查资料再往下读。
具体的js、java相关的session与cookie的操作,这里也不在赘述,可以百度之,这里只讲理论。
2.客户端与服务服端交互:
以下提到的“sessionid”只是一个理论上的代号,具体的实现如tomcat的默认sessionId叫:JSESSIONID当然你可以在配置文件中修改这个key,不要把sessionid当做是具体的字段只是一个理论上的代号。
想要得到session信息需要通过session的id在服务器内存中获取,当然第一次客户端访问服务器是没有对应的session信息,第一次服务端需要新建session对象然后把sessionid返回给客户端(这时sessionid存储在cookie中)。
客户端请求服务器的时会带着cookie信息到服务端,cookie里面存储的有sessionid,服务端通过请求信息中的cookie信息得到sessionid再根据sessionid从内存中获取session信息。
所以说如果浏览器禁用cookie也就是说客户端访问服务器,服务器端获取不到cookie信息,因此也获取不到sessionid信息,最终的结果是获取不到session信息(这里忽略通过url传递sessionid这种方法,因为很少人会用这种方法)。如果浏览器禁用cookie有些需要登录的网站就无法获取session信息,无法验证登录信息,此时不能登录网站。
可以试验一下,禁用浏览器的cookie(不同类型的浏览器禁用方法不同),大部分网站都无法登录。
3.具体实现:
服务器获取session信息用request.getSession()方法,可以看一下底层是怎么实现的。
以tomcat为例
RequestFacade类的getsession方法,需下载tomcat的catalina.jar的源码或者反编译
方法中调用的是Request的getsession方法再往下找
很明显服务端是根据sessionid从内存中取,这里只截取关键代码,如果感兴趣可以下载tomcat源码详细看
在往下看requestSessionId是怎样来的:
很明显上图看到是遍历了cookie的值获取sessionid,再往下看一下tomcat中sessionId在cookie中的key值:
public static final String SESSION_COOKIE_NAME =
System.getProperty("org.apache.catalina.SESSION_COOKIE_NAME", "JSESSIONID");
很明显是JSESSIONID;
所以我们在浏览器调试的时候看到的cookie中的JSESSIONID的值就是服务端的sessionid。
以上验证方法可以找一个网站登录,登录之后用浏览器F12查看cookie信息里面有JSESSIONID的信息。
注意:静态资源不通过servlet可以访问的资源,明显的是不会经过服务端的代码处理,所以不会有sessionid相关的信息。
下面把tomcat生成sessionid的方法粘贴出来,有兴趣可以深入研究一下:
protected synchronized String generateSessionId()
{
byte[] random = new byte[16];
String jvmRoute = getJvmRoute();
String result = null;
StringBuffer buffer = new StringBuffer();
do
{
int resultLenBytes = 0;
if (result != null)
{
buffer = new StringBuffer();
this.duplicates += 1;
}
for (; resultLenBytes < this.sessionIdLength; goto 73)
{
getRandomBytes(random);
random = getDigest().digest(random);
int j = 0;
if ((j < random.length) && (resultLenBytes < this.sessionIdLength))
{
byte b1 = (byte)((random[j] & 0xF0) >> 4);
byte b2 = (byte)(random[j] & 0xF);
if (b1 < 10) {
buffer.append((char)(48 + b1));
} else {
buffer.append((char)(65 + (b1 - 10)));
}
if (b2 < 10) {
buffer.append((char)(48 + b2));
} else {
buffer.append((char)(65 + (b2 - 10)));
}
resultLenBytes++;j++;
}
}
if (jvmRoute != null) {
buffer.append('.').append(jvmRoute);
}
result = buffer.toString();
} while (this.sessions.containsKey(result));
return result;
}