美文网首页基础原理知识点
身份认证 | Token介绍和OAuth协议介绍

身份认证 | Token介绍和OAuth协议介绍

作者: 浪漫宇宙与人间日常 | 来源:发表于2019-01-21 14:30 被阅读97次

    作者的话

    在最近的项目中,遇到了网站部分获取访问量接口,之前的接口是不需要任何认证直接就可以获取到,这样的行为是非常不安全的,而后框架组那边给出了利用token进行身份验证,这里就会涉及到token和OAuth协议的一些基本知识,我们本篇不会深入介绍(作者也了解的不深入),只是作为简单了解。

    背景

    在web浏览器下面,我们通常用来记录身份信息就是利用cookie,通过用户名密码登录来实现认证用户的操作,但是对于手机app等一些没有像web浏览器的状态的客户端就不适用了,从而就会有token(令牌)这种技术的出现,它可以不暴露用户名和密码,给第三方提供资源等。目前实现的方式简单描述就是:通过用户名和密码登录,你可以获取到token,将token置于请求header中,后续需要获取的资源,请求头中有token权限通过就可以获取。

    Token

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

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

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

    这只是其中的一种方式,这里推荐一个其他的token生成工具 (jwt),有兴趣的小伙伴可以去了解下。

    由于HTTP是一种没有状态的协议,它并不知道是谁访问了我们的应用。这里把用户看成是客户端,客户端使用用户名还有密码通过了身份验证,不过下次这个客户端再发送请求时候,还得再验证一下。

    基于session机制的身份认证

    通用的解决方法就是:当用户请求登录的时候,如果没有问题,在服务端生成一条记录,在这个记录里可以说明登录的用户是谁,然后把这条记录的id发送给客户端,客户端收到以后把这个id存储在cookie里,下次该用户再次向服务端发送请求的时候,可以带上这个cookie,这样服务端会验证一下cookie里的信息,看能不能在服务端这里找到对应的记录,如果可以,说明用户已经通过了身份验证,就把用户请求的数据返回给客户端。
    以上所描述的过程就是利用session,那个id值就是sessionid。我们需要在服务端存储为用户生成的session,这些session会存储在内存,磁盘,或者数据库。

    基于token机制的身份认证

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

    客户端使用用户名和密码请求登录。服务端收到请求,验证用户名和密码。验证成功后,服务端会生成一个token,然后把这个token发送给客户端。客户端收到token后把它存储起来,可以放在cookie或者Local Storage(本地存储)里。客户端每次向服务端发送请求的时候都需要带上服务端发给的token。服务端收到请求,然后去验证客户端请求里面带着token,如果验证成功,就向客户端返回请求的数据。

    利用token机制进行登录认证,可以有以下方式:

    a.用设备mac地址作为token

    客户端:客户端在登录时获取设备的mac地址,将其作为参数传递到服务端

    服务端:服务端接收到该参数后,便用一个变量来接收,同时将其作为token保存在数据库,并将该token设置到session中。客户端每次请求的时候都要统一拦截,将客户端传递的token和服务器端session中的token进行对比,相同则登录成功,不同则拒绝。

    此方式客户端和服务端统一了唯一的标识,并且保证每一个设备拥有唯一的标识。缺点是服务器端需要保存mac地址;优点是客户端无需重新登录,只要登录一次以后一直可以使用,对于超时的问题由服务端进行处理。

    b.用sessionid作为token

    客户端:客户端携带用户名和密码登录

    服务端:接收到用户名和密码后进行校验,正确就将本地获取的sessionid作为token返回给客户端,客户端以后只需带上请求的数据即可。

    此方式的优点是方便,不用存储数据,缺点就是当session过期时,客户端必须重新登录才能请求数据。

    当然,对于一些保密性较高的应用,可以采取两种方式结合的方式,将设备mac地址与用户名密码同时作为token进行认证。

    APP利用token机制进行身份认证

    用户在登录APP时,APP端会发送加密的用户名和密码到服务器,服务器验证用户名和密码,如果验证成功,就会生成相应位数的字符产作为token存储到服务器中,并且将该token返回给APP端。

    以后APP再次请求时,凡是需要验证的地方都要带上该token,然后服务器端验证token,成功返回所需要的结果,失败返回错误信息,让用户重新登录。其中,服务器上会给token设置一个有效期,每次APP请求的时候都验证token和有效期。

    token的存储

    token可以存到数据库中,但是有可能查询token的时间会过长导致token丢失(其实token丢失了再重新认证一个就好,但是别丢太频繁,别让用户就去认证)。

    为了避免查询时间过长,可以将token放到内存中。这样查询速度绝对就不是问题了,也不用太担心占据内存,就算token是一个32位的字符串,应用的用户量在百万级或者千万级,也是占不了多少内存的。

    token的加密

    token是很容易泄露的,如果不进行加密处理,很容易被恶意拷贝并用来登录。加密的方式一般有:

    在存储的时候把token进行对称加密存储,用到的时候再解密。文章最开始提到的签名sign:将请求URL、时间戳、token三者合并,通过算法进行加密处理。

    OAuth协议

    我们首先来看下我们平时接触的OAuth协议

    • 我进入网易云音乐听歌,然后提示我登录,我不想自己注册了,我点击使用新浪微博登录,这时候跳出新浪微博登录,我扫码登录后,就自动注册了网易云音乐,我的微博名称和头像都在网易云音乐上显示了。

    很显然,我们这个地方是把新浪微博的信息给了网易云音乐,网易云音乐获取了我新浪微博的信息,这之间就是利用了OAuth2协议

    协议流转图

    我们一起看下流转图,来了解下基本原理:

    以上几个名词至关重要:

    Resource Owner:资源所有者。即用户。
    Client:客户端(第三方应用)。如云冲印。
    HTTP service:HTTP服务提供商,简称服务提供商。如上文提到的github或者Google。
    User Agent:用户代理。本文中就是指浏览器。
    Authorization server:授权(认证)服务器。即服务提供商专门用来处理认证的服务器。
    Resource server:资源服务器,即服务提供商存放用户生成的资源的服务器。它与认证服务器,可以是同一台服务器,也可以是不同的服务器。
    Access Token:访问令牌。使用合法的访问令牌获取受保护的资源。

    其实从图中很清晰看出来他们之间的关系:
    (A)客户端向资源所有者请求授权。授权请求可以直接对资源所有者(如图所示)进行,或者通过授权服务器作为中介进行间接访问(首选方案)。
    (B)资源所有者允许授权,并返回凭证(如code)。
    (C)客户端通过授权服务器进行身份验证,并提供授权凭证(如code),请求访问令牌(access token)。
    (D)授权服务器对客户端进行身份验证,并验证授权凭证,如果有效,则发出访问令牌。
    (E)客户端向资源服务器请求受保护的资源,并通过提供访问令牌来进行身份验证。
    (F)资源服务器验证访问令牌,如果正确则返回受保护资源。

    我们目前接触到最多应该就是通过用户名称密码来获取token了,也就是C所述,只是这部分直接将code 理解为用户名密码登录这一操作。

    在微信公众号开发文档中,就严格按照上述过程进行了OAuth2协议,小伙伴们可以去了解下。

    授权模式

    在整个协议中,最关键就是在于授权,授权的模式有以下几种:

    • 授权码模式(authorization code)
    • 简化模式(implicit)
    • 密码模式(resource owner password credentials)
    • 客户端模式(client credentials)
    授权码模式:

    权码模式是功能最完整、使用最广泛、流程最严密的授权模式。(微信公众号使用这种模式)

    由于这是一个基于重定向的流,所以客户端必须能够与资源所有者的用户代理(通常是web浏览器)进行交互,并且能够从授权服务器接收传入的请求(通过重定向)。

    授权码模式流程图

    (A)用户访问客户端,客户端将用户导向授权服务器,通过用户代理(User-Agent)发送包括它的客户端标识符、请求的范围、本地状态和一个重定向URI,授权服务器在授予(或拒绝)访问权后将其发送给用户代理。
    (B)授权服务器对资源所有者进行身份验证(通过用户代理),并确定资源所有者是否授予或拒绝客户端的访问请求。
    (C)假如资源所有者同意授权请求,那么授权服务器将会使用前面提供的或者事先指定的重定向URI(redirection URI),重定向到客户端,并附上一个授权码(code)和一个前面提供的本地状态(state)(如果有的话,则会原值返回)。
    (D)客户端收到授权码,附上早先的重定向URI,向授权服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见。在发出请求时,授权服务器对客户端进行身份验证。请求参数包含授权代码、用于获得验证的授权代码的重定向URI、标识客户端身份的client id和client secret。
    (E)授权服务器对客户端进行身份验证,验证授权代码,并确保所收到的重定向URI与用于在步骤(C)中对客户端重定向的URI相匹配,如果有效,授权服务器将发送访问令牌access token和刷新令牌refresh token(可选)。

    简化模式

    简化模式(implicit grant type)不通过第三方应用程序的服务器,直接在浏览器中向认证服务器申请令牌,跳过了"授权码"这个步骤,因此得名。所有步骤在浏览器中完成,令牌对访问者是可见的,且客户端不需要认证。

    密码模式

    密码模式中,用户向客户端提供自己的用户名和密码。客户端使用这些信息,向"服务商提供商"索要授权。
    在这种模式中,用户必须把自己的密码给客户端,但是客户端不得储存密码。这通常用在用户对客户端高度信任的情况下,比如客户端是操作系统的一部分,或者由一个著名公司出品。而认证服务器只有在其他授权模式无法执行的情况下,才能考虑使用这种模式。

    客户端模式

    客户端模式(Client Credentials Grant)指客户端以自己的名义,而不是以用户的名义,向"服务提供商"进行认证。严格地说,客户端模式并不属于OAuth框架所要解决的问题。在这种模式中,用户直接向客户端注册,客户端以自己的名义要求"服务提供商"提供服务,其实不存在授权问题。

    关注我

    相关文章

      网友评论

        本文标题:身份认证 | Token介绍和OAuth协议介绍

        本文链接:https://www.haomeiwen.com/subject/aercjqtx.html