鉴权和身份认证
所谓鉴权就是身份认证,就是验证您是否有权限从服务器访问或操作相关数据。通俗的讲就是一个门禁,您想要进入室内,必须通过门禁验证身份,这就是鉴权,如打开一个网站必须要输入用户名和密码才可以登录进入,这种就是鉴权,还有一些业务需要登录以后才可以进行,因为需要token值,则就可以把token添加到鉴权中,这种也是鉴权。
常用的鉴权方式
- Basic 认证:户籍部门已给你签发了一张身份证。你每次去办事,都要带上身份证证,后台要拿你的身份证去系统上查一下。
- Session 认证:户籍部门已给你签发了一张身份证,但只告诉你身份证号码。你每次去办事,只要报出你的身份证号码,后台要查一个即否有效。
- Token 认证:户籍部门已给你签发了一张有防伪功能的身份证。你每次去办事,只要出示这张卡片,它就知道你一定是自己人。
1、Basic
HTTP Basic Authentication
在这种认证方法下,用户每次发送请求时,请求头中都必须携带能通过认证的身份信息。
其交互过程如下:
-
开始时,客户端发送未携带身份信息的请求。
-
服务端返回 401 Unauthorized 状态,并在返回头中说明要用
Basic
方法进行认证:WWW-Authenticate: Basic
。 -
客户端重新发送请求,并将身份信息包含在请求头中:
Authorization: Basic aHk6bXlwYXNzd29yZA==
。 -
服务端验证请求头中的身份信息,并相应返回 200 OK 或 403 Forbidden 状态。
-
之后,客户端每次发送请求都在请求头中携带该身份信息
其中传送的身份信息是 <username>:<password>
经 base64 编码后的字串。如本例中的 aHk6bXlwYXNzd29yZA==
, 经 base64 解码后为 hy:mypassword
。
这种认证方法的优点是简单,容易理解。
缺点有:
- 不安全:认证身份信息用明文传送,因此需结合 https 使用。
- 效率低:服务端处理请求时,每次都需要验证身份信息,如用户名和密码。
2、session
这种认证方法结合了 Session 和 Cookie。服务端将本次会话信息以 Session 对象的形式保存在服务端的内存、数据库或文件系统中,并将对应的 Session 对象 ID 值 SessionID 以 Cookie 形式返回给客户端,SessionID 保存在客户端的 Cookie 中。
这是一种有状态的认证方法:服务端保存 Session 对象,客户端以 Cookie 形式保存 SessionID。
其交互过程如下:
- 客户端在登录页面输入身份信息,如用户名/密码。
- 服务端验证身份信息,通过后生成一个 Session 对象,保存到服务端,并将 SessionID 值以 Cookie 形式返回给客户端。
- 客户端将接收到的 SessionID 保存到 Cookie 中,并且之后每次请求都在请求头中携带 SessionID Cookie。
- 服务端从请求的 Cookie 中获取 SessionID,并查询其对应的 Session 对象,从而获得身份信息。
- 客户端退出本次会话后,客户端删除 SessionID 的 Cookie,服务端删除 Session 对象。
- 如果客户端之后要重新登录,需重新生成 Session 对象和 SessionID。
优点:
- 较安全:客户端每次请求时无需发送身份信息,只需发送 SessionID。
- 较高效:服务端无需每次处理请求时都要验证身份信息,只需通过 SessionID 查询 Session 对象。
缺点:
- 扩展性差,Session 对象保存在服务端,如果是保存在多个服务器上,有一致性问题,如果保存在单个服务器上,无法适应用户增长。
- 基于 Cookie 的 SessionID 不能跨域共享,同一用户的多个客户端(如浏览器客户端和 APP)不能共享 SessionId。
- 基于 Cookie 的 SessionID 易被截获生成 CSRF 攻击。
3、Token
Token验证(包括JWT,SSO)
这是一种 SPA 应用(单页Web应用single page web application
)和 APP 经常使用的认证方法。它是一种无状态的认证方法。
客户端首先将用户信息发送给服务端,服务端根据用户信息+私钥生成一个唯一的 Token 并返回给客户端。Token 只保存在客户端,之后客户端的每个请求头中都携带 Token,而服务端只通过运算(无需查询)来验证用户。
- 客户端使用用户名和密码请求登录
- 服务端收到请求,验证用户名和密码
- 验证成功后,服务端会签发一个token,再把这个token返回给客户端
- 客户端收到token后可以把它存储起来,比如放到cookie中
- 客户端每次向服务端请求资源时需要携带服务端签发的token,可以在cookie或者header中携带
- 服务端收到请求,然后去验证客户端请求里面带着的token,如果验证成功,就向客户端返回请求数据
优点:
- Token 只保存在客户端,因此不影响服务端扩展性。
- 为用户生成的 Token 可以在多个客户端共用。
- 支持跨域访问:cookie是无法跨域的,而token由于没有用到cookie(前提是将token放到请求头中),所以跨域后不会存在信息丢失问题
- 无状态:token机制在服务端不需要存储session信息,因为token自身包含了所有登录用户的信息,所以可以减轻服务端压力
- 更适用CDN:可以通过内容分发网络请求服务端的所有资料
- 更适用于移动端:当客户端是非浏览器平台时,cookie是不被支持的,此时采用token认证方式会简单很多
- 无需考虑CSRF:由于不再依赖cookie,所以采用token认证方式不会发生CSRF,所以也就无需考虑CSRF的防御
缺点:
- Token 包含了用户的全部信息,不只是如 SessionID 类似的一个 ID 值,因此会增加每次请求包的大小。
目前使用较多的是基于JWT(JSON Web Tokens) 的 Token 认证法。
JWT
token认证的一种实现方式。特别适用于分布式站点的单点登录(SSO)场景,是目前最流行的跨域认证解决方案。
https://jwt.io/
通俗地说,JWT的本质就是一个字符串,它是将用户信息保存到一个Json字符串中,然后进行编码后得到一个JWT token
,并且这个JWT token
带有签名信息,接收后可以校验是否被篡改,所以可以用于在各方之间安全地将信息作为Json对象传输。
JWT的认证流程
- 首先,前端通过Web表单将自己的用户名和密码发送到后端的接口,这个过程一般是一个
POST
请求。建议的方式是通过SSL加密的传输(HTTPS),从而避免敏感信息被嗅探。 - 后端核对用户名和密码成功后,将包含用户信息的数据作为JWT的Payload,将其与JWT Header分别进行Base64编码拼接后签名,形成一个JWT Token,形成的JWT Token就是一个如同lll.zzz.xxx的字符串
- 后端将JWT Token字符串作为登录成功的结果返回给前端。前端可以将返回的结果保存在浏览器中,退出登录时删除保存的JWT Token即可
- 前端在每次请求时将JWT Token放入HTTP请求头中的Authorization属性中(解决XSS和XSRF问题)
- 后端检查前端传过来的JWT Token,验证其有效性,比如检查签名是否正确、是否过期、token的接收方是否是自己等等
- 验证通过后,后端解析出JWT Token中包含的用户信息,进行其他逻辑操作(一般是根据用户信息得到权限等),返回结果
JWT结构
JWT由3部分组成:标头(Header)、有效载荷(Payload)和签名(Signature)。在传输的时候,会将JWT的3部分分别进行Base64编码后用.
进行连接形成最终传输的字符串。
JWTString=Base64(Header).Base64(Payload).HMACSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload),secret)
1.Header
JWT头是一个描述JWT元数据的JSON对象,alg属性表示签名使用的算法,默认为HMAC SHA256(写为HS256);typ属性表示令牌的类型,JWT令牌统一写为JWT。最后,使用Base64 URL算法将上述JSON对象转换为字符串保存
{
"alg": "HS256",
"typ": "JWT"
}
2.Payload
有效载荷部分,是JWT的主体内容部分,也是一个JSON对象,包含需要传递的数据。 JWT指定七个默认字段供选择
- iss (issuer):签发人
- exp (expiration time):过期时间
- sub (subject):主题
- aud (audience):受众
- nbf (Not Before):生效时间
- iat (Issued At):签发时间
- jti (JWT ID):编号
这些预定义的字段并不要求强制使用。除以上默认字段外,我们还可以自定义私有字段,一般会把包含用户信息的数据放到payload中,如下例:
{
"sub": "1234567890",
"name": "Helen",
"admin": true
}
请注意!默认情况下JWT是未加密的,因为只是采用base64算法,拿到JWT字符串后可以转换回原本的JSON数据,任何人都可以解读其内容,因此不要构建隐私信息字段,比如用户的密码一定不能保存到JWT中,以防止信息泄露。JWT只是适合在网络中传输一些非敏感的信息。
3.Signature
签名哈希部分是对上面两部分数据签名,需要使用base64编码后的header和payload数据,通过指定的算法生成哈希,以确保数据不会被篡改。首先,需要指定一个密钥(secret)。该密码仅仅保存在服务器中,并且不能向用户公开。然后,使用header中指定的签名算法(默认情况下为HMAC SHA256)根据以下公式生成签名。
HMACSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload),secret)
在计算出签名哈希后,JWT头,有效载荷和签名哈希的三个部分组合成一个字符串,每个部分用.
分隔,就构成整个JWT对象
注意JWT每部分的作用,在服务端接收到客户端发送过来的JWT token之后:
- header和payload可以直接利用base64解码出原文,从header中获取哈希签名的算法,从payload中获取有效数据
- signature由于使用了不可逆的加密算法,无法解码出原文,它的作用是校验token有没有被篡改。服务端获取header中的加密算法之后,利用该算法加上secretKey对header、payload进行加密,比对加密后的数据和客户端发送过来的是否一致。注意secretKey只能保存在服务端,而且对于不同的加密算法其含义有所不同,一般对于MD5类型的摘要加密算法,secretKey实际上代表的是盐值
增加JWT的安全性
- 因为JWT是在请求头中传递的,所以为了避免网络劫持,推荐使用HTTPS来传输,更加安全
- JWT的哈希签名的密钥是存放在服务端的,所以只要服务器不被攻破,理论上JWT是安全的。因此要保证服务器的安全
- JWT可以使用暴力穷举来破解,所以为了应对这种破解方式,可以定期更换服务端的哈希签名密钥(相当于盐值)。这样可以保证等破解结果出来了,你的密钥也已经换了
4、OAuth(开放授权)
OAuth是Open Authority的缩写。OAuth 就是一种授权机制。用来授权第三方应用,获取用户数据。通过数据的所有者授权第三方应用进入系统,系统从而产生一个临时的令牌,代替密码,授权第三方应用使用权限。
OAuth开放授权为用户资源的授权提供了一个安全的、开放而又简易的标准。OAUTH的授权不会使第三方触及到用户的帐号信息例如用户名与密码等,即第三方无需使用用户的用户名与密码就可以申请获得该用户资源的授权,因此OAUTH授权是安全的,目前OAUTH的版本为2.0
优点
可控姓: 保证了令牌既可以让第三方应用获得权限,同时又随时可控,不会危及系统安全;
方便性: 只要知道了令牌,就能进入系统;
重要性: 系统一般不会再次确认身份,所以令牌必须保密,泄漏令牌与泄漏密码的后果是一样的,这也是为什么令牌的有效期,一般都设置得很短的原因。
SSO 与 Oauth
SSO
SSO是Single Sign On的缩写。SSO是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。它包括可以将这次主要的登录映射到其他应用中用于同一个用户的登录的机制。它是目前比较流行的企业业务整合的解决方案之一。
区别
两者都是使用令牌的方式来代替用户密码访问应用。
SSO :一次登陆
Oauth:一次授权
OAuth解决的是服务提供方(微信等)给第三方应用授权的问题;
SSO解决的是大型系统中各个子系统如何共享登陆状态的问题。(比如你登录了百度首页,那么你进入百度百科,百度贴吧,百度音乐等服务的时候都不需要重新登录。)
两者都是基于分布式系统,涉及到多个角色,但是不同的是,OAuth是一种具体的协议,SSO可以说是一种技术,可以用cookie实现,甚至也可以用OAuth实现(虽然不是很好),比如OAuth中的服务提供方可以充当SSO认证中心,OAuth中的第三方应用也可以是SSO中的子系统。文章来源:https://www.toymoban.com/news/detail-839528.html
参考1 参考2 参考3文章来源地址https://www.toymoban.com/news/detail-839528.html
到了这里,关于鉴权与身份认证的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!