文章目录
引入:http是一个无状态协议?怎么解决呢?
无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。HTTP无状态的特性严重阻碍了这些应用程序的实现,毕竟交互是需要承前启后的,简单的购物车程序也要知道用户到底在之前选择了什么商品。于是,两种用于保持HTTP连接状态的技术就应运而生了,一个是 Cookie,而另一个则是 Session。
一、Cookie和Session
cookie中可以用来保存服务端返回的一些用户信息的,每一次的请求,都会携带这些cookie。服务端从请求头中取到cookie中的信息,就可以识别本次请求的来源,http就变成有状态的了。
由于采用服务器端保持状态的方案在客户端也需要保存一个标识,所以session机制可能需要借助于cookie机制来达到保存标识的目的。cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑到安全应当使session, session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie
1.1 cookie 注意事项:
1、cookie存放在客户端(浏览器端),所以是不安全的,人为可以清除。cookie 是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。
2、cookie有过期时间设定。如果不设置过期时间,说明这个cookie就是当前浏览器的会话时间,浏览器关了,cookie就不存在了。如果有过期时间,cookie就会存储到硬盘上,浏览器关闭不影响cookie。下次打开浏览器,cookie还存在
3、cookie可以被用户禁止
4、cookie有大小的限制,一个浏览器能创建的 Cookie 数量最多为 300 个,并且每个不能超过 4KB,每个 Web 站点能设置的 Cookie 总数不能超过 20 个。
5、cookie 是不可跨域的: 每个 cookie 都会绑定单一的域名,无法在别的域名下获取使用,一级域名和二级域名之间是允许共享使用的(靠的是 domain)。
1.2 cookie 重要的属性
属性名
描述
String name
该Cookie的名称。Cookie一旦创建,名称便不可更改 ,必须是字符串类型
Object value
该Cookie的值。如果值为Unicode字符,需要为字符编码。如果值为二进制数据,则需要使用BASE64编码
int maxAge
该Cookie失效的时间,单位秒。如果为正数,则该Cookie在maxAge秒之后失效。如果为负数,该Cookie为临时Cookie,关闭浏览器即失效,浏览器也不会以任何形式保存该Cookie。如果为0,表示删除该Cookie。默认为–1。比expires好用
int expires
设置Cookie过期时间,在设置的某一个时间后该cookie就会失效。
boolean secure
该Cookie是否仅被使用安全协议传输。安全协议。安全协议有HTTPS,SSL等,在网络上传输数据之前先将数据加密。默认为false。**当secure值为true时,**cookie在HTTP中是无效的,在HTTPS中才有效
String path
该Cookie的使用路径。如果设置为“/love/”,则只有contextPath为“/love”的程序可以访问该Cookie。如果设置为“/”,则本域名下contextPath都可以访问该Cookie。注意最后一个字符必须为“/”
String domain
决定该cookie作用在哪个域。默认是当前域名
int version
该Cookie使用的版本号。0表示遵循Netscape的Cookie规范,1表示遵循W3C的RFC 2109规范
HttpOnly
该cookie不能通过js读取,但还是能通过Application中手动修改cookie,所以只是在一定程度上防止XSS攻击,并不是绝对的安全
1.3 session 注意事项:
1、session是将用户信息储存在服务器上面,如果访问服务器的用户越来越多,那么服务器上面的session也越来越多, session会对服务器造成压力,影响服务器的负载.如果Session内容过于复杂,当大量客户访问服务器时还可能会导致内存溢出。
2、用户信息丢失, 或者说用户访问的不是这台服务器的情况下,就会出现数据库丢失。这就是它的弊端。现在有一些技术,例如session共享、iphash、session持久等也可以解决上述问题。
3、当Cookie被禁止,Session也被禁止。cookie只是实现session的其中一种方案。虽然是最常用的,但并不是唯一的方法。禁用cookie后还有其他方法存储,比如放在url中。
4、session 是基于 cookie 实现的,session 存储在服务器端,sessionId 会被存储到客户端的cookie 中
根据以上流程我们可以看出,SessionID 是连接 Cookie 和 Session 的一道桥梁,大部分系统也是根据此原理来验证用户登录状态。但这种模式最大的问题是,没有分布式架构,无法支持横向扩展。如果使用一个服务器,该模式完全没有问题。但是,如果它是服务器群集或面向服务的跨域体系结构的话,则需要一个统一的session数据库库来保存会话数据实现共享,这样负载均衡下的每个服务器才可以正确的验证用户身份。
解决这个问题我们可以使用token,具体看下面对token的讲解
1.4 Cookie 和 Session 的区别:
根据上面的解释,我们在来最终总结一下它们大体的区别:
安全性: Session 比 Cookie 安全,Session 是存储在服务器端的,Cookie 是存储在客户端的。
存取值的类型不同:Cookie 只支持存字符串数据,Session 可以存任意数据类型。
有效期不同: Cookie 可设置为长时间保持,比如我们经常使用的记住我(默认登录)等功能,Session 一般失效时间较短,客户端关闭(默认情况下)或者 Session 超时都会失效。
存储大小不同: 单个 Cookie 保存的数据不能超过 4K,Session 可存储数据远高于 Cookie,但是当访问量过多,会占用过多的服务器资源。
注意点:
现在大多都是Session + Cookie,但是只用session不用cookie,或是只用cookie,不用session在理论上都可以保持会话状态。可是实际中因为多种原因,一般不会单独使用,如果只用cookie不用session,那么账户信息全部保存在客户端,一旦被劫持,全部信息都会泄露。并且客户端数据量变大,网络传输的数据量也会变大。
用session只需要在客户端保存一个id,实际上大量数据都是保存在服务端。如果全部用cookie,数据量大的时候客户端是没有那么多空间的
简而言之, session 就像用户信息表, 里面包含了用户的信息(姓名、状态等等). 而 cookie 就是用户通行证
二、token(令牌)
Token顾名思义就是令牌、凭证、钥匙,只有这把钥匙,你才能打开门。Token一般都是服务端生成,比如一个web系统,用户登录的时候,服务端校验用户名密码通过以后,会生成一个token,然后将token返回给客户端,客户端会将token保存下来(放到 HTTP 的 Header 里), 后续所有的请求都会携带这个token。服务端会判断当前token是否存在已经是否过期。如果token不存在或者过期就会拒绝本次请求。
简单 token 的组成: uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,token 的前几位以哈希算法压缩成的一定长度的十六进制字符串)
2.1 token优势
1. Token 完全由应用管理,所以它可以避开同源策略
2. 安全性。Token 可以避免 CSRF攻击(因为不需要 cookie 了)
CSRF攻击(跨站请求伪造):攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账…造成的问题包括:个人隐私泄露以及财产安全。(CSRF攻击具体是什么大家如果想要了解可以评论区讨论哦)
3.无状态、可扩展,可以在多个服务间共享
4.多平台跨域:CORS(跨域资源共享)对应用程序和服务进行扩展的时候,需要介入各种各种的设备和应用程序。只要用户有一个通过了验证的token,数据和资源就能够在任何域上被请求到。
2.2 token 的身份验证流程
三、基于JWT实现的Token认证方案
创建token的时候,我们可以设定一些选项。但是标准的用法会在JSON Web Tokens简称JWT体现。
JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案。
3.1 JWT组成部分
JSON Web Tokens令牌以紧凑的形式由三部分组成,这些部分由点 (. )分隔,分别是:
Header:标头
Payload: 有效载荷
Signature: 签名
该对象为一个很长的字符串,字符之间通过"."分隔符分为三个子串。
每一个子串表示了一个功能块,总共有以下三个部分:JWT头、有效载荷和签名
3.1.1 Header:标头
标头通常由两部分组成:令牌的类型(即JWT)和所使用的签名算法,例如HMAC SHA256或RSA。
例如:
此JSON被Base64Url编码以形成JWT的第一部分。
{
"alg": "HS256",表示签名使用的算法,默认为HMAC SHA256(写为HS256)
"typ": "JWT"表示令牌的类型,JWT令牌统一写为JWT
}
3.1.2 Payload:有效载荷
有效载荷部分,是JWT的主体内容部分,也是一个JSON对象,包含需要传递的数据。 JWT指定七个默认
字段供选择。
iss:发行人
exp:到期时间
sub:主题
aud:用户
nbf:在此之前不可用
Iat:发布时间
jti:JWT ID用于标识该JWT
除以上默认字段外,我们还可以自定义私有字段,有效负载示例可以是:
{
"sub": "9876543210",
"name": "Mr Fen",
"admin": true
请注意,默认情况下JWT是未加密的,任何人都可以解读其内容,因此不要构建隐私信息字段,存放保密信息,以防止信息泄露。
}
3.1.3 Payload:签名
要创建签名部分,您必须获取编码的头、编码的负载、密钥、头中指定的算法,并对其进行签名。
例如,如果要使用HMAC SHA256算法,则将通过以下方式创建签名:
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(claims), secret)
3.2 什么时候应该使用 JWT?
1、身份验证,这是使用JWT的最常见方案。一旦用户登录,每个后续请求将包括JWT,从而允许用户访问该令牌允许的路由,服务和资源。单一登录是当今广泛使用JWT的一项功能,因为它的开销很小并且可以在不同的域中轻松使用。
2、信息交换,JWT令牌是在各方之间安全地传输信息的一种好方法。因为可以对JWT进行签名(例如,使用公钥/私钥对),所以您可以确定发件人是本人。另外,由于签名是使用标头和有效负载计算的,因此您还可以验证内容是否未被篡改。
3.3 JWT和Token有什么关系?
token是按照一定规则生成的字符串,包含用户信息。
一般我们会采用标准的用法JWT。
JWT就是给我们规定好了规则,使用JWT可以生成字符串,包含用户信息。