普通的用户认证,登录

基于 session 和基于 token(jwt [json web token]) 的用户认证方式

  要实现用户的登录,在我们这里的前后端分离的开发中和之前基于模板的browser开发是有一定区别的,区别主要在于服务端存放数据与否。

  多数网站用户认证都是基于 session 的,即在服务端存放用户相关的 session 数据,而发给客户端 sesssion_id (其实也是token的一种)存放到 cookie 中,这样用客户端请求时带上 session_id 就可以验证服务器端是否存在 session 数据,以此完成用户认证。

这种认证方式,优点是可以更好的在服务端对会话进行控制,安全性比较高(session_id 随机)。但是服务端需要存储 session 数据(如内存或数据库).缺点是   ①增加维护成本和减弱可扩展性(多台服务器),②存在基于cookie的 CSRF攻击,③原生 app 等前端没有浏览器 的cookie 功能,使用这种服务接口会相对麻烦。

   基于 token 的用户认证是一种服务端无状态的认证方式,服务端不用存放 token 数据。用户验证后,服务端生成一个 token(hash 或 encrypt)发给客户端,客户端可以放到 cookie 或 localStorage 中,每次请求时在 Header 中带上 token ,服务端收到 token 通过验证后即可确认用户身份。这种方式相对 于cookie 的认证方式就简单一些,服务端不用存储认证数据.

相应地具有以下优点:①易维护、扩展性强② token 储存在 localStorage 中可避免 CSRF ③ web 和 app 应用这用接口都比较简单。不过这种方式在加密或解密的时候会有一些性能开销(好像也不是很大),有些对称加密存在安全隐患(aes cbc 字节翻转攻击)。

一、基于session

1. 登录
    * 用户输入账号密码,从客户端传到服务端
    * 服务端效验账号密码是否匹配
    * 匹配时,将用户信息存放到session中。session.setAttribute(user);

当执行其他接口请求时,在服务端判断是否已登录,即查看session中是否存在用户数据。session.getAttribute(user)

2. 忘记密码,回答问题答案,注册用户时,设置的,此时就是回答问题,找回密码
    * 输入用户名,检验是否存在该用户。
    * 找到问题,输入问题答案
    * 回答正确,随机生成一个token,存入缓存中,并传给客户端。
    * 客户端修改密码后,将新密码和token传到服务端。

token的作用:如果答案正确,那么就针对这个用户,把一个token存入缓存中。当该用户想改密码时,将传入的token跟缓存中的token进行比较,如果一致,则认为是该用户在操作。token要过期时间的原因是,这次修改需要保证在一段时间内有效,过期就无效了。
这在互联网上修改密码是一个很常用的做法,例如,忘记密码修改邮件里面给的链接,都会有一个提示,告诉你,这个修改密码的链接在10个小时之内有效,过期请重新获取该链接~

基于session认证所显露的问题

Session: 每个用户经过我们的应用认证之后,我们的应用都要在服务端做一次记录,以方便用户下次请求的鉴别,通常而言session都是保存在内存中,而随着认证用户的增多,服务端的开销会明显增大。

扩展性: 用户认证之后,服务端做认证记录,如果认证的记录被保存在内存中的话,这意味着用户下次请求还必须要请求在这台服务器上,这样才能拿到授权的资源,这样在分布式的应用上,相应的限制了负载均衡器的能力。这也意味着限制了应用的扩展能力。

CSRF: 因为是基于cookie来进行用户识别的, cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击。

二、基于token(jwt)鉴权机制

基于token的鉴权机制类似于http协议也是无状态的,它不需要在服务端去保留用户的认证信息或者会话信息。这就意味着基于token认证机制的应用不需要去考虑用户在哪一台服务器登录了,这就为应用的扩展提供了便利。

流程上是这样的:

    *用户使用用户名密码来请求服务器
   * 服务器进行验证用户的信息
   * 服务器通过验证发送给用户一个token
   * 客户端存储token,并在每次请求时附送上这个token值
   * 服务端验证token值,并返回数据
   * 这个token必须要在每次请求时传递给服务端,它应该保存在请求头里,
   * 另外,服务端要支持CORS(跨来源资源共享)策略,一般我们在服务端这么做就可以了 Access-Control-Allow-Origin:*。*

token的优点
  支持跨域访问: Cookie是不允许垮域访问的,这一点对Token机制是不存在的,前提是传输的用户认证信息通过HTTP头传输。
  无状态(也称:服务端可扩展行):Token机制在服务端不需要存储session信息,因为Token 自身包含了所有登录用户的信息,只需要在客户端的cookie或本地介质存储状态信息。
  更适用CDN: 可以通过内容分发网络请求你服务端的所有资料(如:javascript,HTML,图片等),而你的服务端只要提供API即可。
  去耦: 不需要绑定到一个特定的身份验证方案。Token可以在任何地方生成,只要在你的API被调用的时候,你可以进行Token生成调用即可。
  更适用于移动应用: 当你的客户端是一个原生平台(iOS, Android,Windows 8等)时,Cookie是不被支持的(你需要通过Cookie容器进行处理),这时采用Token认证机制就会简单得多。
  CSRF:因为不再依赖于Cookie,所以你就不需要考虑对CSRF(跨站请求伪造)的防范。
  性能: 一次网络往返时间(通过数据库查询session信息)总比做一次HMACSHA256计算 的Token验证和解析要费时得多。
  不需要为登录页面做特殊处理: 如果你使用Protractor 做功能测试的时候,不再需要为登录页面做特殊处理。
  基于标准化:你的API可以采用标准化的 JSON Web Token (JWT). 这个标准已经存在多个后端库(.NET, Ruby, Java,Python, PHP)和多家公司的支持(如:Firebase,Google, Microsoft)。
      因为json的通用性,所以JWT是可以进行跨语言支持的,像JAVA,JavaScript,NodeJS,PHP等很多语言都可以使用。
      因为有了payload部分,所以JWT可以在自身存储一些其他业务逻辑所必要的非敏感信息。
      便于传输,jwt的构成非常简单,字节占用很小,所以它是非常便于传输的。 它不需要在服务端保存会话信息, 所以它易于应用的扩展。
原文地址:https://www.cnblogs.com/FondWang/p/11670375.html