精华内容
下载资源
问答
  • 链接是查询订单详情,但是单独拿出来放在谷歌浏览器地址栏请求就会出现 token不能为空 尝试使用下面的方法,从cookie里面获得tooken 然后发送请求 结果失败 返回的responseText还是 token不能为空 ``` window...
  • 参数值不匹配

    2020-12-25 19:29:48
    genSession(uid,Username,ShowName,LastIP,LastDate,token,Lstat,kpl='yes') <p>genSession方法定义了9个参数 def genSession(SID,Username,ShowName,LastIP,LastLocation,LastDate,Token,Lstat,kpl): ...
  • 通俗地讲就是验证当前用户的身份,证明“你是你自己”(比如:你每天上下班打卡,都需要通过指纹打卡,当你的指纹和系统里录入的指纹相匹配时,就打卡成功) 互联网中的认证: 用户名密码登录 邮箱发送登录链接 手机...

    原文链接:https://mp.weixin.qq.com/s/gfPmK2IL_E64sDMOEFtPuQ

    什么是认证(Authentication)

    通俗地讲就是验证当前用户的身份,证明“你是你自己”(比如:你每天上下班打卡,都需要通过指纹打卡,当你的指纹和系统里录入的指纹相匹配时,就打卡成功)
    互联网中的认证:
    用户名密码登录
    邮箱发送登录链接
    手机号接收验证码
    只要你能收到邮箱/验证码,就默认你是账号的主人
    什么是授权(Authorization)

    用户授予第三方应用访问该用户某些资源的权限
    你在安装手机应用的时候,APP 会询问是否允许授予权限(访问相册、地理位置等权限)
    你在访问微信小程序时,当登录时,小程序会询问是否允许授予权限(获取昵称、头像、地区、性别等个人信息)
    实现授权的方式有:cookie、session、token、OAuth
    什么是凭证(Credentials)

    实现认证和授权的前提是需要一种媒介(证书) 来标记访问者的身份
    在战国时期,商鞅变法,发明了照身帖。照身帖由官府发放,是一块打磨光滑细密的竹板,上面刻有持有人的头像和籍贯信息。国人必须持有,如若没有就被认为是黑户,或者间谍之类的。
    在现实生活中,每个人都会有一张专属的居民身份证,是用于证明持有人身份的一种法定证件。通过身份证,我们可以办理手机卡/银行卡/个人贷款/交通出行等等,这就是认证的凭证。
    在互联网应用中,一般网站(如掘金)会有两种模式,游客模式和登录模式。游客模式下,可以正常浏览网站上面的文章,一旦想要点赞/收藏/分享文章,就需要登录或者注册账号。当用户登录成功后,服务器会给该用户使用的浏览器颁发一个令牌(token),这个令牌用来表明你的身份,每次浏览器发送请求时会带上这个令牌,就可以使用游客模式下无法使用的功能。
    什么是 Cookie

    HTTP 是无状态的协议(对于事务处理没有记忆能力,每次客户端和服务端会话完成时,服务端不会保存任何会话信息):每个请求都是完全独立的,服务端无法确认当前访问者的身份信息,无法分辨上一次的请求发送者和这一次的发送者是不是同一个人。所以服务器与浏览器为了进行会话跟踪(知道是谁在访问我),就必须主动的去维护一个状态,这个状态用于告知服务端前后两个请求是否来自同一浏览器。而这个状态需要通过 cookie 或者 session 去实现。
    cookie 存储在客户端: cookie 是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。
    cookie 是不可跨域的: 每个 cookie 都会绑定单一的域名,无法在别的域名下获取使用,一级域名和二级域名之间是允许共享使用的(靠的是 domain)。
    cookie 重要的属性

    什么是 Session

    session 是另一种记录服务器和客户端会话状态的机制
    session 是基于 cookie 实现的,session 存储在服务器端,sessionId 会被存储到客户端的cookie 中

    session 认证流程:
    用户第一次请求服务器的时候,服务器根据用户提交的相关信息,创建对应的 Session
    请求返回时将此 Session 的唯一标识信息 SessionID 返回给浏览器
    浏览器接收到服务器返回的 SessionID 信息后,会将此信息存入到 Cookie 中,同时 Cookie 记录此 SessionID 属于哪个域名
    当用户第二次访问服务器的时候,请求会自动判断此域名下是否存在 Cookie 信息,如果存在自动将 Cookie 信息也发送给服务端,服务端会从 Cookie 中获取 SessionID,再根据 SessionID 查找对应的 Session 信息,如果没有找到说明用户没有登录或者登录失效,如果找到 Session 证明用户已经登录可执行后面操作。
    根据以上流程可知,SessionID 是连接 Cookie 和 Session 的一道桥梁,大部分系统也是根据此原理来验证用户登录状态。

    Cookie 和 Session 的区别

    安全性: Session 比 Cookie 安全,Session 是存储在服务器端的,Cookie 是存储在客户端的。
    存取值的类型不同:Cookie 只支持存字符串数据,想要设置其他类型的数据,需要将其转换成字符串,Session 可以存任意数据类型。
    有效期不同: Cookie 可设置为长时间保持,比如我们经常使用的默认登录功能,Session 一般失效时间较短,客户端关闭(默认情况下)或者 Session 超时都会失效。
    存储大小不同: 单个 Cookie 保存的数据不能超过 4K,Session 可存储数据远高于 Cookie,但是当访问量过多,会占用过多的服务器资源。
    什么是 Token(令牌)

    Acesss Token

    访问资源接口(API)时所需要的资源凭证
    简单 token 的组成: uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,token 的前几位以哈希算法压缩成的一定长度的十六进制字符串)
    特点:
    服务端无状态化、可扩展性好
    支持移动端设备
    安全
    支持跨程序调用
    token 的身份验证流程:

    客户端使用用户名跟密码请求登录
    服务端收到请求,去验证用户名与密码
    验证成功后,服务端会签发一个 token 并把这个 token 发送给客户端
    客户端收到 token 以后,会把它存储起来,比如放在 cookie 里或者 localStorage 里
    客户端每次向服务端请求资源的时候需要带着服务端签发的 token
    服务端收到请求,然后去验证客户端请求里面带着的 token ,如果验证成功,就向客户端返回请求的数据
    每一次请求都需要携带 token,需要把 token 放到 HTTP 的 Header 里
    基于 token 的用户认证是一种服务端无状态的认证方式,服务端不用存放 token 数据。用解析 token 的计算时间换取 session 的存储空间,从而减轻服务器的压力,减少频繁的查询数据库
    token 完全由应用管理,所以它可以避开同源策略
    Refresh Token

    另外一种 token——refresh token
    refresh token 是专用于刷新 access token 的 token。如果没有 refresh token,也可以刷新 access token,但每次刷新都要用户输入登录用户名与密码,会很麻烦。有了 refresh token,可以减少这个麻烦,客户端直接用 refresh token 去更新 access token,无需用户进行额外的操作。

    Access Token 的有效期比较短,当 Acesss Token 由于过期而失效时,使用 Refresh Token 就可以获取到新的 Token,如果 Refresh Token 也失效了,用户就只能重新登录了。
    Refresh Token 及过期时间是存储在服务器的数据库中,只有在申请新的 Acesss Token 时才会验证,不会对业务接口响应时间造成影响,也不需要向 Session 一样一直保持在内存中以应对大量的请求。
    Token 和 Session 的区别

    Session 是一种记录服务器和客户端会话状态的机制,使服务端有状态化,可以记录会话信息。而 Token 是令牌,访问资源接口(API)时所需要的资源凭证。Token 使服务端无状态化,不会存储会话信息。
    Session 和 Token 并不矛盾,作为身份认证 Token 安全性比 Session 好,因为每一个请求都有签名还能防止监听以及重放攻击,而 Session 就必须依赖链路层来保障通讯安全了。如果你需要实现有状态的会话,仍然可以增加 Session 来在服务器端保存一些状态。
    所谓 Session 认证只是简单的把 User 信息存储到 Session 里,因为 SessionID 的不可预测性,暂且认为是安全的。而 Token ,如果指的是 OAuth Token 或类似的机制的话,提供的是 认证 和 授权 ,认证是针对用户,授权是针对 App 。其目的是让某 App 有权利访问某用户的信息。这里的 Token 是唯一的。不可以转移到其它 App上,也不可以转到其它用户上。Session 只提供一种简单的认证,即只要有此 SessionID ,即认为有此 User 的全部权利。是需要严格保密的,这个数据应该只保存在站方,不应该共享给其它网站或者第三方 App。所以简单来说:如果你的用户数据可能需要和第三方共享,或者允许第三方调用 API 接口,用 Token 。如果永远只是自己的网站,自己的 App,用什么就无所谓了。
    什么是 JWT

    JSON Web Token(简称 JWT)是目前最流行的跨域认证解决方案。
    是一种认证授权机制。
    JWT 是为了在网络应用环境间传递声明而执行的一种基于 JSON 的开放标准(RFC 7519)。JWT 的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源。比如用在用户登录上。
    可以使用 HMAC 算法或者是 RSA 的公/私秘钥对 JWT 进行签名。因为数字签名的存在,这些传递的信息是可信的。
    阮一峰老师的 JSON Web Token 入门教程 讲的非常通俗易懂,这里就不再班门弄斧了
    生成 JWT

    jwt.io/
    jsonwebtoken.io/
    JWT 的原理

    JWT 认证流程:
    用户输入用户名/密码登录,服务端认证成功后,会返回给客户端一个 JWT
    客户端将 token 保存到本地(通常使用 localstorage,也可以使用 cookie)
    当用户希望访问一个受保护的路由或者资源的时候,需要请求头的 Authorization 字段中使用Bearer 模式添加 JWT,其内容看起来是下面这样
    Authorization: Bearer
    服务端的保护路由将会检查请求头 Authorization 中的 JWT 信息,如果合法,则允许用户的行为
    因为 JWT 是自包含的(内部包含了一些会话信息),因此减少了需要查询数据库的需要
    因为 JWT 并不使用 Cookie 的,所以你可以使用任何域名提供你的 API 服务而不需要担心跨域资源共享问题(CORS)
    因为用户的状态不再存储在服务端的内存中,所以这是一种无状态的认证机制
    JWT 的使用方式

    客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在 localStorage。
    方式一

    当用户希望访问一个受保护的路由或者资源的时候,可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求头信息的 Authorization 字段里,使用 Bearer 模式添加 JWT。
    GET /calendar/v1/events
    Host: api.example.com
    Authorization: Bearer
    用户的状态不会存储在服务端的内存中,这是一种 无状态的认证机制
    服务端的保护路由将会检查请求头 Authorization 中的 JWT 信息,如果合法,则允许用户的行为。
    由于 JWT 是自包含的,因此减少了需要查询数据库的需要
    JWT 的这些特性使得我们可以完全依赖其无状态的特性提供数据 API 服务,甚至是创建一个下载流服务。
    因为 JWT 并不使用 Cookie ,所以你可以使用任何域名提供你的 API 服务而不需要担心跨域资源共享问题(CORS)
    方式二

    跨域的时候,可以把 JWT 放在 POST 请求的数据体里。
    方式三

    通过 URL 传输
    http://www.example.com/user?token=xxx
    项目中使用 JWT

    项目地址:github.com/yjdjiayou/jw

    Token 和 JWT 的区别

    相同:

    都是访问资源的令牌
    都可以记录用户的信息
    都是使服务端无状态化
    都是只有验证成功后,客户端才能访问服务端上受保护的资源
    区别:

    Token:服务端验证客户端发送过来的 Token 时,还需要查询数据库获取用户信息,然后验证 Token 是否有效。
    JWT:将 Token 和 Payload 加密后存储于客户端,服务端只需要使用密钥解密进行校验(校验也是 JWT 自己实现的)即可,不需要查询或者减少查询数据库,因为 JWT 自包含了用户信息和加密的数据。
    常见的前后端鉴权方式

    Session-Cookie
    Token 验证(包括 JWT,SSO)
    OAuth2.0(开放授权)
    常见的加密算法

    哈希算法(Hash Algorithm)又称散列算法、散列函数、哈希函数,是一种从任何一种数据中创建小的数字“指纹”的方法。哈希算法将数据重新打乱混合,重新创建一个哈希值。
    哈希算法主要用来保障数据真实性(即完整性),即发信人将原始消息和哈希值一起发送,收信人通过相同的哈希函数来校验原始数据是否真实。
    哈希算法通常有以下几个特点:
    2 的 128 次方为 340282366920938463463374607431768211456,也就是 10 的 39 次方级别
    2 的 160 次方为 1.4615016373309029182036848327163e+48,也就是 10 的 48 次方级别
    2 的 256 次方为 1.1579208923731619542357098500869 × 10 的 77 次方,也就是 10 的 77 次方
    正像快速:原始数据可以快速计算出哈希值
    逆向困难:通过哈希值基本不可能推导出原始数据
    输入敏感:原始数据只要有一点变动,得到的哈希值差别很大
    冲突避免:很难找到不同的原始数据得到相同的哈希值,宇宙中原子数大约在 10 的 60 次方到 80 次方之间,所以 2 的 256 次方有足够的空间容纳所有的可能,算法好的情况下冲突碰撞的概率很低:
    注意:

    以上不能保证数据被恶意篡改,原始数据和哈希值都可能被恶意篡改,要保证不被篡改,可以使用RSA 公钥私钥方案,再配合哈希值。
    哈希算法主要用来防止计算机传输过程中的错误,早期计算机通过前 7 位数据第 8 位奇偶校验码来保障(12.5% 的浪费效率低),对于一段数据或文件,通过哈希算法生成 128bit 或者 256bit 的哈希值,如果校验有问题就要求重传。
    常见问题

    使用 cookie 时需要考虑的问题

    因为存储在客户端,容易被客户端篡改,使用前需要验证合法性
    不要存储敏感数据,比如用户密码,账户余额
    使用 httpOnly 在一定程度上提高安全性
    尽量减少 cookie 的体积,能存储的数据量不能超过 4kb
    设置正确的 domain 和 path,减少数据传输
    cookie 无法跨域
    一个浏览器针对一个网站最多存 20 个Cookie,浏览器一般只允许存放 300 个Cookie
    移动端对 cookie 的支持不是很好,而 session 需要基于 cookie 实现,所以移动端常用的是 token
    使用 session 时需要考虑的问题

    将 session 存储在服务器里面,当用户同时在线量比较多时,这些 session 会占据较多的内存,需要在服务端定期的去清理过期的 session
    当网站采用集群部署的时候,会遇到多台 web 服务器之间如何做 session 共享的问题。因为 session 是由单个服务器创建的,但是处理用户请求的服务器不一定是那个创建 session 的服务器,那么该服务器就无法拿到之前已经放入到 session 中的登录凭证之类的信息了。
    当多个应用要共享 session 时,除了以上问题,还会遇到跨域问题,因为不同的应用可能部署的主机不一样,需要在各个应用做好 cookie 跨域的处理。
    sessionId 是存储在 cookie 中的,假如浏览器禁止 cookie 或不支持 cookie 怎么办? 一般会把 sessionId 跟在 url 参数后面即重写 url,所以 session 不一定非得需要靠 cookie 实现
    移动端对 cookie 的支持不是很好,而 session 需要基于 cookie 实现,所以移动端常用的是 token
    使用 token 时需要考虑的问题

    如果你认为用数据库来存储 token 会导致查询时间太长,可以选择放在内存当中。比如 redis 很适合你对 token 查询的需求。
    token 完全由应用管理,所以它可以避开同源策略
    token 可以避免 CSRF 攻击(因为不需要 cookie 了)
    移动端对 cookie 的支持不是很好,而 session 需要基于 cookie 实现,所以移动端常用的是 token
    使用 JWT 时需要考虑的问题

    因为 JWT 并不依赖 Cookie 的,所以你可以使用任何域名提供你的 API 服务而不需要担心跨域资源共享问题(CORS)
    JWT 默认是不加密,但也是可以加密的。生成原始 Token 以后,可以用密钥再加密一次。
    JWT 不加密的情况下,不能将秘密数据写入 JWT。
    JWT 不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数。
    JWT 最大的优势是服务器不再需要存储 Session,使得服务器认证鉴权业务可以方便扩展。但这也是 JWT 最大的缺点:由于服务器不需要存储 Session 状态,因此使用过程中无法废弃某个 Token 或者更改 Token 的权限。也就是说一旦 JWT 签发了,到期之前就会始终有效,除非服务器部署额外的逻辑。
    JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。
    JWT 适合一次性的命令认证,颁发一个有效期极短的 JWT,即使暴露了危险也很小,由于每次操作都会生成新的 JWT,因此也没必要保存 JWT,真正实现无状态。
    为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。
    使用加密算法时需要考虑的问题

    绝不要以明文存储密码
    永远使用 哈希算法 来处理密码,绝不要使用 Base64 或其他编码方式来存储密码,这和以明文存储密码是一样的,使用哈希,而不要使用编码。编码以及加密,都是双向的过程,而密码是保密的,应该只被它的所有者知道, 这个过程必须是单向的。哈希正是用于做这个的,从来没有解哈希这种说法, 但是编码就存在解码,加密就存在解密。
    绝不要使用弱哈希或已被破解的哈希算法,像 MD5 或 SHA1 ,只使用强密码哈希算法。
    绝不要以明文形式显示或发送密码,即使是对密码的所有者也应该这样。如果你需要 “忘记密码” 的功能,可以随机生成一个新的 一次性的(这点很重要)密码,然后把这个密码发送给用户。
    分布式架构下 session 共享方案

    1. session 复制

    任何一个服务器上的 session 发生改变(增删改),该节点会把这个 session 的所有内容序列化,然后广播给所有其它节点,不管其他服务器需不需要 session ,以此来保证 session 同步
    优点: 可容错,各个服务器间 session 能够实时响应。
    缺点: 会对网络负荷造成一定压力,如果 session 量大的话可能会造成网络堵塞,拖慢服务器性能。

    2. 粘性 session /IP 绑定策略

    采用 Ngnix 中的 ip_hash 机制,将某个 ip的所有请求都定向到同一台服务器上,即将用户与服务器绑定。 用户第一次请求时,负载均衡器将用户的请求转发到了 A 服务器上,如果负载均衡器设置了粘性 session 的话,那么用户以后的每次请求都会转发到 A 服务器上,相当于把用户和 A 服务器粘到了一块,这就是粘性 session 机制。
    优点: 简单,不需要对 session 做任何处理。
    缺点: 缺乏容错性,如果当前访问的服务器发生故障,用户被转移到第二个服务器上时,他的 session 信息都将失效。
    适用场景: 发生故障对客户产生的影响较小;服务器发生故障是低概率事件 。
    实现方式: 以 Nginx 为例,在 upstream 模块配置 ip_hash 属性即可实现粘性 session。

    3. session 共享(常用)

    使用分布式缓存方案比如 Memcached 、Redis 来缓存 session,但是要求 Memcached 或 Redis 必须是集群
    把 session 放到 Redis 中存储,虽然架构上变得复杂,并且需要多访问一次 Redis ,但是这种方案带来的好处也是很大的:
    实现了 session 共享;
    可以水平扩展(增加 Redis 服务器);
    服务器重启 session 不丢失(不过也要注意 session 在 Redis 中的刷新/失效机制);
    不仅可以跨服务器 session 共享,甚至可以跨平台(例如网页端和 APP 端)

    4. session 持久化

    将 session 存储到数据库中,保证 session 的持久化
    优点: 服务器出现问题,session 不会丢失
    缺点: 如果网站的访问量很大,把 session 存储到数据库中,会对数据库造成很大压力,还需要增加额外的开销维护数据库。

    只要关闭浏览器 ,session 真的就消失了?

    不对。对 session 来说,除非程序通知服务器删除一个 session,否则服务器会一直保留,程序一般都是在用户做 log off 的时候发个指令去删除 session。
    然而浏览器从来不会主动在关闭之前通知服务器它将要关闭,因此服务器根本不会有机会知道浏览器已经关闭,之所以会有这种错觉,是大部分 session 机制都使用会话 cookie 来保存 session id,而关闭浏览器后这个 session id 就消失了,再次连接服务器时也就无法找到原来的 session。如果服务器设置的 cookie 被保存在硬盘上,或者使用某种手段改写浏览器发出的 HTTP 请求头,把原来的 session id 发送给服务器,则再次打开浏览器仍然能够打开原来的 session。
    恰恰是由于关闭浏览器不会导致 session 被删除,迫使服务器为 session 设置了一个失效时间,当距离客户端上一次使用 session 的时间超过这个失效时间时,服务器就认为客户端已经停止了活动,才会把 session 删除以节省存储空间。

    展开全文
  • 什么是认证(Authentication)通俗地讲就是验证当前用户的身份,证明“你是你自己”(比如:你每天上下班打卡,都需要通过指纹打卡,当你的指纹和系统里录入的指纹相匹配时,就打卡成功)互联网中的认证:用户名密码...

    什么是认证(Authentication)

    • 通俗地讲就是验证当前用户的身份,证明“你是你自己”(比如:你每天上下班打卡,都需要通过指纹打卡,当你的指纹和系统里录入的指纹相匹配时,就打卡成功)
    • 互联网中的认证:
      • 用户名密码登录
      • 邮箱发送登录链接
      • 手机号接收验证码
      • 只要你能收到邮箱/验证码,就默认你是账号的主人

    什么是授权(Authorization)

    • 用户授予第三方应用访问该用户某些资源的权限
      • 你在安装手机应用的时候,APP 会询问是否允许授予权限(访问相册、地理位置等权限)
      • 你在访问微信小程序时,当登录时,小程序会询问是否允许授予权限(获取昵称、头像、地区、性别等个人信息)
    • 实现授权的方式有:cookie、session、token、OAuth

    什么是凭证(Credentials)

    • 实现认证和授权的前提是需要一种媒介(证书) 来标记访问者的身份
      • 在战国时期,商鞅变法,发明了照身帖。照身帖由官府发放,是一块打磨光滑细密的竹板,上面刻有持有人的头像和籍贯信息。国人必须持有,如若没有就被认为是黑户,或者间谍之类的。
      • 在现实生活中,每个人都会有一张专属的居民身份证,是用于证明持有人身份的一种法定证件。通过身份证,我们可以办理手机卡/银行卡/个人贷款/交通出行等等,这就是认证的凭证。
      • 在互联网应用中,一般网站(如掘金)会有两种模式,游客模式和登录模式。游客模式下,可以正常浏览网站上面的文章,一旦想要点赞/收藏/分享文章,就需要登录或者注册账号。当用户登录成功后,服务器会给该用户使用的浏览器颁发一个令牌(token),这个令牌用来表明你的身份,每次浏览器发送请求时会带上这个令牌,就可以使用游客模式下无法使用的功能。

    什么是 Cookie

    • HTTP 是无状态的协议(对于事务处理没有记忆能力,每次客户端和服务端会话完成时,服务端不会保存任何会话信息):每个请求都是完全独立的,服务端无法确认当前访问者的身份信息,无法分辨上一次的请求发送者和这一次的发送者是不是同一个人。所以服务器与浏览器为了进行会话跟踪(知道是谁在访问我),就必须主动的去维护一个状态,这个状态用于告知服务端前后两个请求是否来自同一浏览器。而这个状态需要通过 cookie 或者 session 去实现。
    • cookie 存储在客户端: cookie 是服务器发送到用户浏览器并保存在本地的一小块数据,它会在浏览器下次向同一服务器再发起请求时被携带并发送到服务器上。
    • cookie 是不可跨域的: 每个 cookie 都会绑定单一的域名,无法在别的域名下获取使用,一级域名和二级域名之间是允许共享使用的靠的是 domain)

    cookie 重要的属性

    2c825ec9efaa01934879728341164441.png

    什么是 Session

    • session 是另一种记录服务器和客户端会话状态的机制
    • session 是基于 cookie 实现的,session 存储在服务器端,sessionId 会被存储到客户端的cookie 中
    • session 认证流程:
      • 用户第一次请求服务器的时候,服务器根据用户提交的相关信息,创建对应的 Session
      • 请求返回时将此 Session 的唯一标识信息 SessionID 返回给浏览器
      • 浏览器接收到服务器返回的 SessionID 信息后,会将此信息存入到 Cookie 中,同时 Cookie 记录此 SessionID 属于哪个域名
      • 当用户第二次访问服务器的时候,请求会自动判断此域名下是否存在 Cookie 信息,如果存在自动将 Cookie 信息也发送给服务端,服务端会从 Cookie 中获取 SessionID,再根据 SessionID 查找对应的 Session 信息,如果没有找到说明用户没有登录或者登录失效,如果找到 Session 证明用户已经登录可执行后面操作。

    根据以上流程可知,SessionID 是连接 Cookie 和 Session 的一道桥梁,大部分系统也是根据此原理来验证用户登录状态。

    Cookie 和 Session 的区别

    • 安全性: Session 比 Cookie 安全,Session 是存储在服务器端的,Cookie 是存储在客户端的。
    • 存取值的类型不同:Cookie 只支持存字符串数据,想要设置其他类型的数据,需要将其转换成字符串,Session 可以存任意数据类型。
    • 有效期不同: Cookie 可设置为长时间保持,比如我们经常使用的默认登录功能,Session 一般失效时间较短,客户端关闭(默认情况下)或者 Session 超时都会失效。
    • 存储大小不同: 单个 Cookie 保存的数据不能超过 4K,Session 可存储数据远高于 Cookie,但是当访问量过多,会占用过多的服务器资源。

    什么是 Token(令牌)

    Acesss Token

    • 访问资源接口(API)时所需要的资源凭证
    • 简单 token 的组成: uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,token 的前几位以哈希算法压缩成的一定长度的十六进制字符串)
    • 特点:
      • 服务端无状态化、可扩展性好
      • 支持移动端设备
      • 安全
      • 支持跨程序调用
    • token 的身份验证流程:

    c7a7265b4db6225d05bd5b42c2fd3cbb.png
    1. 客户端使用用户名跟密码请求登录
    2. 服务端收到请求,去验证用户名与密码
    3. 验证成功后,服务端会签发一个 token 并把这个 token 发送给客户端
    4. 客户端收到 token 以后,会把它存储起来,比如放在 cookie 里或者 localStorage 里
    5. 客户端每次向服务端请求资源的时候需要带着服务端签发的 token
    6. 服务端收到请求,然后去验证客户端请求里面带着的 token ,如果验证成功,就向客户端返回请求的数据
    • 每一次请求都需要携带 token,需要把 token 放到 HTTP 的 Header 里
    • 基于 token 的用户认证是一种服务端无状态的认证方式,服务端不用存放 token 数据。用解析 token 的计算时间换取 session 的存储空间,从而减轻服务器的压力,减少频繁的查询数据库
    • token 完全由应用管理,所以它可以避开同源策略

    Refresh Token

    • 另外一种 token——refresh token
    • refresh token 是专用于刷新 access token 的 token。如果没有 refresh token,也可以刷新 access token,但每次刷新都要用户输入登录用户名与密码,会很麻烦。有了 refresh token,可以减少这个麻烦,客户端直接用 refresh token 去更新 access token,无需用户进行额外的操作。

    4080d095339669cc6116ce7f765129a2.png
    • Access Token 的有效期比较短,当 Acesss Token 由于过期而失效时,使用 Refresh Token 就可以获取到新的 Token,如果 Refresh Token 也失效了,用户就只能重新登录了。
    • Refresh Token 及过期时间是存储在服务器的数据库中,只有在申请新的 Acesss Token 时才会验证,不会对业务接口响应时间造成影响,也不需要向 Session 一样一直保持在内存中以应对大量的请求。

    Token 和 Session 的区别

    • Session 是一种记录服务器和客户端会话状态的机制,使服务端有状态化,可以记录会话信息。而 Token 是令牌访问资源接口(API)时所需要的资源凭证。Token 使服务端无状态化,不会存储会话信息。
    • Session 和 Token 并不矛盾,作为身份认证 Token 安全性比 Session 好,因为每一个请求都有签名还能防止监听以及重放攻击,而 Session 就必须依赖链路层来保障通讯安全了。如果你需要实现有状态的会话,仍然可以增加 Session 来在服务器端保存一些状态。
    • 所谓 Session 认证只是简单的把 User 信息存储到 Session 里,因为 SessionID 的不可预测性,暂且认为是安全的。而 Token ,如果指的是 OAuth Token 或类似的机制的话,提供的是 认证 和 授权 ,认证是针对用户,授权是针对 App 。其目的是让某 App 有权利访问某用户的信息。这里的 Token 是唯一的。不可以转移到其它 App上,也不可以转到其它用户上。Session 只提供一种简单的认证,即只要有此 SessionID ,即认为有此 User 的全部权利。是需要严格保密的,这个数据应该只保存在站方,不应该共享给其它网站或者第三方 App。所以简单来说:如果你的用户数据可能需要和第三方共享,或者允许第三方调用 API 接口,用 Token 。如果永远只是自己的网站,自己的 App,用什么就无所谓了。

    什么是 JWT

    • JSON Web Token(简称 JWT)是目前最流行的跨域认证解决方案。
    • 是一种认证授权机制
    • JWT 是为了在网络应用环境间传递声明而执行的一种基于 JSON 的开放标准(RFC 7519)。JWT 的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源。比如用在用户登录上。
    • 可以使用 HMAC 算法或者是 RSA 的公/私秘钥对 JWT 进行签名。因为数字签名的存在,这些传递的信息是可信的。

    8098e41ace3b27e1103d64b7850b97ae.png

    JWT 的原理

    8098e41ace3b27e1103d64b7850b97ae.png

    JWT 认证流程:

      • 用户输入用户名/密码登录,服务端认证成功后,会返回给客户端一个 JWT
      • 客户端将 token 保存到本地(通常使用 localstorage,也可以使用 cookie)
      • 当用户希望访问一个受保护的路由或者资源的时候,需要请求头的 Authorization 字段中使用Bearer 模式添加 JWT,其内容看起来是下面这样
    Authorization: Bearer <token>
    • 服务端的保护路由将会检查请求头 Authorization 中的 JWT 信息,如果合法,则允许用户的行为
    • 因为 JWT 是自包含的(内部包含了一些会话信息),因此减少了需要查询数据库的需要
    • 因为 JWT 并不使用 Cookie 的,所以你可以使用任何域名提供你的 API 服务而不需要担心跨域资源共享问题(CORS)
    • 因为用户的状态不再存储在服务端的内存中,所以这是一种无状态的认证机制

    JWT 的使用方式

    • 客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在 localStorage。

    方式一

    • 当用户希望访问一个受保护的路由或者资源的时候,可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求头信息的 Authorization 字段里,使用 Bearer 模式添加 JWT。
      用户的状态不会存储在服务端的内存中,这是一种 无状态的认证机制
    • 服务端的保护路由将会检查请求头 Authorization 中的 JWT 信息,如果合法,则允许用户的行为。
    • 由于 JWT 是自包含的,因此减少了需要查询数据库的需要
    • JWT 的这些特性使得我们可以完全依赖其无状态的特性提供数据 API 服务,甚至是创建一个下载流服务。
    • 因为 JWT 并不使用 Cookie ,所以你可以使用任何域名提供你的 API 服务而不需要担心跨域资源共享问题(CORS)

    方式二

    • 跨域的时候,可以把 JWT 放在 POST 请求的数据体里。

    方式三

    • 通过 URL 传输

    Token 和 JWT 的区别

    相同:

    • 都是访问资源的令牌
    • 都可以记录用户的信息
    • 都是使服务端无状态化
    • 都是只有验证成功后,客户端才能访问服务端上受保护的资源

    区别:

    • Token:服务端验证客户端发送过来的 Token 时,还需要查询数据库获取用户信息,然后验证 Token 是否有效。
    • JWT:将 Token 和 Payload 加密后存储于客户端,服务端只需要使用密钥解密进行校验(校验也是 JWT 自己实现的)即可,不需要查询或者减少查询数据库,因为 JWT 自包含了用户信息和加密的数据。

    常见的前后端鉴权方式

    1. Session-Cookie
    2. Token 验证(包括 JWT,SSO)
    3. OAuth2.0(开放授权)

    常见的加密算法

    4566dd71cf76166d818367f2bfff33bf.png
    • 哈希算法(Hash Algorithm)又称散列算法、散列函数、哈希函数,是一种从任何一种数据中创建小的数字“指纹”的方法。哈希算法将数据重新打乱混合,重新创建一个哈希值。
    • 哈希算法主要用来保障数据真实性(即完整性),即发信人将原始消息和哈希值一起发送,收信人通过相同的哈希函数来校验原始数据是否真实。
    • 哈希算法通常有以下几个特点:
      • 2 的 128 次方为 340282366920938463463374607431768211456,也就是 10 的 39 次方级别
      • 2 的 160 次方为 1.4615016373309029182036848327163e+48,也就是 10 的 48 次方级别
      • 2 的 256 次方为 1.1579208923731619542357098500869 × 10 的 77 次方,也就是 10 的 77 次方
      • 正像快速:原始数据可以快速计算出哈希值
      • 逆向困难:通过哈希值基本不可能推导出原始数据
      • 输入敏感:原始数据只要有一点变动,得到的哈希值差别很大
      • 冲突避免:很难找到不同的原始数据得到相同的哈希值,宇宙中原子数大约在 10 的 60 次方到 80 次方之间,所以 2 的 256 次方有足够的空间容纳所有的可能,算法好的情况下冲突碰撞的概率很低:

    注意:

    1. 以上不能保证数据被恶意篡改,原始数据和哈希值都可能被恶意篡改,要保证不被篡改,可以使用RSA 公钥私钥方案,再配合哈希值。
    2. 哈希算法主要用来防止计算机传输过程中的错误,早期计算机通过前 7 位数据第 8 位奇偶校验码来保障(12.5% 的浪费效率低),对于一段数据或文件,通过哈希算法生成 128bit 或者 256bit 的哈希值,如果校验有问题就要求重传。

    常见问题

    使用 cookie 时需要考虑的问题

    • 因为存储在客户端,容易被客户端篡改,使用前需要验证合法性
    • 不要存储敏感数据,比如用户密码,账户余额
    • 使用 httpOnly 在一定程度上提高安全性
    • 尽量减少 cookie 的体积,能存储的数据量不能超过 4kb
    • 设置正确的 domain 和 path,减少数据传输
    • cookie 无法跨域
    • 一个浏览器针对一个网站最多存 20 个Cookie,浏览器一般只允许存放 300 个Cookie
    • 移动端对 cookie 的支持不是很好,而 session 需要基于 cookie 实现,所以移动端常用的是 token

    使用 session 时需要考虑的问题

    • 将 session 存储在服务器里面,当用户同时在线量比较多时,这些 session 会占据较多的内存,需要在服务端定期的去清理过期的 session
    • 当网站采用集群部署的时候,会遇到多台 web 服务器之间如何做 session 共享的问题。因为 session 是由单个服务器创建的,但是处理用户请求的服务器不一定是那个创建 session 的服务器,那么该服务器就无法拿到之前已经放入到 session 中的登录凭证之类的信息了。
    • 当多个应用要共享 session 时,除了以上问题,还会遇到跨域问题,因为不同的应用可能部署的主机不一样,需要在各个应用做好 cookie 跨域的处理。
    • sessionId 是存储在 cookie 中的,假如浏览器禁止 cookie 或不支持 cookie 怎么办? 一般会把 sessionId 跟在 url 参数后面即重写 url,所以 session 不一定非得需要靠 cookie 实现
    • 移动端对 cookie 的支持不是很好,而 session 需要基于 cookie 实现,所以移动端常用的是 token

    使用 token 时需要考虑的问题

    • 如果你认为用数据库来存储 token 会导致查询时间太长,可以选择放在内存当中。比如 redis 很适合你对 token 查询的需求。
    • token 完全由应用管理,所以它可以避开同源策略
    • token 可以避免 CSRF 攻击(因为不需要 cookie 了)
    • 移动端对 cookie 的支持不是很好,而 session 需要基于 cookie 实现,所以移动端常用的是 token

    使用 JWT 时需要考虑的问题

    • 因为 JWT 并不依赖 Cookie 的,所以你可以使用任何域名提供你的 API 服务而不需要担心跨域资源共享问题(CORS)
    • JWT 默认是不加密,但也是可以加密的。生成原始 Token 以后,可以用密钥再加密一次。
    • JWT 不加密的情况下,不能将秘密数据写入 JWT。
    • JWT 不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数。
    • JWT 最大的优势是服务器不再需要存储 Session,使得服务器认证鉴权业务可以方便扩展。但这也是 JWT 最大的缺点:由于服务器不需要存储 Session 状态,因此使用过程中无法废弃某个 Token 或者更改 Token 的权限。也就是说一旦 JWT 签发了,到期之前就会始终有效,除非服务器部署额外的逻辑。
    • JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。
    • JWT 适合一次性的命令认证,颁发一个有效期极短的 JWT,即使暴露了危险也很小,由于每次操作都会生成新的 JWT,因此也没必要保存 JWT,真正实现无状态。
    • 为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。

    使用加密算法时需要考虑的问题

    • 绝不要以明文存储密码
    • 永远使用 哈希算法 来处理密码,绝不要使用 Base64 或其他编码方式来存储密码,这和以明文存储密码是一样的,使用哈希,而不要使用编码。编码以及加密,都是双向的过程,而密码是保密的,应该只被它的所有者知道, 这个过程必须是单向的。哈希正是用于做这个的,从来没有解哈希这种说法, 但是编码就存在解码,加密就存在解密。
    • 绝不要使用弱哈希或已被破解的哈希算法,像 MD5 或 SHA1 ,只使用强密码哈希算法。
    • 绝不要以明文形式显示或发送密码,即使是对密码的所有者也应该这样。如果你需要 “忘记密码” 的功能,可以随机生成一个新的 一次性的(这点很重要)密码,然后把这个密码发送给用户。

    分布式架构下 session 共享方案

    1. session 复制

    • 任何一个服务器上的 session 发生改变(增删改),该节点会把这个 session 的所有内容序列化,然后广播给所有其它节点,不管其他服务器需不需要 session ,以此来保证 session 同步

    优点: 可容错,各个服务器间 session 能够实时响应。缺点: 会对网络负荷造成一定压力,如果 session 量大的话可能会造成网络堵塞,拖慢服务器性能。

    2. 粘性 session /IP 绑定策略

    • 采用 Ngnix 中的 ip_hash 机制,将某个 ip的所有请求都定向到同一台服务器上,即将用户与服务器绑定。 用户第一次请求时,负载均衡器将用户的请求转发到了 A 服务器上,如果负载均衡器设置了粘性 session 的话,那么用户以后的每次请求都会转发到 A 服务器上,相当于把用户和 A 服务器粘到了一块,这就是粘性 session 机制。

    优点: 简单,不需要对 session 做任何处理。缺点: 缺乏容错性,如果当前访问的服务器发生故障,用户被转移到第二个服务器上时,他的 session 信息都将失效。适用场景: 发生故障对客户产生的影响较小;服务器发生故障是低概率事件。实现方式: 以 Nginx 为例,在 upstream 模块配置 ip_hash 属性即可实现粘性 session。

    3. session 共享(常用)

    • 使用分布式缓存方案比如 Memcached 、Redis 来缓存 session,但是要求 Memcached 或 Redis 必须是集群
    • 把 session 放到 Redis 中存储,虽然架构上变得复杂,并且需要多访问一次 Redis ,但是这种方案带来的好处也是很大的:
      • 实现了 session 共享;
      • 可以水平扩展(增加 Redis 服务器);
      • 服务器重启 session 不丢失(不过也要注意 session 在 Redis 中的刷新/失效机制);
      • 不仅可以跨服务器 session 共享,甚至可以跨平台(例如网页端和 APP 端)

    b53f98978b9dc1ad2a869f8033602957.png

    4. session 持久化

    • 将 session 存储到数据库中,保证 session 的持久化

    优点: 服务器出现问题,session 不会丢失缺点: 如果网站的访问量很大,把 session 存储到数据库中,会对数据库造成很大压力,还需要增加额外的开销维护数据库。

    只要关闭浏览器 ,session 真的就消失了?

    不对。对 session 来说,除非程序通知服务器删除一个 session,否则服务器会一直保留,程序一般都是在用户做 log off 的时候发个指令去删除 session。
    然而浏览器从来不会主动在关闭之前通知服务器它将要关闭,因此服务器根本不会有机会知道浏览器已经关闭,之所以会有这种错觉,是大部分 session 机制都使用会话 cookie 来保存 session id,而关闭浏览器后这个 session id 就消失了,再次连接服务器时也就无法找到原来的 session。如果服务器设置的 cookie 被保存在硬盘上,或者使用某种手段改写浏览器发出的 HTTP 请求头,把原来的 session id 发送给服务器,则再次打开浏览器仍然能够打开原来的 session。
    恰恰是由于关闭浏览器不会导致 session 被删除,迫使服务器为 session 设置了一个失效时间,当距离客户端上一次使用 session 的时间超过这个失效时间时,服务器就认为客户端已经停止了活动,才会把 session 删除以节省存储空间。

    展开全文
  • 写这一篇文章的来源是因为某一天的我被面试官提问:让你设计一个登录页面,你会如何设计?我当时的脑子只有???...我还没领悟到面试官想让我回答的是Token。。。。参考链接:https://juejin.i...

    写这一篇文章的来源是因为某一天的我被面试官提问:让你设计一个登录页面,你会如何设计?

    我当时的脑子只有???

    不就是提交账号、密码给后台就搞定了呢?

    不可能那么简单,我弱弱的想,难道要对密码加密??

    之后他继续提问,当你登录成功后,去请求购物车时,后台为什么会返回的是你的购物车,而不是别人的?

    不是匹配用户id吗??我还没领悟到面试官想让我回答的是Token。。。。

    参考链接:https://juejin.im/post/5a6c60166fb9a01caf37a5e5

    什么是Token?

    token的意思是“令牌”,是服务端生成的一串字符串,作为客户端进行请求的一个标识。

    当用户第一次登录后,服务器生成一个token并将此token返回给客户端,以后客户端只需带上这个token前来请求数据即可,无需再次带上用户名和密码。

    简单token的组成;uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,token的前几位以哈希算法压缩成的一定长度的十六进制字符串。为防止token泄露)。

    为什么要用Token?

    Token 完全由应用管理,所以它可以避开同源策略

    Token 可以避免 CSRF 攻击

    Token 可以是无状态的,可以在多个服务间共享

    基于token机制的身份认证

    使用token机制的身份验证方法,在服务器端不需要存储用户的登录记录。大概的流程:

    客户端使用用户名和密码请求登录。

    服务端收到请求,验证用户名和密码。

    验证成功后,服务端会生成一个token,然后把这个token发送给客户端。

    客户端收到token后把它存储起来,可以放在cookie或者Local Storage(本地存储)里。

    客户端每次向服务端发送请求的时候都需要带上服务端发给的token。

    服务端收到请求,然后去验证客户端请求里面带着token,如果验证成功,就向客户端返回请求的数据。(如果这个 Token 在服务端持久化(比如存入数据库),那它就是一个永久的身份令牌。)

    Token需要设置有效期吗?

    对于这个问题,我们不妨先看两个例子。一个例子是登录密码,一般要求定期改变密码,以防止泄漏,所以密码是有有效期的;另一个例子是安全证书。SSL 安全证书都有有效期,目的是为了解决吊销的问题。所以无论是从安全的角度考虑,还是从吊销的角度考虑,Token 都需要设有效期。

    那么有效期多长合适呢?

    只能说,根据系统的安全需要,尽可能的短,但也不能短得离谱——想像一下手机的自动熄屏时间,如果设置为 10 秒钟无操作自动熄屏,再次点亮需要输入密码,会不会疯?

    然后新问题产生了,如果用户在正常操作的过程中,Token 过期失效了,要求用户重新登录……用户体验岂不是很糟糕?

    解决Token失效的问题

    一种方案是在服务器端保存 Token 状态,用户每次操作都会自动刷新(推迟) Token 的过期时间——Session 就是采用这种策略来保持用户登录状态的。然而仍然存在这样一个问题,在前后端分离、单页 App 这些情况下,每秒种可能发起很多次请求,每次都去刷新过期时间会产生非常大的代价。如果 Token 的过期时间被持久化到数据库或文件,代价就更大了。所以通常为了提升效率,减少消耗,会把 Token 的过期时保存在缓存或者内存中。

    另一种方案,使用 Refresh Token,它可以避免频繁的读写操作。这种方案中,服务端不需要刷新 Token 的过期时间,一旦 Token 过期,就反馈给前端,前端使用 Refresh Token 申请一个全新 Token 继续使用。这种方案中,服务端只需要在客户端请求更新 Token 的时候对 Refresh Token 的有效性进行一次检查,大大减少了更新有效期的操作,也就避免了频繁读写。当然 Refresh Token 也是有有效期的,但是这个有效期就可以长一点了,比如,以天为单位的时间。

    使用Token和RefreshToken的时序图如下:

    上面的时序图中并未提到 Refresh Token 过期怎么办。不过很显然,Refresh Token 既然已经过期,就该要求用户重新登录了。

    当然还可以把这个机制设计得更复杂一些,比如,Refresh Token 每次使用的时候,都更新它的过期时间,直到与它的创建时间相比,已经超过了非常长的一段时间(比如三个月),这等于是在相当长一段时间内允许 Refresh Token 自动续期。

    到目前为止,Token 都是有状态的,即在服务端需要保存并记录相关属性。那说好的无状态呢,怎么实现?

    无状态Token

    如果我们把所有状态信息都附加在 Token 上,服务器就可以不保存。但是服务端仍然需要认证 Token 有效。不过只要服务端能确认是自己签发的 Token,而且其信息未被改动过,那就可以认为 Token 有效——“签名”可以作此保证。平时常说的签名都存在一方签发,另一方验证的情况,所以要使用非对称加密算法。但是在这里,签发和验证都是同一方,所以对称加密算法就能达到要求,而对称算法比非对称算法要快得多(可达数十倍差距)。更进一步思考,对称加密算法除了加密,还带有还原加密内容的功能,而这一功能在对 Token 签名时并无必要——既然不需要解密,摘要(散列)算法就会更快。可以指定密码的散列算法,自然是 HMAC。

    上面说了这么多,还需要自己去实现吗?不用!JWT 已经定义了详细的规范,而且有各种语言的若干实现。

    不过在使用无状态 Token 的时候在服务端会有一些变化,服务端虽然不保存有效的 Token 了,却需要保存未到期却已注销的 Token。如果一个 Token 未到期就被用户主动注销,那么服务器需要保存这个被注销的 Token,以便下次收到使用这个仍在有效期内的 Token 时判其无效。有没有感到一点沮丧?

    在前端可控的情况下(比如前端和服务端在同一个项目组内),可以协商:前端一但注销成功,就丢掉本地保存(比如保存在内存、LocalStorage 等)的 Token 和 Refresh Token。基于这样的约定,服务器就可以假设收到的 Token 一定是没注销的(因为注销之后前端就不会再使用了)。

    如果前端不可控的情况,仍然可以进行上面的假设,但是这种情况下,需要尽量缩短 Token 的有效期,而且必须在用户主动注销的情况下让 Refresh Token 无效。这个操作存在一定的安全漏洞,因为用户会认为已经注销了,实际上在较短的一段时间内并没有注销。如果应用设计中,这点漏洞并不会造成什么损失,那采用这种策略就是可行的。

    在使用无状态 Token 的时候,有两点需要注意:

    Refresh Token 有效时间较长,所以它应该在服务器端有状态,以增强安全性,确保用户注销时可控

    应该考虑使用二次认证来增强敏感操作的安全性

    到此,关于 Token 的话题似乎差不多了——然而并没有,上面说的只是认证服务和业务服务集成在一起的情况,如果是分

    分离认证服务

    当 Token 无状态之后,单点登录就变得容易了。前端拿到一个有效的 Token,它就可以在任何同一体系的服务上认证通过——只要它们使用同样的密钥和算法来认证 Token 的有效性。就样这样:

    当然,如果 Token 过期了,前端仍然需要去认证服务更新 Token:

    可见,虽然认证和业务分离了,实际即并没产生多大的差异。当然,这是建立在认证服务器信任业务服务器的前提下,因为认证服务器产生 Token 的密钥和业务服务器认证 Token 的密钥和算法相同。换句话说,业务服务器同样可以创建有效的 Token。

    如果业务服务器不能被信任,该怎么办?

    不受信的业务服务器

    遇到不受信的业务服务器时,很容易想到的办法是使用不同的密钥。认证服务器使用密钥1签发,业务服务器使用密钥2验证——这是典型非对称加密签名的应用场景。认证服务器自己使用私钥对 Token 签名,公开公钥。信任这个认证服务器的业务服务器保存公钥,用于验证签名。幸好,JWT 不仅可以使用 HMAC 签名,也可以使用 RSA(一种非对称加密算法)签名。

    不过,当业务服务器已经不受信任的时候,多个业务服务器之间使用相同的 Token 对用户来说是不安全的。因为任何一个服务器拿到 Token 都可以仿冒用户去另一个服务器处理业务……悲剧随时可能发生。

    为了防止这种情况发生,就需要在认证服务器产生 Token 的时候,把使用该 Token 的业务服务器的信息记录在 Token 中,这样当另一个业务服务器拿到这个 Token 的时候,发现它并不是自己应该验证的 Token,就可以直接拒绝。

    现在,认证服务器不信任业务服务器,业务服务器相互也不信任,但前端是信任这些服务器的——如果前端不信任,就不会拿 Token 去请求验证。那么为什么会信任?可能是因为这些是同一家公司或者同一个项目中提供的若干服务构成的服务体系。

    但是,前端信任不代表用户信任。如果 Token 不没有携带用户隐私(比如姓名),那么用户不会关心信任问题。但如果 Token 含有用户隐私的时候,用户得关心信任问题了。这时候认证服务就不得不再啰嗦一些,当用户请求 Token 的时候,问上一句,你真的要授权给某某某业务服务吗?而这个“某某某”,用户怎么知道它是不是真的“某某某”呢?用户当然不知道,甚至认证服务也不知道,因为公钥已经公开了,任何一个业务都可以声明自己是“某某某”。

    为了得到用户的信任,认证服务就不得不帮助用户来鉴别业务服务。所以,认证服器决定不公开公钥,而是要求业务服务先申请注册并通过审核。只有通过审核的业务服务器才能得到认证服务为它创建的,仅供它使用的公钥。如果该业务服务泄漏公钥带来风险,由该业务服务自行承担。现在认证服务可以清楚的告诉用户,“某某某”服务是什么了。如果用户还是不够信任,认证服务甚至可以问,某某某业务服务需要请求 A、B、C 三项个人数据,其中 A 是必须的,不然它不工作,是否允许授权?如果你授权,我就把你授权的几项数据加密放在 Token 中……

    废话了这么多,有没有似曾相识……对了,这类似开放式 API 的认证过程。

    e...看了那么多,我希望下次面试官问我登录页面怎么设计的时候,我可以说一番长篇大论哈哈哈。

    展开全文
  • PHP token令牌

    2017-12-21 01:49:14
    避免重复提交数据. 检查来路,是否是外部提交 匹配要执行的动作(如果有多个逻辑在同一个页面实现,比如...token不可明文,如果是明文,那就太危险了,所以要采用一定的加密方式.密文要可逆.我的算法很白痴,所以采用了网上...

    PHP Token(令牌)设计 设计目标:

    避免重复提交数据. 检查来路,是否是外部提交 匹配要执行的动作(如果有多个逻辑在同一个页面实现,比如新增,删除,修改放到一个PHP文件里操作) 这里所说的token是在页面显示的时候,写到FORM的一个隐藏表单项(type=hidden).。token不可明文,如果是明文,那就太危险了,所以要采用一定的加密方式.密文要可逆.我的算法很白痴,所以采用了网上一个现成的方法.

    PHP Token(令牌)-使用场景

    怎样避免重复提交?

    在SESSION里要存一个数组,这个数组存放以经成功提交的token.在后台处理时,先判断这个token是否在这个数组里,如果存在,说明是重复提交

    如何检查来路?

    可选项,这个token在生成的时候,加入了当前的session_id.如果别人copy你的html(token一迸copy),在提交时,理论上token里包含的session_id不等于当前session_id,就可以判断这次提交是外部提交.

    如何匹配要执行的动作?

    在token的时候,要把这个token的动作名称写进这个token里,这样,在处理的时候,把这个动作解出来进行比较就行了.

    接口

    接口特点汇总:

    1、因为是非开放性的,所以所有的接口都是封闭的,只对公司内部的产品有效;

    2、因为是非开放性的,所以OAuth那套协议是行不通的,因为没有中间用户的授权过程;

    3、有的接口需要用户登录才能访问;

    4、有的接口不需要用户登录就可访问;

    针对以上特点,移动端与服务端的通信就需要2把钥匙,即2个token。

    第一个token是针对接口的(api_token);

    第二个token是针对用户的(user_token);

    先说第一个token(api_token)

    它的职责是保持接口访问的隐蔽性和有效性,保证接口只能给自家人用,怎么做到?参考思路如下:

    按服务器端和客户端都拥有的共同属性生成一个随机串,客户端生成这个串,服务器也按同样算法生成一个串,用来校验客户端的串。

    现在的接口基本是mvc模式,URL基本是restful风格,URL大体格式如下:

    http://blog.snsgou.com/模块名/控制器名/方法名?参数名1=参数值1&参数名2=参数值2&参数名3=参数值3

    接口token生成规则参考如下:

    api_token = md5 ('模块名' + '控制器名' + '方法名' + '2013-12-18' + '加密密钥') = 770fed4ca2aabd20ae9a5dd774711de2

    其中的

    1、 '2013-12-18' 为当天时间,

    2、'加密密钥' 为私有的加密密钥,手机端需要在服务端注册一个“接口使用者”账号后,系统会分配一个账号及密码,数据表设计参考如下:

    字段名 字段类型 注释

    client_id varchar(20) 客户端ID

    client_secret varchar(20) 客户端(加密)密钥

    服务端接口校验,PHP实现流程如下:

    再说第二个token(user_token)

    它的职责是保护用户的用户名及密码多次提交,以防密码泄露。

    如果接口需要用户登录,其访问流程如下:

    1、用户提交“用户名”和“密码”,实现登录(条件允许,这一步最好走https);

    2、登录成功后,服务端返回一个 user_token,生成规则参考如下:

    user_token = md5('用户的uid' + 'Unix时间戳') = etye0fgkgk4ca2aabd20ae9a5dd77471fgf

    服务端用数据表维护user_token的状态,表设计如下:

    字段名 字段类型 注释

    user_id int 用户ID

    user_token varchar(36) 用户token

    expire_time int 过期时间(Unix时间戳)

    (注:只列出了核心字段,其它的再扩展吧!!!)

    服务端生成 user_token 后,返回给客户端(自己存储),客户端每次接口请求时,如果接口需要用户登录才能访问,则需要把 user_id 与 user_token 传回给服务端,服务端接受到这2个参数后,需要做以下几步:

    1、检测 api_token的有效性;

    2、删除过期的 user_token 表记录;

    3、根据 user_id,user_token 获取表记录,如果表记录不存在,直接返回错误,如果记录存在,则进行下一步;

    4、更新 user_token 的过期时间(延期,保证其有效期内连续操作不掉线);

    5、返回接口数据;

    接口用例如下:

    1、发布日志

    URL: http://blog.snsgou.com/blog/Index/addBlog?client_id=wt3734wy636dhd3636sr5858t6&api_token=880fed4ca2aabd20ae9a5dd774711de2&user_token=etye0fgkgk4ca2aabd20ae9a5dd77471fgf&user_id=12

    请求方式: POST

    POST参数:title=我是标题&content=我是内容

    返回数据:

    {

    'code' => 1, // 1:成功 0:失败

    'msg' => '操作成功' // 登录失败、无权访问

    'data' => []

    }

    展开全文
  • 调试的时候可以获取到token,但是发布之后不知怎么回事,无论如何都获取token。提示如图: token后面加了一个e,是我在成功之后复现错误故意改的。 startup.cs的部分代码如图: 后来通过日志,发现发布...
  • 点击上方“java大数据修炼之道”,选择“设为星标”优质文章, 第一时间送达来自:掘金...证明“你是你自己”(比如:你每天上下班打卡,都需要通过指纹打卡,当你的指纹和系统里录入的指纹相匹配时,就打卡成功)互...
  • sessionid token

    2020-10-21 22:44:38
    sessionid token 前者 浏览器访问服务器的时候 服务器创建session 同时生成唯一会话key :sessionid.session 、sessioni保存再缓存中 。下次访问的时候cookie携带sessionid 服务器根据id找到响应的session进行匹配。 ...
  • 线上项目有一天测试发现在填写收货地址时无法提交一直提示手机号码正确! 但是手动输入就可以然后一个一个排查过程中发现红色箭头所指是从Iphone复制出来的 绿色箭头是自己输入的同样的正则 手机号码也完全符合...
  • 下次用户在访问一些需要用户登录才能访问的接口时就不用携带...如果有效就在请求接口的时候带着这串字符串一起进来访问,我们可以重写登录拦截器进行token匹配。如果通过就继续访问用户要访问的接口,如果通过可...
  • PHP Token(令牌)设计

    2021-01-21 15:46:02
    如果别人copy你的html(token一迸copy),在提交时,理论上token里包含的session_id等于当前session_id,就可以判断这次提交是外部提交. 如何匹配要执行的动作? 在token的时候,要把这个token的动作名称写进这个token里...
  • 与google的模型文件对比可以发现它们的参数与模型结构有些许差别,比如:albert_zh里的albert_large_zh模型参数:{'bert/embeddings/word_embeddings': [21128, 128],'bert/...,'bert/embeddings/token_type_embedd...
  • 傻傻分清之 Cookie、Session、Token、JWT 注:本文转载自微信公众号:路人甲java 什么是认证(Authentication) 通俗地讲就是验证当前用户的身份,证明 “你是你自己”(比如:你每天上下班打卡,都需要通过...
  • 2、如果带引号,将会匹配每个单词:uid token 3、模糊搜索:path:”/app/~” 4、* 匹配0到多个字符:*oken 5、? 匹配单个字符 : tok?n 6、+:搜索结果中必须包含此项 -:能含有此
  • 通俗地讲就是验证当前用户的身份,证明“你是你自己”(比如:你每天上下班打卡,都需要通过指纹打卡,当你的指纹和系统里录入的指纹相匹配时,就打卡成功) 互联网中的认证 1)用户名密码登录 2)邮箱发送登录链接 ...
  • 后续客户端的每次请求资源都必须携带token,这里放在请求头中,服务端接收到请求首先校验是否携带token,以及token是否和redis中的匹配,若不存在或不匹配直接拦截返回错误信息(如未认证)。 token管理:生成、...
  • 通俗地讲就是验证当前用户的身份,证明“你是你自己”(比如:你每天上下班打卡,都需要通过指纹打卡,当你的指纹和系统里录入的指纹相匹配时,就打卡成功) 互联网中的认证: 用户名密码登录 邮箱发送登录链接 手机...
  • 每次请求攻击者只能够盗取到被攻击这的cookice而能伪造当次请求的token,这是因为token是由服务器随机生成的,只有匹配当次的token,服务器才会与客户端进行连接,否则拒绝连接。而token无法防止暴力破解的原因是...
  • <p>I have a token in my MySQL database on every user. When I login this token will be stored as a cookie, but when I look at the cookie value it doesn't match the one I have in the database. <p>...
  • <p>I'm getting the dreaded "token mismatch" error on my phpMyAdmin. My install lives in a vagrant/ansible box so it is a clean system. <p>If I have auth_type set to "cookie" I simply stay on the ...
  • 什么是认证(Authentication)通俗地讲就是验证当前用户的身份,证明“你是你自己”(比如:你每天上下班打卡,都需要通过指纹打卡,当你的指纹和系统里录入的指纹相匹配时,就打卡成功...
  • 服务器将令牌给页面,页面拿到令牌和服务器匹配,如果一直,继续完成程序往下走,如果不匹配,那么返回 拦截器配置 使用步骤: 1.在页面form表单中加<s:token></s:token> ...

空空如也

空空如也

1 2 3 4 5 ... 19
收藏数 361
精华内容 144
关键字:

token不匹配