cookie
Web Application一般使用HTTP协议作为信息传输协议,但是HTTP协议是无状态的,也就是说一次HTTP成功断开后(HTTP协议为一次请求一次响应),这个时候如果客户端再次发送请求,服务端则不能辨识这个客户端为上次刚刚发起请求过的客户端,这就说明HTTP协议不能支持会话跟踪,这个时候cookie的出现,实现了HTTP的会话跟踪。
简单地来说,cookie就是服务端发放给客户端的一账通行证,并且通过这张通行证(cookie)来进行身份的辨识。本质上cookie是一小段文本信息,包含有如user_session/logged_in等可以标识用户以及可以表示用户的状态的一些字段
可以看到在登陆之后存在的比较关键的两个字段logged_in(状态显示yes已登录)user_session是一串会话的标识,这两个字段基本就能在标识一个用户的同时还能标识这个用户的状态
可以看到标识的logged_in字段的值已经变成no,表示当前没有用户登录github并且也没有了user_session这个字段,因为也没有必要为一个没有登录的用户分发一个辨识会话的session
我们可以借助浏览器的调试功能查看到浏览器存储至本地的一些cookie,需要注意这两个字段,一个是Domain另一个是path,通常我们在做单点登陆SSO的时候可能会在后端向指定的Domain和Path种特定的Cookie去实现一些特殊的功能,这里有一些要点就是
- 比如一个cookie种在某个一级域名下,如.jianshu.com那么,访问简书的子域名则会自动携带这个cookie访问,反之则不行
- 再比如,一个cookie种在了.jianshu.com下,但是指定了path为/login,这个时候只有访问.jianshu.com/login才会自动携带上这个cookie
- 换言之cookie的domain和path属性同样会影响在指定域和path路径下能否拿到cookie
domain规则
- 设置cookie——设置cookie的时候,domain要符合域名的规则,比如可以设置成www1.pclady.com.cn和pclady.com.cn 但是不能设置成pclady。要有.com.cn或者其他域名做结尾。 通过js手动设置cookie的domain都是以.开头的。比如设置domain=pclady.com.cn,实际的domain名为.pclady.com.cn;删除cookie时加不加.都可以。
- 获取cookie——js只能获取domian大于等于当前页面域名的cookie。比如http://www1.pclady.com.cn/zt/20160623/testCookie.html页面中的js能获取domain为“www1.pclady.com.cn”和“.www1.pclady.com.cn”和“.pclady.com.cn”但是获取不到“g.pclady.com.cn”中的cookie;
- 删除cookie——要删除一个cookie,domain值必须跟要删除cookie的domain相同,默认的domain为html文件的domain。
- 跨域domain——js不可以把cookie设置成不同与html域名的domian。cookie设置不会成功,但不会影响后面程序对cookie的操作。
- 错误——如果domain设置错误,该cookie将不会被创建,并且后续对cookie的操作不论正确与否都会被浏览器禁止。
path规则
- 设置cookie——js设置path要以"/"开头,比如html路径为"/zt/20160623/",路径可以设置成"/"或"/zt"。
- 获取cookie——使用js只能获取path大于等于当前页面path的cookie,比如html路径为/zt/20160623/,使用js只能获取“/zt/20160623/”和“/zt”和“/”路径下的cookie。不能获取其他路径下的cookie
- 删除cookie——删除cookie的时候路径也必须相同,默认的路径是html的path路径。
- 错误——如果path不是以"/"开头的则创建cookie的path使用默认的path;如果是以"/"开头但是设置错了,路径名不存在或者直接设置成子路径。比如设置成"/20160623"或者"/zt1",该cookie将不会被创建,并且后续对cookie的操作不论正确与否都会被浏览器禁止。
session
基于 session 的用户认证借助于请求体对象 req 中的 session 数据来完成.
//基于WebServlet3.0的获取session的方式
//这种方式获取session如果本次会话存在,则返回本次会话session
//如果不存在则创建一个新的session
HttpSession session = request.getSession();
session在访问tomcat服务器HttpServletRequest的getSession(true)的时候创建,tomcat的ManagerBase类提供创建sessionid的方法:随机数+时间+jvmid。
当客户端请求服务端经过身份验证之后,服务端会生成并且保存身份信息相关的session数据,并且将对应sessionid写入cookie,通过响应传输给客户端,客户端将cookie保存在本地,以便第二次或以后的请求能够带上cookie中的sessionid去让服务端辨识该用户是属于哪个会话的(tomcat生成的sessionid叫做jsessionid),并且也会验证cookie字段中的logged_in字段,判断这个字段是因为,如果该用户是经过验证的,则这个字段的值肯定为(yes,true,1)这时,就无需重新认证身份,否则,需要重新进入身份认证流程。
session缺点
- tomcat的StandardManager类将session存储在内存中,也可以持久化到file,数据库,memcache,redis等。客户端只保存sessionid到cookie中,而不会保存session,session销毁只能通过invalidate或超时,关掉浏览器并不会关闭session。
token
token也称作令牌,由uid+time+sign[+固定参数]组成:
- uid: 用户唯一身份标识
- time: 当前时间的时间戳
- sign: 签名, 使用 hash/encrypt 压缩成定长的十六进制字符串,以防止第三方恶意拼接
- 固定参数(可选): 将一些常用的固定参数加入到 token 中是为了避免重复查库
以下几点特性会让你在程序中使用基于Token的身份验证
- 无状态、可扩展
- 支持移动设备
- 跨程序调用
- 安全
由其组成可以看出, token 的认证方式类似于临时的证书签名, 并且是一种服务端无状态的认证方式, 非常适合于 REST API 的场景. 所谓无状态就是服务端并不会保存身份认证相关的数据,
token 只被保存在客户端 中的cookie 或 localstorage(数据库).
因为用户的状态在服务端的内存中是不存储的,所以这是一种无状态的认证机制。
token的认证流程
- 用户登录校验,校验成功后就返回Token给客户端。
- 客户端收到数据后保存在客户端
- 客户端每次访问API是携带Token到服务器端。
- 服务器端采用filter过滤器校验。校验成功则返回请求数据,校验失败则返回错误码
缺点:
因为 token 一般都是 hash/encrypt 的字符串, 所以会额外附加 加密/解密 的性能开销
有些加密方式同样存在安全隐患
推荐一篇讲解JWT优缺点的帖子 //www.greatytc.com/p/af8360b83a9f