前端需要知道的登录鉴权方式

463 阅读15分钟

image.png 借用一张图,参考:juejin.cn/post/712929…

1.认证

认证就是“用户”需要拿着自己的“工牌”,进入到服务器之中。有的人可能难以理解:认证就是证明你是你自己这句话。因为我们日常中几乎很少碰到需要证明我是我的情况。举一个极端的情况:我的身份证被偷了,小偷拿着我的身份证去银行机器门口挂失了我所有的银行卡。小偷为什么可以拿着我的身份证挂失我的银行卡。因为银行的认证是通过机器认证的(忽略人脸识别,只有刷身份证认证)。所以认证的过程就是识别身份证的过程。因此我进入到服务器,需要拿着服务器给我的工牌,服务器通过工牌认证我是工牌中照片这个人。如果那一天我的工牌被盗用了,那么即使我是我自己,但是服务器也是认证我不是我。因此工牌很重要,不能丢掉。常用的认证技术:身份证、用户名&密码、指纹等一切可以区别个体实例的东西,所以认证ID具有唯一性。
常见场景:我们登录的用户名&密码相当于我们拿着身份证去公司认证,公司认证:存在你这个身份证或者你的用户名和ID在公司有注册表过,那么就相当于你认证成功。下一步人事会给你一张属于你的工牌,下次来的时候直接拿工牌刷就可以了。但是公司有好几栋楼,你的工牌并不能进入每一栋楼,所以当你想进入一栋楼的时候,你会先拿你的工牌去刷每栋楼的门禁,成功即可进入,否则没有权限。刷每栋楼门禁的过程就是鉴权。

2.授权

授权是认证完成之后需要处理的东西。当我们拿着工牌进入公司之后,公司保安给我一张内部的卡。给我这张卡的行为就是授权。因为这张卡决定了进入公司后我可以做那些事,或者拿着这个工牌可以进出公司的哪些门。说白了就是我这个“个体”的操作权限范围。如果不给我这张授权卡,我只能在公司闲逛。在互联网领域就是coookie/颁发授权令牌(token)

所以认证是为了发给你一张身份卡,鉴权是你拿着这张卡给保安鉴定你可以做那些事情。

3.鉴权&方案

我拿着授权卡去刷公司内部其他的门禁,那么门禁的机器就是鉴权机器,这个过程就是鉴权的过程,在互联网领域就是校验 session/cookie/token 的合法性和有效性。
鉴权问题一般考虑两个方面:
1.鉴权本身的安全问题,前端怎么防护工牌cookie不被盗取
2.用户状态保存,后端拿到cookie就要知道用户之前操作到哪一步了

总结1:
所以,我们登录用户名和密码的时候,就相当于认证了,然后接口返回响应(这个过程包含了后端授权和发工牌给前端,这个工牌前端怎么存储,有好几种方式,存在cookie种等)。然后前端再次请求的时候需要带上这个工牌,后端拿到这个工牌后需要验证合法性和有效性(前端请求时候带上工牌cookie,后端验证工牌cookie),这个过程就是鉴权。具体前端怎么带(放在cookie还是autheration),后端怎么验证,可以拓展为鉴权的方式。因此,日常种我们所说的前端cookie怎么传,就是指这个工牌怎么传才安全,不会被捕获。 典型的就是csrf,攻击方利用你的cookie操作。

总结2:
认证、授权、鉴权、权限控制这四个环节是拥有前后关系的,但是在互联网中,这四个环节的发生几乎是一气呵成,不易察觉。我们登录用户名和密码就是我们拿工牌的过程,点击登录那一下就是把密码发给服务器进行“认证”。服务器认证完成后(此时还在后端逻辑中,没有返回)开始要把内部使用授权卡给用户。这样让用户下次请求的时候带上这个授权卡(弥补了http无状态,避免每次都要认证的过程),用户下次请求拿上这个授权卡就可以认为经过了认证完成,已经在公司内了,此时响应登录接口,响应字段中将授权卡给用户。
用户登录之后进入到主页面(中间可能存在重定向到主html),查询主页面中的数据,调用getdate接口。待用的时候拿上“授权卡”,后端服务器通过“鉴权”这张“授权卡”,鉴权通过就可以认为是鉴权通过(鉴权通过包括认证通过)。当然后面也可以通过权限控制来变更。

总之:
1.前端登录并发出请求的过程是“认证”
2.登录接口响应是“授权”
3.后面接口的调用就是“带上授权卡”给后端“鉴权”
image.png

3.1 Session-Cookie鉴权

3.1.1 Session-Cookie 的认证流程图

客户端向服务端发送创建账号请求之后,服务端就会为这个刚刚创建的账号新建一个sessionID(将 Session 保存在内存中,也可以保存在 Redis 中),然后给这个 Session 生成一个唯一的标识字符串会话身份凭证 session_id(通常称为 sid),并在响应头 Set-Cookie 中设置这个唯一标识符;
step1: 用户登录用户名和密码之后,服务器返回的响应中会存在一个set-cookie字段,浏览器会拿到这个字段并放入到自己的cookie中 step2:
注意:浏览器的cookie机制,即当cookie中domain或者path符合当前请求链接,并且没有禁用限制时候浏览器会自动在这个请求的请求头字段加上cookie值。这个操作是浏览器自动执行的,不需要开发人员代码中设置。
(1)服务器可设置的set-cookie字段如下: image.png (2)cookie中存在的字段如下(10个):

标题意义
domain域名
path路径
namecookie名称
value
expires/max-age过期时间
httpOnly设置为true时候,只能浏览器自己自动在http/https中携带cookie,禁止js通过操作document.cookie获取
securehttp/https两个协议中只能https传递此cookie
SameSite'strict':当前浏览器tab的URL和请求的API目标一致才可发送cookie,可用来防止CSRF攻击,但是一般请求API域名多个,所以一般使用token防止CSRF攻击。SameSite默认值为none|

3.1.2 Session-Cookie的优点:

  • 只需要后端操作即可,前端可以无感等进行操作
  • Cookie 简单易用
  • Session 数据存储在服务端,相较于 JWT 方便进行管理,也就是当用户登录和主动注销,只需要添加删除对应的 Session 就可以了,方便管理

3.1.3 Session-Cookie 的缺点

  • 1.存在cookie限制:依赖 Cookie,一旦用户在浏览器端禁用 Cookie,就无法发送
  • 2.前端安全CSRF问题:非常不安全,Cookie 将数据暴露在浏览器中,增加了数据被盗的风险(容易被 CSRF 等攻击)
  • 3.Session后端存储问题:Session 存储在服务端,增大了服务端的开销,用户量大的时候会大大降低服务器性能;
    对移动端的支持性不友好;

3.1.4 使用场景

  • 一般中大型的网站都适用(除了 APP 移动端);
  • 由于一般的 Session 需集中存储在内存服务器上(如 Redis),这样就会增加服务器的预算,所以预算不够请谨慎选择; 总结: cookie-session机制说到底,就是后端在认证授权完成后,将工牌<=>等价于

3.2 Token鉴权

token鉴权主要是为了解决两个问题: 1.前端cookie-seesion鉴权安全问题 2.后端维护session的问题:Token 机制在服务端不需要存储会话(Session)信息,因为 Token 自身包含了其所标识用户的相关信息,这有利于在多个服务间共享用户状态

token为什么可以预防csrf攻击?
csrf,跨站请求伪造,说白了就是可能利用你的浏览器发送邮件,因为浏览器存的cookie会在domain允许范围内自动带上发送给服务器,这就是csrf攻击的原理。攻击者要利用这个原理,在自己的html中发送对特定网址的请求,例如人人都有QQ邮箱,因此我们qq邮箱的cookie没有过期的时候,我们打开的有毒网站,网站在初始化的时候就会调用post('qq/api/fuck', params)。这个时候通过js脚本发出qq请求(等价于我们在网页上通过邮箱的send按钮操作)。这个时候浏览器不管是界面还是js发出的请求都会带上qq邮箱的cookie。然后邮箱服务器收到之后,验证cookie,成功,向你每个好友都发送了fuck邮件,直接社死。而token是我们在项目中js放在请求头的,所以不会存在自动发送的问题。csrf说到底就是自动发送惹的祸。

当因为token的有效期一般都比较短,所以很容易出现token过期了,出现重新登录的情况怎么办?
(1) 方法1: 让用户重新登录,然后获取新的token
(2) 方法2: 为了解决方法1重新登录的麻烦,新增了fresh token来避免二次登录。这个fresh token 和access token是一起生成的。也就是说,当我们登录之后会生成两个token,一个是真正要认证用到的access-token(短期有效),还有一个是fresh token(长期有效)。当前端收到后端的响应发现access失效之后,会在代码中重新发起一个特殊请求(这个请求专门用来获取新的access-token)(这个请求需要带上fresh-token),后端收到这个请求中的fresh-token后发现通过认证fresh-token,通过后会生层一个新的access-token给前端,前端收到后再次发起数据请求。

参考文献: juejin.cn/post/712929…

3.3 JWT鉴权

3.4 SSO单点登录(认证&鉴权)

SSO登录,说白了就是解决通过一个token可以登录多个不同的系统,解决每个系统对应各自的token认证导致切换时候需要另外登录的繁琐操作。在多个应用系统中,只需要登录一次,就可以访问其他相互信任的应用系统。

  • 例如登录天猫,淘宝也会自动登录;
  • 登录百度贴吧,百度网盘也会自动登录;

sso按照系统域名的不同,可以分为同域SSO和跨域SSO

(1)同域SSO

解决方案cookie-domain

所谓同域,就是指同域名,这里的同域名一般来说是指二级域名相同(.com是一级域名,baidu.com是二级域名),例如:百度贴吧的域名tieba.baidu.com和百度网盘的域名pan.baidu.com,因为二级域名相同,所以两个系统的SSO登录属于同域名SSO。一般是同一个企业下的不同子系统,其二级域名一般都是相同的,例如:子系统名.企业名.com,对于这种同域名的系统

同域名SSO解决方案
通过set-cookie设置cookie中的domain属性值为二级域名即可,而不是设置为三级域名

例如:在后端设置tieba.baidu.com的cookie时候,通过setCookie设置对应的domain值为“baidu.com”即可,那么浏览器在访问pan.baidu.com的时候就会去匹配到“baidu.com”对应的cookie值(即SSO-TOKEN),自动发送给pan.baidu.com域名服务器。后端拿到“baidu.com”对应的cookie值(这个cookie值就是SSO-token)去验证登录状态。

具体步骤如下:

  • 客户端: 用户访问某个子系统时(例如 tieba.baidu.com),如果没有登录,则跳转至 SSO 认证中心提供的登录页面进行登录;
  • 服务端: 登录认证后,服务端把登录用户的信息存储于 Session 中,并且附加在响应头的 Set-Cookie 字段中,设置 Cookie 的 Domain 为 .baidu.com
  • 客户端:再次发送请求时,携带主域名 Domain 下的 Cookie 给服务器,此时服务端就可以通过该 Cookie 来验证登录状态了;

(2)跨域SSO

解决方案CAS(Central Authentication Service)中央授权服务

所谓跨域SSO,就是指不同域名下的SSO(注意:这里的不同域名就是指从二级域名开始就不同,例如tmall.com和taobao.com,在企业发展过程中,不同公司合并后,系统名称不方便变动,保留原来名称,但是sso认证需要更改,避免用户繁琐登录) 因为二级域名不同,显然不能通过cookie-domain的方式,所以将SSO认证服务专门提取出来,成立一个专门用来认证的SSO服务器来执行认证操作。 以下为具体sso认证过程:

  1. 用户访问系统A,系统A对应的服务器发现没有系统A的cookie,证明没有登录过,需要登录。这个时候服务器A应该放回用户302重定向,重定向地址返回值为:www.sso.com/logain/redi… ,这里的redirectURL是为了方便sso服务器认证完之后重新返回到系统A中。
  2. 用户浏览器收到302之后,自动访问302重定向地址,即sso登录地址:www.sso.com/logain/redi… 这个时候用户访问到登录页面,填写并提交登录表单,之后sso服务器需要去做两件事情:
    (1) 认证成功后通过set-cookie给用户种下sso.com的cookie值,值为sso-token。
    (2) 再通过重定向使用户重新访问系统A,重定向地址为:www.A.com?token=sso-token值, (这里通过查询参数将sso-token的值传给系统A服务器)。
  3. 系统A服务器收到请求后,进行参数解析拿到sso-token,然后系统A服务器将解析到的sso-token去给sso服务器校验认证,sso服务器认证完成后响应系统A服务器用户通过认证,然后系统A服务器主要做两件事情
    (1) 既然sso服务器认证通过,就返回页面响应给用户
    (2) 通过set-cookie给用户A种下系统A专门的cookie-A,这样下次再访问的时候自动带上系统A的cookie即可
  4. 此时,用户想要系统b,这个时候也是先输入系统b的url,系统b收到请求后没有看见系统b的cookie-b,判定没有登录,让用户重定向到sso去认证,重定向链接为:www.sso.com/logain/redi…
  5. 用户浏览器收到重定向后立即访问重定向链接,即sso链接。这个时候因为浏览器中已经存在sso的cookie,此时会自动带上sso的cookie(值为sso-token),这个时候sso服务器收到了sso-token,就不用让用户执行步骤2的登录表单填写了,直接拿token取验证,验证完成后,返回重定向链接。
    通过重定向链接将sso-token值传送给系统B,此时重定向链接为www.系统B.com?token=sso-token,
  6. 系统B通过sso服务器的重定向链接,拿到了链接中的sso-token查询参数,然后去sso系统中认证,无误后,同步骤3的系统A一样,主要做两件事情:
    (1) 既然sso服务器认证通过,就返回页面响应给用户
    (2) 通过set-cookie给用户A种下系统A专门的cookie-A,这样下次再访问的时候自动带上系统A的cookie即可

总结:
1.主要知道用户如何重定向到sso认证?
2.sso认证完成后如何返回系统A(种下sso-cookie && 通过重定向链接传递给系统A对应的sso- token)?
3.系统A向sso服务器认证完成后需要做的两件事(除了正常响应外,还要种下系统A的cookie) 对于鉴权而言,前端需要做的是,对于已经登录的系统每次请求都要发送服务器对应的cookie。而对于登录了sso系统中某个系统的时候,前端需要做的是,第一次登录的时候种下sso-token,第二次重定向sso登录链接的时候立刻将sso的token值传递给sso服务器鉴权(鉴权通过,这个时候就跳过了表单填写的响应页面,而是)。然后重定向的时候需要将sso-token交给服务器B,让B去sso服务器鉴权,然后通过后返回cookie-B。

3.5 扫码登录

3.6 一键登录(APP)