session,token,jwt认证

什么是认证?

认证即是登录认证,在我们日常浏览网站时经常会遇到,比如,购物网站中购买商品时需要我们先进行登录认证,在一些问答型网站,往往需要用户登录认证后才能发表,评论和收藏。


常见认证方式

常见的认证方式有:

  • cookie-session认证;
  • token认证;
  • JWT(json web token)认证。

cookie-session认证

http协议是一种无状态的协议。

什么是无状态?当用户在发送请求时,向服务器提供了用户名和密码进行用户认证,服务器验证通过后返回200/OK,一个http的请求就结束了,所以现在的状态应该是已登录验证状态,如果按照正常的逻辑,验证过之后就可以使用一些验证过才能使用的功能,但http是一种无状态协议,这代表着浏览器和服务器都不会记住该状态(也就是我们已经登录过了)。

再一次发送请求时,服务器依然会让我们执行登陆验证,因为服务器并不知道我们已经验证过了。

为了能让服务器记住我们的操作,服务器在登录验证后,会创建一个Session信息(一般session会包含用户的信息)用于标识并跟踪用户,并且将SessionID存到response的cookie字段中,然后返回给浏览器。浏览器会保存该cookie,在下次发送请求时,自动带上cookie信息,服务器通过cookie获取session进行校验,并获取服务器Session中存储的信息。
认证流程如下图:

cookie-session认证的缺点

  1. 用户经过验证后,会在服务器上做一次记录,创建一条session信息方便用户下次请求的鉴别,而session是存放在服务器内存中,随着用户的增多,服务器的开销会逐渐增大,到达一定的数量后,会影响服务器的运行效率;
  2. 用户认证后,服务端的session存放在服务器内存中,下次请求必须还要发送到这个服务器上,才能拿到授权的资源。但是在分布式应用中,该操作就限制了网关的负载均衡功能,这时候就需要考虑session同步问题;
  3. 该认证方式是基于cookie来进行用户识别的,如果cookie被截获,用户就很容易受到 CSRF(跨站请求伪造)的攻击;
  4. cookie不能跨域,所以需要考虑跨域的问题;

基于token的鉴权机制

Token,通常叫做令牌,是一种自定义实现的类似Session/Cookie机制的,用来代替传统Session/Cookie的新兴鉴权方案。

Token是服务端生成的一串加密字符串,在用户登录认证成功后生成并返回给客户端,之后客户端的每次请求都会携带token,服务端通过验证token的有效性来完成鉴权。

基于token的鉴权机制是无状态的,不需要在服务端去保留用户的认证信息或会话信息。

流程示意:

  • 用户使用用户名密码来请求服务器
  • 服务器进行验证用户的信息
  • 服务器通过验证发送给用户一个token
  • 客户端存储token,并在每次请求时附送上这个token值
  • 服务端验证token值,并返回数据
  • Token存活时间达到设置的有效期后自动失效

这个token必须要在每次请求时传递给服务端,它应该保存在请求头里, 另外,服务端要支持CORS(跨来源资源共享)策略,一般我们在服务端这么做就可以了Access-Control-Allow-Origin: *

token的优点

  1. 无状态、可扩展、适合分布式;
  2. 性能高、安全性好,能够防止CSRF(跨站请求伪造),解决跨域问题;
  3. Token鉴权时只需要客户端保存信息,减少了服务端对内存的消耗;
  4. 对于手机APP端适应性好;

JWT认证

JWT技术是基于token方案的技术实现。

什么是JWT(JSON WEB TOKEN)?

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

JWT的认证流程图

流程说明

  1. 浏览器发起请求登陆,携带用户名和密码;
  2. 服务端验证身份,根据算法,将用户标识符打包生成 JWT;
  3. 服务器返回JWT信息给浏览器,JWT不包含敏感信息;
  4. 浏览器发起请求获取用户资料,把刚刚拿到的 JWT一起发送给服务器;
  5. 服务器发现数据中有 JWT,验明正身;
  6. 服务器返回该用户所需资源;

JWT的构成

JWT是由三段信息构成的,将这三段信息用.链接起来就构成了jwt字符串。格式如下:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

JWT的三段信息分别为:

  1. header(头部);
  2. payload(载荷);
  3. signature(签证);

header(头部)

JWT的头部承载两部分信息:

  • 声明类型,这里是jwt;
  • 声明加密的算法,通常直接使用HMAC SHA256;

完整的头部如下json所示:

{
  'typ': 'JWT',
  'alg': 'HS256'
}

然后将头部进行base64加密(该加密是可以对称解密的),构成了第一部分

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

payload(载荷)

载荷就是存放有效信息的地方,也是一个JSON对象,用来存放实际需要传递的数据。这些有效信息包含三个部分:

标准中注册的声明(建议但不强制使用):

JWT规定了7个官方字段,可供选用;

iss (issuer):jwt签发者

exp (expiration time):过期时间 ,这个过期时间必须要大于签发时间

sub (subject):jwt所面向的用户

aud (audience):接受jwt的一方

nbf (Not Before):生效时间,定义在什么时间之前,该jwt都是不可用的

iat (Issued At):jwt的签发时间

jti (JWT ID):jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击

公共的声明
公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息.但不建议添加敏感信息,因为该部分在客户端可解密.

私有的声明
私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息。

代码展示

定义一个payload:

{
  "sub": "1234567890",
  "name": "John Doe",
  "admin": true
}

然后将其进行base64加密,得到Jwt的第二部分。

eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9

signature(签证)

signature是对前两部分的签名,防止数据被篡改。signature由三部分组成:

  • header(base64加密后的)
  • payload(base64加密后的)
  • secret

签名生成时,首先需要指定一个密钥(secret),这个密钥只有服务器才知道,不能泄漏给用户,然后,使用 Header 里面指定的签名算法(默认是 HMAC SHA256),按照下面的公式产生签名。

signature = HMACSHA256(  base64UrlEncode(header) + "." +  base64UrlEncode(payload),   secret)

使用公式就可以生成jwt的第三部分,将这三部分用.连接成一个完整的字符串,就构成整个JWT对象TOKEN, 就可以返回给用户。

注意:secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。

总结

优点

  • 因为json的通用性,所以JWT是可以进行跨语言支持的,像JAVA,JavaScript,NodeJS,PHP等很多语言都可以使用;

  • 因为有了payload部分,所以JWT可以在自身存储一些其他业务逻辑所必要的非敏感信息;

  • 便于传输,jwt的构成非常简单,字节占用很小,所以它是非常便于传输的;

  • 它不需要在服务端保存会话信息, 所以它易于应用的扩展;

安全相关

  • 不应该在jwt的payload部分存放敏感信息,因为该部分是客户端可解密的部分;
  • 保护好secret私钥,该私钥非常重要;
  • 如果可以,请使用https协议;

Session和JWT的区别

  • session存储在服务端,占用服务器的资源,而JWT存储在客户端;
  • sesison在客户端存储在cookie中,存在请求跨站伪造攻击的风险;
  • session只存在一台服务器上,那么下次请求就必须请求这台服务器,不利于分布式应用;
  • 存储在客户端的JWT比存储在服务端的session更具有扩展性;

Token和JWT的区别

相同:

  • 都是访问资源的令牌;
  • 都可以记录用户的信息;
  • 都是服务端无状态化(都保存在客户端,服务端无需保存);
  • 都是只有验证成功后,客户端才能够访问服务端上受保护的资源;

区别:

  • Token:服务端验证客户端发送过来的token时,还需要去查询数据库获取用户信息。然后验证Token是否有效;
  • JWT:将Token和Payload加密后存储于客户端,服务端只需要使用密钥解密进行校验(校验JWT自己实现的)即可,不需要查询或者减少查询数据库,因为JWT自包含了用户信息和加密的数据;

本文参考:

  1. 什么是 JWT -- JSON WEB TOKEN - 简书 (jianshu.com)
  2. 说一说几种常用的登录认证方式,你用的哪种-腾讯云开发者社区-腾讯云 (tencent.com)
  3. 什么是Http无状态?Session、Cookie、Token三者之间的区别 - 翎野君 - 博客园 (cnblogs.com)
  4. 鉴权界的后起之秀:Token鉴权方案 - 掘金 (juejin.cn)
  5. 【深度知识】JSON Web令牌(JWT)的原理,流程和数据结构-腾讯云开发者社区-腾讯云 (tencent.com)
  6. 30s 看懂最基础的认证方式: Session-Cookie 认证-腾讯云开发者社区-腾讯云 (tencent.com)
  7. JSON Web Token Introduction - jwt.io
  8. RFC 7519 - JSON Web Token (JWT) (ietf.org)
posted @ 2023-05-06 16:35  joudys  阅读(195)  评论(0)    收藏  举报