发布于2021-03-10 18:38 阅读(1269) 评论(0) 点赞(20) 收藏(5)
http协议是无状态协议,服务端不能从请求中判断用户的身份,用户怎么每次去找到自己对应的信息呢?
1. cookie
这种方式最简单,在用户第一次登陆成功某个网站A,网站A服务端就将你的用户信息(比如用户名,用户id,证件号等等)写入到cookie 对象中,然后再把这个cookie对象发送给对应的客户端,客户端就存下这个cookie,例如博客园的cookie如下
当cookie超时时间到了浏览器就会自动删除这个cookie,这个时候需要你重新登录一下, 然后服务器就会根据你的用户名和密码去数据库中查询一次,成功查询到就再一次将用户信息丢到cookie对象中,返回给客户端存起来,后续每次请求都带着这个cookie
这种方式的好处就是:用户的所有信息都存在客户端,服务端只有在数据库中存了一份,服务端压力很小;
坏处是显而易见,每次都要带上这个cookie这么多信息,一方面是传输效率问题,另一方面是安全问题,别人只要截获你的cookie,你的所有信息都一览无余;
还有一点就是有的客户端会禁用cookie...
2. session
在cookie的基础上优化了一下,因为不是有安全和效率问题吗,那么我们就把用户所有的信息都存到服务端,例如现在有这样的一个结构:Map<sessionId,Session<User>>
用户第一次登陆成功,就会生成一个唯一字符串sessionId,然后将sessionId和用户信息存到map中,最后就将这个sessionId丢到cookie返回给客户端,后续的客户端访问服务端只需要带着cookie,服务端就能从cookie中获取到这个sessionId,到Map里面去找,就可以找到用户信息了;
注意,不一定非要叫做sessionId这个名字啊,叫做aId,bId等等也行....看每个地方的要求
这种方式比较安全,而且效率也提高了,因为只需要多传一个字符串,但是服务端内存中存所有的用户信息,压力都给到了服务端
我们还从请求方式来比较cookie和session:
cookie的方式一般只能用户post请求,因为get请求的url有长度限制
session的方式只是get和post方式,get方式的话在url后面添加一个参数传sessionId就行了,即使客户端禁用了cookie,在服务端将sessionId传给了客户端之后,客户端想办法存起来下次请求的时候带过去就行了
3. session共享
上面说的是单体应用的实现方式,但是到了分布式环境下就会失效(很多东西在单机中使用是可以的,分布式环境下就没用了,比如数据库事务,锁),下图所示,会导致tomcat2需要用户重新登录
解决方案有两种:
1)hash一致性:在nginx中配置ip_hash,其实就是用过一定的算法对用户的ip处理,假如用户第一次访问的是tomcat1,那么只要用户ip不会变化,第二次该用户访问的还是tomcat1
2)引入中间件:这里以redis为例
4. jwt
上面的实现方式看着一大堆东西也是麻烦,又是传sessionId,又是引入redis,在分布式环境下有没有简单的方式啊!
jwt全称JSON Web Token,我们之前每次都是传的sessionId,这个字符串是没有实际意义的,只是起到了一个唯一标识的作用,那么有没有可能我们把它的语义化呢?就是想办法直接解析这个字符串,然后可以获取用户信息
下图所示,结构是不是一下子简单多了,可以看到只要我们每次请求都带上这个token,不管是单机环境,还是分布式环境都适用,而且服务端也不需要保存什么东西,客户端只需要保存一个token字符串就行了;
现在就比较关心的是jwt的那个算法和生成后的token字符串有什么特殊的要求!
token字符串的格式,分为三部分,用点进行连接:aaa.bbb.ccc
示例:
第一部分是Header:放入token的类型(“JWT”)和算法名称(比如:HMAC SHA256或者RSA等等),然后使用Base64对这个JSON编码就得到JWT的第一部分
第二部分是Payload:一般放入用户的不敏感信息,比如用户id,名称和角色等,即使被别人截获了也没啥用,然后使用Base64对这个JSON编码就得到JWT的第二部分
第三部分是Signature:准备一个只有你自己知道的密钥,加上第一部分的字符串aaa和第二部分的字符串,通过Header中声明的算法就生成了签名,也就得到了第三部分
将上面三部分通过点相连就组成了token,然后发到客户端,客户端只需要每次在请求头中放入这个token,后端通过密钥验证这个token的合法性,并且从Payload中获取用户不敏感的信息,进行后续处理
想看看简单的demo,可以看看这个老哥的博客 ,不过一般校验jwt是配置一个拦截器进行处理的
5. jwt的补充
其实仔细想了想,一般还有以下两个疑问
1)Token被盗了怎么办?
答: 在启用https的情况下,token被放在Header中还是比较安全的。另外Token的有效期不要设置过长。例如可以设置为1小时(微信公众号的网页开发的Token有效期为2小时)。
2)Token到期了如何处理?
答:理论上Token过期应该是跳到登录界面,但这样太不友好了。可以在后台根据Token的过期时间定期去请求新的Token。
可以看看以下两篇博客看看
原文链接:https://www.cnblogs.com/wyq1995/p/14421382.html
作者:哦哦好吧
链接:http://www.javaheidong.com/blog/article/112439/2ebe2b28455c07410b95/
来源:java黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 java黑洞网 All Rights Reserved 版权所有,并保留所有权利。京ICP备18063182号-2
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!