目录
1:什么是HTTP协议
HTTP协议(HyperText Transfer Protocol,超文本传输协议)是因特网上应用最为广泛的一种网络传输协议,所有的WWW文件都必须遵守这个标准。http是基于tcp/ip通信来实现传递数据(html文件,图片文件,查询结果等)
http是基于客户端/服务器(C/S)的架构模型,通过一个可靠的连接来交换数据,是无状态的请求相应协议。
HTTP客户端可以是一个应用程序比如浏览器或者其他任何客户端。HTTP服务器同样是一个应用程序,比如tomcat或者其他服务器
HTTP使用统一的资源标识符(Uniform Resource Identifiers, URI)来传输数据可创建链接。
http请求:request
http响应:response
1.1URL和URI的区别
URI强调的是给资源标记命名,可以是一个网站,邮箱地址。你的qq号也是一个URI资源仅仅想对腾讯,是一种资源标记命名,URI 可以是绝对的,也可以是相对的,URI仅仅是标记了一个资源。你不一定能操作这个资源。
也就是说URI是以一种抽象的,高层次概念定义统一资源标识
URL强调的是给资源定位:指定出来具体的访问地址,是绝对的资源路径,
2:HTTP的session和cookie
会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话。常用的会话跟踪技术是Cookie与Session。Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端记录信息确定用户身份。
3:cookie
3.1 Cookie机制
在程序中,会话跟踪是很重要的事情。理论上,一个用户的所有请求操作都应该属于同一个会话,而另一个用户的所有请求操作则应该属于另一个会话,二者不能混淆。例如,用户A在超市购买的任何商品都应该放在A的购物车内,不论是用户A什么时间购买的,这都是属于同一个会话的,不能放入用户B或用户C的购物车内,这不属于同一个会话。
而Web应用程序是使用HTTP协议传输数据的。HTTP协议是无状态的协议。一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接。这就意味着服务器无法从连接上跟踪会话。即用户A购买了一件商品放入购物车内,当再次购买商品时服务器已经无法判断该购买行为是属于用户A的会话还是用户B的会话了。要跟踪该会话,必须引入一种机制。
Cookie就是这样的一种机制。它可以弥补HTTP协议无状态的不足。在Session出现之前,基本上所有的网站都采用Cookie来跟踪会话。
3.2 什么是Cookie
Cookie意为“甜饼”,是由W3C组织提出,最早由Netscape社区发展的一种机制。目前Cookie已经成为标准,所有的主流浏览器如IE、Netscape、Firefox、Opera等都支持Cookie。
由于HTTP是一种无状态的协议,服务器单从网络连接上无从知道客户身份。怎么办呢?就给客户端们颁发一个通行证吧,每人一个,无论谁访问都必须携带自己通行证。这样服务器就能从通行证上确认客户身份了。这就是Cookie的工作原理。
Cookie实际上是一小段的文本信息。客户端请求服务器,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户状态。服务器还可以根据需要修改Cookie的内容。根据Cookie规范,浏览器访问Google只会携带Google的Cookie,而不会携带Baidu的Cookie。Google也只能操作Google的Cookie,而不能操作Baidu的Cookie。Cookie具有不可跨域名性。
3.3Cookie属性
查看cookie源码,cookie类里边有如下属性,和含有name和value的构造方法,由此我们可知创建cookie传入name和value的构造方法即可:
Cookie cookie=new Cookie("cookie名字", "cookie值");
属 性 名 | 描 述 |
String name | 该Cookie的名称。Cookie一旦创建,名称便不可更改 |
Object value | 该Cookie的值。如果值为Unicode字符,需要为字符编码。如果值为二进制数据,则需要使用BASE64编码 |
int maxAge | 该Cookie失效的时间,单位秒。如果为正数,则该Cookie在maxAge秒之后失效。如果为负数,该Cookie为临时Cookie, 关闭浏览器即失效,浏览器也不会以任何形式保存该Cookie。 如果为0,表示删除该Cookie。默认为–1 |
boolean secure | 该Cookie是否仅被使用安全协议传输。安全协议。安全协议有HTTPS,SSL等,在网络上传输数据之前先将数据加密。默认为false |
String path | 该Cookie的使用路径。如果设置为“/sessionWeb/”,则只有contextPath为“/sessionWeb”的程序可以访问该Cookie。 如果设置为“/”,则本域名下contextPath都可以访问该Cookie。注意最后一个字符必须为“/” |
String domain | 可以访问该Cookie的域名。如果设置为“.google.com”,则所有以“google.com”结尾的域名都可以访问该Cookie。注意第一个字符必须为“.” |
String comment | 该Cookie的用处说明。浏览器显示Cookie信息的时候显示该说明 |
int version | 该Cookie使用的版本号。0表示遵循Netscape的Cookie规范,1表示遵循W3C的RFC 2109规范 |
4:SESSION
4.1session机制
除了使用Cookie,Web应用程序中还经常使用Session来记录客户端状态。Session是服务器端使用的一种记录客户端状态的机制,使用上比Cookie简单一些,相应的也增加了服务器的存储压力。
4.2什么是session
Session是另一种记录客户状态的机制,不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是Session。客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。
如果说Cookie机制是通过检查客户身上的“通行证”来确定客户身份的话,那么Session机制就是通过检查服务器上的“客户明细表”来确认客户身份。Session相当于程序在服务器上建立的一份客户档案,客户来访的时候只需要查询客户档案表就可以了。Session对象是在客户端第一次请求服务器的时候创建的。
4.3session属性
HttpSession session = request.getSession(); // 获取Session对象
方 法 名 | 描 述 |
void setAttribute(String attribute, Object value) | 设置Session属性。value参数可以为任何Java Object。通常为Java Bean。value信息不宜过大 |
String getAttribute(String attribute) | 返回Session属性 |
Enumeration getAttributeNames() | 返回Session中存在的属性名 |
void removeAttribute(String attribute) | 移除Session属性 |
String getId() | 返回Session的ID。该ID由服务器自动创建,不会重复 |
long getCreationTime() | 返回Session的创建日期。返回类型为long,常被转化为Date类型,例如:Date createTime = new Date(session.get CreationTime()) |
long getLastAccessedTime() | 返回Session的最后活跃时间。返回类型为long |
int getMaxInactiveInterval() | 返回Session的超时时间。单位为秒。超过该时间没有访问,服务器认为该Session失效 |
void setMaxInactiveInterval(int second) | 设置Session的超时时间。单位为秒 |
void putValue(String attribute, Object value) | 不推荐的方法。已经被setAttribute(String attribute, Object Value)替代 |
Object getValue(String attribute) | 不被推荐的方法。已经被getAttribute(String attr)替代 |
boolean isNew() | 返回该Session是否是新创建的 |
void invalidate() | 使该Session失效 |
5:通过实际代码实现cookie和session
5.1需求描述
1:我们通过用户登录之后在服务器保存用户账户密码到session里边,设置有效时间5分钟。并且把登录账户密码存储的cookie里边设置有效时间5分钟,返回给浏览器。
2:然后关闭浏览器,只要在5分钟之内再次登录,浏览器就会携带本地的cookie(里边包含账户密码信息)到服务器找到session(session里边也含有用户的账户密码)。对比验证,实现下一次免登陆。
实现搭建好了SSM框架以备使用。
5.2代码实现
登录表单是一个简单的from
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<form action="httpService/login">
账户:<input name="name" id="name" type="text"><br>
密码<input name="password" id="password" type="password" class="">
<input type="submit" value="登陆" />
</form>
</body>
</html>
请求到后要的controller:在这个controller里边保存用户账户密码到session里边,设置有效时间5分钟。并且把登录账户密码存储的cookie里边设置有效时间5分钟,返回给浏览器。
@Controller
@RequestMapping("httpService")
public class HttpService {
@RequestMapping(value="/login",method=RequestMethod.GET,produces = "application/json; charset=utf-8")
@ResponseBody
public String login(HttpServletRequest request,HttpServletResponse response) throws UnsupportedEncodingException {
String name=request.getParameter("name");
String password=request.getParameter("password");
if(name==null&&"".equals(name)) {
return "用户名不能为空!";
}
if(password==null&&"".equals(password)) {
return "密码不能为空!";
}
//第一步:将用户名和密码放到session里边
HttpSession session=request.getSession();
System.out.println("登陆的sessionID:"+session.getId());
session.setAttribute("username", name);
session.setAttribute("password",password);
session.setMaxInactiveInterval(10*60);
//第二步:将用户名和密码放到cookie里边
Cookie cookie1=new Cookie("Cname", name);
cookie1.setPath("/");//根路径
cookie1.setMaxAge(5*60);//5分钟
cookie1.setSecure(false);//http可用 true是https专用
response.addCookie(cookie1);
Cookie cookie2=new Cookie(URLEncoder.encode("Cpwd", "UTF-8"), password);
cookie2.setPath("/");//根路径
cookie2.setMaxAge(5*60);//5分钟
response.addCookie(cookie2);
Cookie cookie3=new Cookie(URLEncoder.encode("JSESSIONID", "UTF-8"), session.getId());
cookie3.setPath("/");//根路径
cookie3.setMaxAge(5*60);//5分钟
response.addCookie(cookie3);
return "登陆成功:(姓名是:"+name+",密码是:"+password+")";
}
然后登录成功的效果如下:
然后到查询页面去:
<!DOCTYPE html>
<html>
<head>
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script type="text/javascript" src="https://cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.js"></script>
</head>
<body>
<input id="submit" type="submit" value="select" />
<p id="p1">返回结果</p>
<script type='text/javascript' src='./resources/js/shop/cookie.js' charset='utf-8'></script>
</body>
</html>
查询页面导入的cookie.js如下:
$(document).ready(function() {
getShopInfo();
function getShopInfo() {
alert("加载cookies");
var a = $.cookie("JSESSIONID");
alert("JSESSIONID:" + a);
var b = $.cookie("Cname");
alert("姓名:" + b);
};
$("#submit").click(function() {
alert("跳转方法1:");
var a = $.cookie("JSESSIONID");
var selectUTL = "/o2odemo/httpService/select;JSESSIONID=" + a;
if (a != null) {
$.ajax({
url : selectUTL,
type : 'POST',
dataType : "html",
success : function(data, textStatus) {
if (data.success) {
alert("返回值1:" + data);
$("#p1").html(data);
alert("返回值1:" + textStatus);
} else {
$("#p1").html(data);
alert("返回值2:" + data);
alert("返回值2:" + textStatus);
}
}
});
} else {
alert("jessionid为空,请登录!");
}
});
});
查询后台controller:在验证cookie里边的账户密码是否跟session里边的一样,一样免登陆。否则需要登录
@RequestMapping(value="/select",produces = "application/json; charset=utf-8")
@ResponseBody
public String select(HttpServletRequest request,HttpServletResponse response) {
Cookie[] cookies=request.getCookies();
//第一部:判断session里边是否有账户信息
HttpSession session= request.getSession();
System.out.println("查询的sessionID:"+session.getId());
String sname=(String) session.getAttribute("username");
String spassword=(String) session.getAttribute("password");
//第三部:检查页面传递过来的cookie.得到账户密码。
String ZH=null;
String MM=null;
if(cookies!=null) {
for (Cookie cookie : cookies) {
System.out.println("----------------------------------------");
String n=cookie.getName();
String v=cookie.getValue();
System.out.println("cookie的键:"+n);
System.out.println("cookie的值:"+v);
if("Cname".equals(n)) {
ZH=v;
}
if("Cpwd".equals(n)) {
MM=v;
}
}
if(ZH!=null&&MM!=null) {
//第三部:对比cookie的账户是否和session里面的对照
if(ZH.equals(sname)&&MM.equals(spassword)) {
return "session账户信息跟cookie相等,支持免登陆查询!";
}else {
return "无法查询,请先登陆,谢谢!";
}
}else {
return "cookies账户密码为空,无法查询,请先登陆,谢谢!";
}
}else {
return "cookies为空,无法查询,请先登陆,谢谢!";
}
}
通过验证,登陆之后,只要在5分钟之内,无论是否关闭浏览器,都能通过查询页面访问数据,过了5分钟,就不能登陆了
5分钟之后 查询cookie消失。
6:对比总结
1 .存取方式的不同
Cookie中只能保管ASCII字符串,假如需求存取Unicode字符或者二进制数据,需求先进行编码。Cookie中也不能直接存取Java对象。若要存储略微复杂的信息,运用Cookie是比拟艰难的。
而Session中能够存取任何类型的数据,包括而不限于String、Integer、List、Map等。Session中也能够直接保管Java Bean乃至任何Java类,对象等,运用起来十分便当。能够把Session看做是一个Java容器类。
2 .隐私策略的不同(一个安全一个不安全)
Cookie存储在客户端阅读器中,对客户端是可见的,客户端的一些程序可能会窥探、复制以至修正Cookie中的内容。而Session存储在服务器上,对客户端是透明的,不存在敏感信息泄露的风险。
假如选用Cookie,比较好的方法是,敏感的信息如账号密码等尽量不要写到Cookie中。最好是像Google、Baidu那样将Cookie信息加密,提交到服务器后再进行解密,保证Cookie中的信息只要本人能读得懂。而假如选择Session就省事多了,反正是放在服务器上,Session里任何隐私都能够有效的保护。
3.有效期上的不同(Tomcat默认30分钟过期)
使用过Google的人都晓得,假如登录过Google,则Google的登录信息长期有效。用户不用每次访问都重新登录,Google会持久地记载该用户的登录信息。要到达这种效果,运用Cookie会是比较好的选择。只需要设置Cookie的过期时间属性为一个很大很大的数字。
由于Session依赖于名为JSESSIONID的Cookie,而Cookie JSESSIONID的过期时间默许为–1,只需关闭了阅读器该Session就会失效,因而Session不能完成信息永世有效的效果。运用URL地址重写也不能完成。而且假如设置Session的超时时间过长,服务器累计的Session就会越多,越容易招致内存溢出。
4.服务器压力的不同(session在大的并发情况下,占内存很多,很耗资源)
Session是保管在服务器端的,每个用户都会产生一个Session。假如并发访问的用户十分多,会产生十分多的Session,耗费大量的内存。因而像Google、Baidu、Sina这样并发访问量极高的网站,是不太可能运用Session来追踪客户会话的。
而Cookie保管在客户端,不占用服务器资源。假如并发阅读的用户十分多,Cookie是很好的选择。关于Google、Baidu、Sina来说,Cookie或许是唯一的选择。
5 .浏览器支持的不同(浏览器器禁用cookie需要session重写)
格式是 "/o2odemo/httpService/select;JSESSIONID= "+ session的id
Cookie是需要客户端浏览器支持的。假如客户端禁用了Cookie,或者不支持Cookie,则会话跟踪会失效。关于WAP上的应用,常规的Cookie就派不上用场了。
假如客户端浏览器不支持Cookie,需要运用Session以及URL地址重写。需要注意的是一切的用到Session程序的URL都要进行URL地址重写,否则Session会话跟踪还会失效。关于WAP应用来说,Session+URL地址重写或许是它唯一的选择。
假如客户端支持Cookie,则Cookie既能够设为本浏览器窗口以及子窗口内有效(把过期时间设为–1),也能够设为一切阅读器窗口内有效(把过期时间设为某个大于0的整数)。但Session只能在本阅读器窗口以及其子窗口内有效。假如两个浏览器窗口互不相干,它们将运用两个不同的Session。(IE8下不同窗口Session相干)
6.跨域支持上的不同(二级域名需要设置公共域)
Cookie支持跨域名访问,例如将domain属性设置为“.biaodianfu.com”,则以“.biaodianfu.com”为后缀的一切域名均能够访问该Cookie。跨域名Cookie如今被普遍用在网络中,例如Google、Baidu、Sina等。而Session则不会支持跨域名访问。Session仅在他所在的域名内有效。
仅运用Cookie或者仅运用Session可能完成不了理想的效果。这时应该尝试一下同时运用Cookie与Session。Cookie与Session的搭配运用在实践项目中会完成很多意想不到的效果。
关系的理解
客户第一次发送请求给服务器,此时服务器产生一个唯一的sessionID,并返回给客户端(通过cookie),保存于客户端的内存中,并与一个浏览器窗口对应着,由于HTTP协议的特性,这一次连接就断开了
以后此客户端再发送请求给服务器的时候,就会在请求request中携带cookie,由于cookie中有sessionID,所以服务器就知道这是刚才那个客户端。