认证
认证
定义
身份验证的目的是确认当前所声称为某种身份的用户,确实是所声称的用户。简单来说就是系统确认你是你的过程,用户声称自己是管理员,用什么证明?当你输入了正确的管理员账户和密码,你是管理员就被证实了,这就是认证的通俗解释。
方式
- 用户名密码
- cookie
- token
基于用户名密码的认证
客户端发送请求时,携带用户名和密码,服务器根据用户名和密码对请求进行认证。
- 优点:简单
- 缺点:
- 用户名密码泄漏风险大
- 每次请求到达,服务器都需要比对用户密码数据库,服务器端压力大
- 无法提供更多的有效信息,只有用户名
基于session(cookie)的认证
基本的步骤:
- 用户输入用户名和密码,发送给服务器
- 服务器验证一下用户名和密码,正确的话就创建一个会话( session ),保存方式多种多样,可以是内存,数据库,缓存
- 通过 set-cookie 将生成的sessionID 写入的客户端的 cookie 中,作为 session 的唯一标识符
- 后续的请求中,浏览器会发送会话 ID 到服务器,服务器上如果能找到对应 ID 的会话,那么服务器就会返回需要的数据给浏览器
- 当用户退出登录,会话会同时在客户端和服务器端被销毁
优缺点
- 优点:简单
- 缺点:
- App等移动应用中,没有 Cookie 机制
- CSRF(跨站请求伪造)
- CORS(跨域资源共享)
基于token的认证
基本步骤
使用token机制的身份验证方法,大概的流程:
- 客户端使用用户名和密码请求登录。
- 服务端收到请求,验证用户名和密码。
- 验证成功后,服务端会生成一个token,然后把这个token发送给客户端。
- 客户端收到token后把它存储起来,可以放在cookie或者Local Storage(本地存储)里。
- 客户端每次向服务端发送请求的时候都需要带上服务端发给的token。
- 服务端收到请求,然后去验证客户端请求里面带着token,如果验证成功,就向客户端返回请求的数据。
token是什么
Token是服务端生成的一串字符串,用作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。
简单token的组成;uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(数字签名,服务器的签名,表示该token由服务器签发)
其实基于session的认证也可以理解成一种基于token的认证方式,他们的步骤和原理都是一样的。他们的区别仅仅是客户端cookie中存储的是什么,如果存储的是sessionID,那么就是基于session的认证。如果cookie中存储的是token,那么就是基于token的认证方式。如果你将sessionID也看成是一种特殊的token的话,那么这两种方式就是一样的
token的优点
- HTTP是无状态协议,客户端使用用户名和密码通过了身份验证,不过下次这个客户端再发送请求时候,还得再验证一下。也就是说如果没有token,那么客户端的每次请求都需要携带用户和密码信息,同时服务器每次都需要对用户和密码进行验证。对服务器来说每次验证都是查询数据库,服务器压力很大。
- 如果客户端每次请求都携带用户名和密码,用户密码泄漏的风险会变高;同时,相比较密码,token具有时效性,就算泄漏了,那也会因为过期而失效,如果是密码泄漏,如果用户不主动修改密码,那么账户的风险会一直存在。
- token能够弥补基于cookie的认证方式中的缺点。
token的存储
- 客户端存储在前端的cookie、Local Storage中(纯前端客户端)。
- 服务器端存储方式有很多实现,数据库,内存。
- 存储在前端的cookie、Storage中存在XSS的风险,安全系数低;现代架构中,客户端一般会做成前后端分离(纯前端和专为前端服务的后端BFF),这时将token存储在客户端的后端中,就会很安全。(引申:这种架构,在选择oauth2.0方式时,应该选择授权码模式;纯前端的客户端选择隐藏模式后面会讲到)
token之于服务端和客户端
一般情况下token需要在客户端和服务器端都保存,对于客户端和服务器端,token对他们的意义不同:
- 服务器端:用户输入正确的账户和密码,服务器生成(签发)一个token给客户端;同时,服务器端也要存储该token,当客户端再次携带token请求时,服务器端查询该token是否存在(不存在则表示token无效),验证token是否过期(通过查看token中的时间戳判断),在某些情况下还会提取token的其他业务信息。同时,服务器端可以随时吊销签发过的token(将服务器端存储的token删除)。
- 客户端:每次请求都将token携带,一般不会读取token内容;有些场景下,比如第三方系统(微信小程序),在获得用户授权后,微信服务器会签发token,小程序就会读取token中的用户信息,这样就可以不用做用户认证和用户管理功能了。
- 这种情况下的token称之为有状态的,服务器端可以随时吊销签发过的token。
还有一种token只需要在客户端存储:
- 服务器端:在用户登录后,签发token给客户端,服务器端不存储token,签发的token中会携带用户信息、token过期时间、其他的业务信息等;
- 客户端:每次请求都将token携带,一般不会读取token内容;特殊情况下同上。
- 这种情况下的token称之为无状态的token,因为服务器端不会存储token,一旦签发过后,无法吊销。
token的形式
- 用设备mac地址作为token
- 用sessionid作为token
- JWT(无状态):不是协议,时一种token格式。
- Oauth2.0(有状态):Oauth2.0是一种协议,它的token形式是access_token和refresh_token。
token的形式不局限于上面四种,其实用什么样的token都是可以的;jwt和oauth2.0只是一种业界好的实现方式而已,并没有什么特别的地方,仅仅是实现他们需要遵照他们的协议。为了需要,你甚至可以自己创建一个协议。
参考
认证
http://mybestcheng.site/2020/12/25/authenticate/authentication/