zoukankan      html  css  js  c++  java
  • jwt身份验证

      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。

    可以看看以下两篇博客看看

    应用JWT进行用户认证及Token的刷新

    JWT生成token及过期处理方案

     

    --------------以上皆原创,给未来的自己留下一点学习的痕迹!--------
  • 相关阅读:
    LeetCode:387字符串中唯一出现一一次的字符
    LeetCode-79. 单词搜索
    LeetCode-75. 颜色分类
    LeetCode-121. 买卖股票的最佳时机
    LeetCode-58. 最后一个单词的长度
    LeetCode-1103. 分糖果 II
    LeetCode:283. 移动零
    LeetCode:38. 外观数列
    LeetCode:70. 爬楼梯
    获取美拍视频的链接--JS分析
  • 原文地址:https://www.cnblogs.com/wyq1995/p/14421382.html
Copyright © 2011-2022 走看看