session和token鉴权方式

1.什么是token

在接口的响应结果中,经常会出现类似这样的返回值

{
    'msg':'success',
    'token':'eyJzsKIKLJdkjgias436ajsdlgjalsjfowe'
}

往往需要在访问下一个接口时传递token数据

cur -x  POST -H Authorization:eyJzsKIKLJdkjgias436ajsdlgjalsjfowe
<http://127.0.0.1:500/user>
{'alg':'HS256','typ':'JWT'}

所以token本质上就是用户信息通过编码转化成另一种形态得到token,再通过token解码得到用户数据

 转换方式会有很多种,可能不是这种base64url

2.无状态 

 要理解token的由来,先得从HTTP协议讲起。HTTP协议是一种无状态的协议,服务器没有记忆能力,无法记住客户端之前有没有发送过请求,因此客户端每次发送的请求都是独立的

这会造成一个问题,当客户必须要登录才能进行的操作,每次请求都要重复发送用户名和密码给服务器进行核验,频繁发送敏感信息会造成很大的安全问题

 比如我们要访问user接口(用户相关信息),访问完后再请求第二个接口rechage(充钱)或第三个接口(取钱)时,服务器已经失忆了,不会自动记住user接口访问过的的信息

我们要获得用户的相关信息,肯定需要传入该用户的用户名及密码,不然服务器是不知道返回谁的信息的,然后我们充钱,肯定要传入要充多少钱,充到哪个账户里,所以要传入用户名及密码,最后,我们要取钱,肯定也要传入取的钱数,从哪个账户里取,所以啦还要传入用户名及密码

所以我们就能总结得出,这种方式会每次都需要传入用户名及密码,这样就会造成非常不安全

 总结:

无状态的问题:1.不安全 2.重复数据

 3.session

有没有一种方式让服务器记住客户端的(登录)状态呢?session就是一种好的方式,当用户登录时,发送用户名和密码之后,服务端会给客户端派生一个sessionId,表明这是属于哪一个用户,然后在sessionId中存储该用户数据,比如这个用户之前添加的购物车信息,这个用户的登录时间等等,这些信息会保存在服务器

接下来,服务器通过cookie的形式把sessionId返回给客户端。每次客户端请求该服务器时,会自动带上sessionId这个cookie。服务器接收到后查询有没有存储这个sessionId的信息

相当于进入某个产业园,保安大叔会把你的信息登记在一个小本子上,比如身份证号等,下次你就拿着这个号码来,保安大叔已核对,在小本子上有登录,你就可以进去了

总结:

-- 让服务器记住客户端

-- session 在服务器当中保存用户访问数据

-- session = 'username:momo,password:123456,21-10-18 16:08 ,购买手机'

sessionId sessionId = get_id(session) = '123'

session返回加密后的用户信息给sessionId

session_id 和session发生关联的一个简短的数据,一般来源是用户名或密码加密之后的结果

cookie 是客户端存储的用户相关数据(同一个域名),是从服务端返回(set-cookie)

session会带来几个问题:

第一:session需要占用很多服务器的资源(要买一个很厚的本子登记)。服务器针对每个用户都要创建一个session,然后在这个sessionId对应的存储空间中存储大量数据。用户每次请求后都需要查询有没有对应的sessionId,会影响服务器的响应速度,尤其设计到最大数据节点时,还需要同步

第二:每次都要查询,翻一个很厚的本子,速度很慢,当有太多请求时,很久才能收到响应(来一个人,保安大叔要翻看上千页的本子核对)

第三:session通常会和cookie搭配,但是cookie无法跨域。对于涉及到多个服务的跨域操作,有很大的局限性。同时,如果涉及到跨域或者多服务器,就需要共享session,必须保证每台服务器都能获取session而且要保持数据同步和一致性(人太多,设置多个保安亭,每个保安亭都要保持数据一致性,还要每天更新离职和新进来的员工)

我们可以采取数据库保存session,像redis这样的数据库就会比较适合存储session,但是新问题又来了。服务器每接收一次请求都需要查询数据库,当访问量太大时会线数据库带来非常大的压力,如果数据库挂了,那服务就直接无法使用了

解决方式是配置redis集群,当单点数据库挂掉时,可以使用其他数据库中的数据。集群要做好数据同步,保证每个节点的数据一致性,也要做好负载均衡,尽量不让节点因为负载挂掉。就算其中有节点挂掉了,也不影响服务执行

 4.token

虽然最终通过集群管理能解决session的问题,但是工程和成本还是相当高的

既然服务器处理用户状态这么麻烦,那为什么不放在客户端去存储呢?当用户登录以后,服务器根据用户ID或者用户名生成一个userId,然后获取用户数据,比如购物车数据,登录时间等,把这些数据放在userId盒子里,和之前的sessionId差不多,只是不在服务器存储了,而是直接丢给客户端

客户端每次都携带这个关于用户的盒子给服务器,盒子中带有用户的数据。服务器可以直接拿到用户的数据,并不需要再次查询服务器

相当于保安大叔不需要小本子了,而是直接发给你一个通行证

这种方式就是token方式,服务器并不存储用户数据,而是直接通过编码或者加密方式把用户数据作为令牌直接返回客户端,传递的方式由服务器端自己设置。每次客户端都携带这个令牌,证明自己的身份,从而得到自己的状态和数据

这样,服务器可以节省大量的存储资源,也不需要每次查询,加快了响应速度。而且传递的方式也是由双方协定,不管是不是跨域,都可以正常传递

 5.签名

这种token方式目前还有一个问题,很容易被伪造,任何人都可以宣称自己是某个用户,从而获取该用户的私密信息,必须要想办法证明这个token就是由信任的服务器颁发给客户端的

这个办法就是签名

当用户登录时,服务器提取用户名或者ID组装成Paylod,代表用户数据,然后用Header拼接Paylod组装成新的数据,通过HSA256这一类的加密算法得到签名,然后再拼接Header,Paylod和Sign得到签名

 Sign保证了token是由服务器签发的,因为只有服务器知道签名的密钥。接下来还是和之前一样,每次访问新的接口,只需要带上这个token就可以了

服务器获取Header和Paylod,使用服务端的密钥得到新的签名,和客户端传过来的Sign对比,如果一致,表示这是合法的token,如果不一致,就是伪造的

6.cookie vs session

session:

-- 存储在服务端

-- 需要专用服务端,内存,磁盘,数据库

--  需要频繁查询,从而拖慢请求的处理速度

-- 跨域麻烦

token:

-- 不存服务端,直接丢给客户端。客户端存在哪儿?cookie,indexdb,local,storage

-- 不需要消耗服务器存储资源

-- 速度很快

-- 跨域方便

token的缺点:不能立即注销,不能立即让token失效

如果强行废除token,就只能用小本本记一下

cookie:只是实现token和session的一种手段,cookie只是一个http请求头字段,格式cookie:value

猜你喜欢

转载自blog.csdn.net/weixin_40611700/article/details/120826721