HTTP---会话机制JWT( JSON Web Token)

3.会话机制JWT( JSON Web Token)会话机制(翻译:令牌)
3.1.JWT是一个非常轻巧的规范
3.2.这个规范允许我们使用JWT在用户和服务器之间传递安全可靠的信息
3.3.是服务端生成的一串字符串,作为客户端进行请求的一个标识,由三部分组成,它们之间用圆点(.)连接。
3.4.一个典型的JWT看起来是这个样子的:xxxxx.yyyyy.zzzzz

 1.头部(Header):用于描述关于该JWT的最基本的信息,两部分组成:token的类型(“JWT”)和算法名称(HMAC SHA256或者RSA)
   {
     "typ": "JWT",
     "alg": "HS256"
   }
   被表示成一个JSON对象,指明了签名算法是HS256算法,用Base64对这个JSON编码就得到JWT的第一部分
   编码后的字符串如下:eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
 2.载荷(Payload):包含声明(要求),是关于实体(通常是用户)和其他数据的声明
      声明有三种类型: registered, public 和 private
            Registered claims : 预定义的声明,它们不是强制的,但是推荐。比如:iss (issuer), exp (expiration time), sub (subject), aud (audience)等
            Public claims : 可以随意定义
            Private claims : 用于在同意使用它们的各方之间共享信息,并且不是注册的或公开的声明
     {
       "GivenName": "aaa", 
       "Surname": "bbb", 
       "Email": "[email protected]", 
      "Role": [ "Manager", "Project Administrator" ] 
      }
     对payload进行Base64编码就得到JWT的第二部分
     注:不要在JWT的payload或header中放置敏感信息,除非它们是加密的
3.签名(Signature):必须有编码过的header、编码过的payload、一个秘钥
     签名算法是header中指定的那个,然对它们签名即可!
     签名是用于验证消息在传递过程中有没有被更改,并且,对于使用私钥签名的token,它还可以验证JWT的发送方是否为它所称的发送方
    小知识:Base64是一种基于64个可打印字符来表示二进制数据的表示方法

3.5.token主要有两个作用:

1.防止表单重复提交(防止表单重复提交一般还是使用前后端都限制的方式):
          前端:(1)在前端点击提交之后,将按钮置为灰色,不可再次点击;
                (2) 客户端存储token,客户端存储在Cookie或者Form的隐藏域
          后端:(1)服务端存储在Session(单机系统中可以使用)或者其他缓存系统(分布式系统可以使用)中
  防止表单重复提交,后端主要的理念是:
            (1)后端代码生成一个token,返回给客户端,客户端储存token;
            (2)然后就将request(请求)中的token与(session)中的token进行比较;
            后端代码示例:
            public String add(HttpServletRequestrequest,HttpServletResponse response){
             //生成token
            token = JwtTokenUtil.createJWT(user, userAgent);
             //放入session中
            request.getSession().setAttribute("token",token.toString());
            //放入request作用域中传到前台
            request.setAttribute("token",token);
            return "add";}
             //获取session中的token
            token = request.getSession().getAttribute("token");
            //获取前台穿过来的token
            String token=request.getParameter("token");
             if(token1==null){
            System.out.println("提交出错");
            } else if(!token1.equals(token)){
            System.out.println("提交出错");
            }else{
            System.out.println("提交成功");
            //移除session 防止重复提交
            request.getSession().removeAttribute("token");
             }    
            return "";
2.用来作身份验证:在服务端不需要存储用户的登录记录
       大概的流程是这样的:
       (1)客户端使用用户名跟密码请求登录;
       (2)服务端收到请求,去验证用户名与密码;
       (3)验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端(token就是用户凭证了)
       (4)客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里
       (5)客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
       (6)服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据
       扩展:1. 通常放在Authorization header中,用Bearer schema
             2. 如果token是在授权头(Authorization header)中发送的,那么跨源资源共享(CORS)将不会成为问题,因为它不使用cookie
             3. 每一次请求都需要token
             4. 还需要将服务器设置为接受来自所有域的请求,用Access-Control-Allow-Origin: *
             5. 验证Token,可以使用拦截器/过滤器

3.5.基于Token的身份认证是无状态的,服务器或者Session中不会存储任何用户信息
3.6.使用JWT优缺点

1.优点:(5点)
          (1)无状态和可扩展性:Tokens存储在客户端。完全无状态,可扩展
          (2) 自包含,减少存储开销;
          (3) 跨语言,支持多种语言的实现
          (4) 支持过期,发布者校验
          (5) 安全性高,防止token被伪造和篡改:
                   《1》Token不是Cookie,每次请求的时候Token都会被发送,
                   《2》助于防止CSRF攻击
                   《3》即使在实现中将token存储到客户端的Cookie中,这个Cookie也只是一种存储机制,而非身份认证机制
                   《4》没有基于会话的信息可以操作,因为没有会话
                   《5》token在一段时间以后会过期,这个时候用户需要重新登录,这有助于保持安全
2.缺点:(3点)
          (1) 消息体可以被base64解密为明文
          (2)不适合存放大量信息
          (3)无法作废未过期的jwt
          (4)JWT并不支持用户主动退出登录,在客户端删除这个token,但在别处使用的token仍然可以正常访问

3.7JWT应用场景:
3.7.1.一次性验证:比如用户注册后需要发一封邮件让其激活账户,通常邮件中需要有一个链接
3.7.2.restful api 的无状态认证:
3.7.3.使用 jwt 做单点登录+会话管理(不推荐)
3.7.4.用于应用下载
例如:在A服务器上下载文件,但是文件资源在B服务器中,如果在A服务器登录成功进入B服务器需要进行身份认证才能获取下载资源,可以使用JWT

 总结:Cookie,Session,Token,JWT
  1.Session:(1)存储于服务器,拥有一个唯一识别符号sessionId,通常存放于cookie中.
            (2)服务器收到cookie后解析出sessionId,再去session列表中查找,才能找到相应session
            (3)依赖cookie
  2.Cookie:类似一个令牌,装有sessionId,存储在客户端,浏览器通常会自动添加
  3.Token:(1)也类似一个令牌,无状态,用户信息都被加密到token中,服务器收到token后解密就可知道是哪个用户
          (2)需要开发者手动添加
  4.JWT只是一个跨域认证的方案
  5.Token与JWT区别:
      (1) Token 是存储在数据库中的,在服务器端进行数据库查询,并比对 Token 是否合法
      (2)JWT 的意义是让 Token 和 Payload 加密后存储于用户端,服务端只需要解密即可,不需要查库即可获得类似存储于 Session 的数据(Payload),并且可信赖

你可能感兴趣的:(java会话机制专栏)