前端登录

常见的几种登录方式

  • cookie+Session

Cookie + Session 实现流程

用户首次登录时:
在这里插入图片描述

  1. 用户访问 a.com/pageA,并输入密码登录。
  2. 服务器验证密码无误后,会创建 SessionId,并将它保存起来
  3. 服务器端响应这个 HTTP 请求,并通过 Set-Cookie 头信息,将 SessionId 写入 Cookie 中
服务器端的 SessionId 可能存放在很多地方,例如:内存、文件、数据库等。

第一次登录完成之后,后续的访问就可以直接使用 Cookie 进行身份验证了:
在这里插入图片描述

  1. 用户访问 a.com/pageB 页面时,会自动带上第一次登录时写入的 Cookie。
  2. 服务器端比对 Cookie 中的 SessionId 和保存在服务器端的 SessionId 是否一致
  3. 如果一致,则身份验证成功。

Cookie + Session 存在的问题

  • 由于服务器端需要对接大量的客户端,也就需要存放大量的 SessionId,这样会导致服务器压力过大。
  • 如果服务器端是一个集群,为了同步登录态,需要将 SessionId 同步到每一台机器上,无形中增加了服务器端维护成本。
  • 由于 SessionId 存放在 Cookie 中,所以无法避免 CSRF 攻击。((Cross Site Request Forgery, 跨站域请求伪造)是一种网络的攻击方式,CSRF通过伪装来自受信任用户的请求来利用受信任的网站,CSRF 攻击之所以能够成功,是因为黑客可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于 cookie 中,因此黑客可以在不知道这些验证信息的情况下直接利用用户自己的 cookie 来通过安全验证。要抵御 CSRF,关键在于在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中。可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。
  • Token 登录

Token 是服务端生成的一串字符串,以作为客户端请求的一个令牌。当第一次登录后,服务器会生成一个
 Token 并返回给客户端,客户端后续访问时,只需带上这个 Token 即可完成身份认证。

用户首次登录时:
在这里插入图片描述

  1. 用户输入账号密码,并点击登录
  2. 服务器端验证账号密码无误,创建 Token。
  3. 服务器端将 Token 返回给客户端,由***客户端自由保存***。

后续页面访问时
在这里插入图片描述

  1. 用户访问 a.com/pageB 时,带上第一次登录时获取的 Token。
  2. 服务器端验证 Token ,有效则身份验证成功。

Token 机制的特点

  1. 服务器端不需要存放 Token,所以不会对服务器端造成压力,即使是服务器集群,也不需要增加维护成本。(优)
  2. Token 可以存放在前端任何地方,可以不用保存在 Cookie 中,提升了页面的安全性。(优)
  3. Token 下发之后,只要在生效时间之内,就一直有效,如果服务器端想收回此 Token 的权限,并不容易。(缺)

Token 的生成方式
最常见的 Token 生成方式是使用 JWT(Json Web Token),它是一种简洁的,自包含的方法用于通信双方之间以 JSON 对象的形式安全的传递信息。

为什么使用JWT
除了前面说的安全问题和性能问题
(1)前后端分离
以前的传统模式下,后台对应的客户端就是浏览器,就可以使用session+cookies的方式实现登录,但是在前后分离的情况下,后端只负责通过暴露的RestApi提供数据,而页面的渲染、路由都由前端完成。因为rest是无状态的,因此也就不会有session记录到服务器端。
(2)兼容问题
在移动端app里,或者是前后端分离的架构中,用户访问的是前端的web server(如 node.js),前端的渲染,ajax请求都是由web server完成的,这里就跟传统的不一样了,用户不是直接访问后台应用服务器的,这时候用cookie+session就比较麻烦,问题在于开发繁琐、安全性和客户体验差、有些前端技术不支持cookie(如微信小程序)

使用 Token 后,服务器端并不会存储 Token,那怎么判断客户端发过来的 Token 是合法有效的呢?答案其实就在 Token 字符串中,其实 Token 并不是一串杂乱无章的字符串,而是通过多种算法拼接组合而成的字符串。

JWT 算法主要分为 3 个部分:header(头信息)playload(消息体)signature(签名)

header 部分指定了该 JWT 使用的签名算法:

header = '{"alg":"HS256","typ":"JWT"}'  

alg属性表示签名的算法(algorithm),默认是 HMAC SHA256(写成 HS256);typ属性表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT

playload 部分表明了 JWT 的意图:
Payload 部分也是一个 JSON 对象,用来存放实际需要传递的数据。JWT 规定了7个官方字段,供选用。

  • iss (issuer):签发人
  • exp (expiration time):过期时间
  • sub (subject):主题
  • aud (audience):受众
  • nbf (Not Before):生效时间
  • iat (Issued At):签发时间
  • jti (JWT ID):编号

除了官方字段,你还可以在这个部分定义私有字段

 payload = '{"loggedInAs":"admin","iat":1422779638}'     //iat 表示令牌生成的时间

注意,JWT 默认是不加密的,任何人都可以读到,所以不要把秘密信息放在这个部分。这个 JSON 对象也要使用 Base64URL 算法转成字符串。

signature 部分为 JWT 的签名,主要为了让 JWT 不能被随意篡改

签名的方法分为两个步骤:

  1. 输入 base64url 编码的 header 部分、 . 、base64url 编码的 playload 部分,输出 unsignedToken。

  2. 输入服务器端私钥、unsignedToken,输出 signature 签名。

    const base64Header = encodeBase64(header)
    const base64Payload = encodeBase64(payload)
    const unsignedToken = `${base64Header}.${base64Payload}`
    const key = '服务器私钥'
    
    signature = HMAC(key, unsignedToken)
    

最后的 Token 计算如下:

const base64Header = encodeBase64(header)
const base64Payload = encodeBase64(payload)
const base64Signature = encodeBase64(signature)

token = `${base64Header}.${base64Payload}.${base64Signature}`

服务器在判断 Token 时:

const [base64Header, base64Payload, base64Signature] = token.split('.')

const signature1 = decodeBase64(base64Signature)
const unsignedToken = `${base64Header}.${base64Payload}`
const signature2 = HMAC('服务器私钥', unsignedToken)

if(signature1 === signature2) {
  return '签名验证成功,token 没有被篡改'
}

const payload =  decodeBase64(base64Payload)
if(new Date() - payload.iat < 'token 有效期'){
  return 'token 有效'
}
  • SSO单点登录

  • OAuth第三方登录

参考文档

浅谈CSRF
前端登录,这一片就够了
登录系统相关知识(JWT、加密算法、cookie、session)

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值