登录、授权(Cookie、Authorization、OAuth2)

742 阅读32分钟

Cookie

起源:购物车

  • 他的起源比较早,那个时候还不是IE,更不是现在的Chrome,是更早的Netscape(网景)
  • 那个时候浏览器的开发者、开发浏览器的公司也会去帮别人开发网站。
  • 当时是是什么情况?有个电商网站希望有购物车这个功能。(购物车现在都是怎么做?不管是淘宝还是什么网站,他们的购物车都是存在服务器的)
  • 可是那个时候的开发商他不想在自己服务器上面存信息,你又没有买,我存什么呀,你存本地吧,但是本地怎么存呢?没这功能呀。
  • 他就去给他做网站的开发人员,同时也是开发浏览器公司的人说, 你去给浏览器加这个功能吧, 你同时是浏览器的开发者,又是网站的开发者,这个时候做这个事是比较方便的。然后浏览器开发者就说,可以,我给你做,然后他们就干脆一不做二不休,做了一个完整的功能。
  • 这个功能叫做Cookie。他就是用来记录购物车的,只不过因为服务器不想记,想记到本地去,记到每一个添加购物车的电脑上。

工作机制:

  • 他是在本地记录,那么本地记录一个服务器需要的信息,怎么做呢?
    • 大致就是,服务器需要你保存什么,本来是服务器自己保存的信息,改成客户端记录。
    • 服务器需要你保存什么,然后发过来,你把他保存到本地就可以了。
  • 第一步,我在这个网站里面,我想往我的购物车里面加一个苹果,怎么加呢?
    • 我访问cart(购物车)这个接口,用post传过去一个数据,叫apple=1,就表示我要往我的购物车里面加一个apple。(请求响应报文完全不懂的可以补充一下知识http的原理和工作机制
  • 好,服务器就知道了。然后服务器处理完就会给我返回一个信息:
    • 好的(200 OK),同时会加一个header,这个header叫Set-Cookie:cart="apple=1"(不是Cookie,是Set-Cookie。
    • Cookie是客户端给服务器用的,而 Set-Cookie就是服务器给客户端用的,意思是你把这个cookie存下来吧),表示购物车里面有一个苹果。
    • 然后客户端就记下来了。好的,我知道了,我下次再访问shop.com的时候附加进去
    • (下图客户端下面这个shop.com就是服务器的请求地址,跟上面的请求是对应的,而且这个cookie存下来以后,他还有继续的自动机制,当浏览器再次访问这个内容的时候,他的cookie会自动附加进去,这是自动的,由浏览器来实现的,网站开发者不需要关心,用户也不需要关心)

image.png

  • 下次,我要加一个东西,比如我要加一个香蕉,
    • 我只要发过去我需要一个香蕉,同时将本地的这个cookie附加过去,而且这个cookie我不需要管,浏览器自动处理,服务器发消息的时候也不需要管,
    • 现在,我通过这个post告诉服务器要加一个香蕉,并且通过cookie告诉他我已经加了一个苹果,
  • 然后服务器就知道了,然后就返回消息告诉你记下来,记在本地。这个时候客户端自动更新这个东西。
  • 注意到没有,服务器什么都没记,他不管,客户端记了,所以依然不影响通讯。

image.png

  • 这个时候如果客户端要结账,
    • 他不需要发其他内容,因为cookie会把他的购物车给带过去,然后服务器再把这东西返回来。
    • 这里有一个东西很浪费,我把购物车信息发给你,你再发给我,好浪费啊,真麻烦,既然你帮我处理,我自己处理不就完了吗?
      • 这是早期,js这个东西在早期还是很落后的,服务器帮你做一个事,而且他还会做一些额外的事情,帮你做验证啊,还有没有货这些,我只是把他传过去,然后传回来,但是这个工作还是要服务器做的。
    • cookie是谁管理的?
      • 是服务器,每次修改都是服务器在做。客户端完全只是一个被动保存的机器。
    • 这个就是cookie设计这个机制的原因。就是服务器需要存什么,告诉他,客户端无条件的存下来,然后每次访问回去的时候,再把他带回去。

image.png

  • 关于Cookie大致知道就可以,因为我们在工作中,在移动开发中用cookie用得非常少,前些年还用一用,现在都不用了。逐渐在抛弃,但是抛弃的不是cookie,而是抛弃使用cookie来做登录,用cookie来做认证。

作用:

会话管理:登录状态,购物车

  • 那么我们怎么用cookie来管理登录状态呢?
    • 首先,我向服务器发一个http请求,去login,
      • 我要登录,我把我的用户名和登录密码都添加过去,给服务器确认。
    • 服务器怎么确认?
      • 他会记录a(username)登录了,
      • 同时他会为这件事情创建一个会话,表示我现在在和某个客户端,或者说某个用户代理,我们在通信,他现在是一个什么状态,他也许是一个登录状态,也许是一个非登录状态,总之我们正在会话中。
      • 他会记录下来他的会话信息(session),比如他的id是123。他就会把这个东西给存下来,
      • 然后把我的session id返回给我,服务器返回给客户端,session是一个名字,我可以叫session,可以叫metting都可以,他只是表示我和客户端之间交互了,然后他就会发回来,
      • session也是通过set-cookie。他是通过服务端定的,客户端什么都不管,我只把他记下来。

image.png

  • 然后客户端再次访问的时候,
  • 就会自动把这个session给移过去,然后服务器收到以后就会去对照,有没有一个session id=123的,
  • 一看,有,哦,原来他是username叫a的这个人,并且他现在是登录状态,好的,他要用户信息是吧?我给他,因为他已经登录了。
  • 然后就会正常地返回过来。这个是使用cookie来管理登录状态。

image.png

  • 类似session的标识,cookie里面是可以有多个的
    • 现在我用sessionid来管理我的登录信息是吧,同时我虽然已经用session存了你的登录信息了,我还不想存你的购物车,没关系,你要添加一个apple对吧?跟刚才那个过程是一样的,你发一个apple=1过来,我给你返回一个cart=“apple=1”,你记下来,
    • 你可以记两个cookie,
      • 一个sessionid用来管理你的登录,
      • 一个cart来管理你的购物车,两个东西互相不干扰。cookie是可以记多个的。

image.png

个性化:用户偏好、主题

  • 怎么用cookie来管理用户偏好呢?
    • 比如我现在有一个网站,叫shop.com,一个叫黑色主题,一个叫白色主题,我向服务器请求,请求完了以后,服务器给我返回一个client_id,他和session id是一样的,是一个标记,我把这个标记给你发过去,啪嗒贴脸上,然后每次你找我说话,我都会看见,你是做了那个标记的人。

image.png

  • 下次你再跟我说,我想换个蓝色主题, 专门发一个请求去改变主题,服务器觉得可以,就返回ok,这是一个正常的返回,然后服务器就记住了,这个client_id=123的人喜欢蓝色主题,他帮你保存了。

image.png

  • http是无状态的,假如你不存这个123,你下次再访问另一个页面,那肯定还是给你默认主题,因为记不住你,我不知道你就是上次那个人。
  • 那么下次我再访问过来,这个cookie是会自动附加的,然后他访问的是另外一个页面,并不是原页面,也不是改变主题的页面,可是服务器就是知道我要给他蓝色主题,因为他是123。
  • 这个就是网站用来管理用户偏好的一种记录方式,使用cookie在用户端记录的。

image.png

分析用户行为:

  • 关于分析用户行为,用户的追踪的使用

    • 这个在国外是比较有争议的,尤其是欧洲。我们在登录网址的时候,不知道你们注意到没有,尤其是一些国外的网站,国内的网站还不是很在意这个,因为跟法律有关跟当地法律有关,跟道德关系其实很小很小,一般都是跟法律有关,法律要求你必须这么干,或者就是民众的意识,你必须这么干这么干,你如果不这么干大家不用你网站了,那怎么办?做呗。分析用户行为,追踪用户行为,就是你能知道用户去了哪些网站,那么我们访问国外网站的时候,他在顶部或者底部跟你说,你现在访问的网站正在使用cookie对你进行行迹的追踪,这个对你是没有害处的,而且我们一定不会把你的消息给公开,只是我们自己来用的,请你理解。都会用这样的东西。我们看起来可能会觉得你怎么这么多余啊,你用就用呗,你还告诉我,让我不爽干嘛?但其实是这样的,在那些国家尤其是欧洲,你不通知用户,就使用cookie追踪用户是非法的,是会遭到惩罚的,比如巨额罚款,那么他们要做,就只有把他申明出来,用户点一个确定。都会点的,少数人不点,这个用户追踪是很有价值的。如果你真的那么在意的话那你别用了。没办法,我很想让你用,我很想赚你的钱,我只有不挣了。
  • 说一下这个东西怎么工作的。

    • 我有一个客户端和服务器,我想向你请求一个数据,
    • 然后你返回的数据有点意思,在body里面返回一个图片的链接,从你这个链接可以定到那个图片去,而且是自动的。就好像在你的网站打开一个在线图片一样,
    • 但他有什么关键的地方?
      • 就下面图片标记的那个地方,他加了一个和图片本身无关的信息from=shop.com,我在访问shop.com对吧,他去另外一个网站(3rd-part.com),这个网站就是帮助记录用户行踪的网站。
    • 追踪用户信息,从来都不是从a网站记录a网站,从b网站记录b网站,永远都是有一个统一的站点,他去记录用户去各个站点的行迹,然后他做一个统计。然后让其他网站一起来用,一个网站只记录一个网站在当前,只记录用户在自己的行为是没用的。这个不叫用户追踪。都是有一个统一的网站去记。
    • 这个例子里面就是这个3rd-part.com,他去记录了这个用户在shop.com的行为,那么这个链接有什么效果?
      • 就是这个用户打开这个网站之后,自动地去显示一张图片,可能会是一张广告什么的,然后这个图片他会附加一个信息,这个信息跟图片显示无关。也就是我去shop.com去放这个图片,后面就是追这个,如果我去tabao.com就是追的tabao.com,他们显示的是同样的图片,但是对于第三方记录网站来说不一样,
      • 他就会记录下来,当前这个用户是从shop.com来的,他就会在他的数据里面加一条,加什么呢?这个用户他去过shop.com。

image.png

  • 服务器返回这个Cookie信息,客户端会记下来(client_id = 123),
  • 然后客户端在访问这个图片的时候会自动往这个第三方发一个请求,不发请求怎么显示图片吧?怎么把图片下载下来?那么就只能请求这个第三方。
  • 然后第三方网站(3rd-part.com)就会记录,在他的数据库里面加一条,这个叫123的用户他来自shop.com,他就会增加这个用户记录。
  • 接下来,他会把图片显示给你,然后呢,也给你这么一个记录,会给一个针对第三方网站的一个id,这两个id可以不是同一个东西,他们名字也不一样,他们后面值也可以不一样,因为他们只是一个三方网站用来记录用户行踪的。
  • 如果接下来,这个用户去上另外一个网站,假如这个网站也捆绑了同一个第三方的统计,那么会有什么一个结果,他也会访问这个网站的图片。
  • 然后这个第三方就会知道,这个用户已经来过了,之前是去过shop.com,现在来了taobao.com,我记录一下,这个用户喜欢shop.com和taobao.com,喜欢去这么两个网站。
  • 那么这个时候就对这个用户有一定的画像了。他去了两个网站,如果用户去的网站很多的话,虽然我不知道你具体是谁,但是我知道你是一个什么样的人,那么说明什么?说明要推广告了。比如我之前去了一个旅游网站,然后我现在去一个电商网站,那么他就可能会推旅游团信息。另外,想象的空间是非常大的,就是你拿到足够多的用户数据之后,你对这个用户的画像足够精确之后,他能推的广告非常多。其实这种追踪用户行为,都是为了什么?都是为了推广告,都是为了从你兜里拿钱。

image.png

说两个额外的东西

XSS跨站脚本攻击(Cross-site scripting):HttpOnly

  • XSS跨站脚本攻击
    • 攻击?攻击不只是我打你,我对你有人任何的侵犯行为都叫攻击。
    • 我们的js,我们的网页脚本,他可能会帮我们的网页去做一些很方便的事情,另外他也可以拿到他的cookie,去用cookie做一些很方便的事情。
    • 可是,他也有可能去做坏事,比如我们记录用户信息靠的是什么?靠得就是cookie,那么假如你的cookie存的不是购物车,存的不是什么喜好,而是登录信息,如果js是一个坏人写的,他会怎么做呢?他可能会拿到你本地的cookie,然后直接给发出去,他去访问一个地址,比如访问他们自己的网站的一个存cookie的地址,把这个cookie发过去了, 你都不知道,后台就做这件事了。你的cookie就这么泄漏了,你的登录信息就这么泄漏了。一个js,一个本地脚本去获取header信息多正常啊,非常正常。
    • 这就是为什么cookie这个东西他为什么危险。因为我们登录这个事,本来是不存在的,后来慢慢出了,就用cookie做吧,然后慢慢就有人利用这个漏洞去做坏事。我的一个脚本,拿到你的cookie,直接给发走了,连邮件都不用,直接访问一个网页,一个url就可以了。
  • 他的应对政策有很多,其中一个就是在cookie这个header后面加上HttpOnly限制。
    • 比如:Set-Cookie:sessionid=123;HttpOnly
  • 他有什么效果?
    • 就是这个cookie你的本地脚本看不到,他只用于我们http的交换,只用于信息交换,本地脚本看不到,那么如果你是一个包含敏感信息,比如登录信息的cookie的话,那么你加这个东西去做限制。这都是后来被摸索出来的。

XSRF跨站请求伪造(Cross-site request forgery):Referer

  • 跨站请求伪造
    • 这个更加猥琐,也让我们有点想不到。他是什么呢?cookie是个自动机制,假如我现在访问一个网站,是个银行网站,然后我又去访问一个坏人的网站,我并不知道这个坏人网站,这个坏人在他的脚本里面加东西了,加什么呢?让我去访问一个地址,比如我使用图片的时候访问一个地址,访问地址的时候会附加一些别的操作,让我去访问银行,他会对各种银行都去试一试,我就赌你最近访问过银行,并且有cookie。
      • 比如这么一个url:bank.com/transfer?am…
      • 就这么一个url,你访问过去,就把钱转给坏人了,不需要我登录,不需要我确认,为什么?因为有cookie,cookie是自动的,对吧?假如我之前去登录过这个网站,那么他只要暗中去访问这个网址,刷,我钱转走了。
      • 当然实际操作中会有各种各样的防范,银行方面也会做这方面的防范,浏览器他们也会互相配合做这些东西,只是这是一个搞坏事的原型。
  • 那么解决方案,其中一点就是Referer这个header,Referer他的拼写是错的,Referrer(转发者)由于历史原因,就应该错着写才行。
    • 用法:Referer:www.google.com
    • 他就是用来显示你是从哪个网站跳转过来的。假如这个银行发现你这个url,你这个申请转账的url他是来自一个我不认识的网站,或者一个危险的网站,那么我拒绝对你转账。不过这种解决方案也有他的缺陷,你需要依赖浏览器,浏览器需要能给你做这个功能,假如浏览器不帮你做这个功能,我从a网站跳到b网站的时候,我不帮你自动加这个Referer这个header,那不就是瞎了吗。
  • 不过说来说去就比较长了,这两个都是cookie比较危险的点。cookie危险的点很多,但是不是因为他不好,而是这个东西天生劣势,由于要获得什么什么好处,所以会有什么什么危险。cookie为什么被遗弃?并不是他被遗弃,而是不再用于授权。

2.Authorization

  • 相比于cookie,Authorization就更加流行,而且越来越流行。 Authorization最常用的有两种:

Basic:

  • basic就是基本的授权方式,即使我们用的很少,但是也是很实用的。
  • Authorization:Basic<username:password(Base64ed)>
    • 例子:
    • get /user http/1.1
    • host: xxxxxx.xxx
    • Authorization:Basic eGlhb21pbmc6cWl1bG9uZw==
  • 比如现在我要做一个请求,我有一个header叫Authorization:Basic xxxx,这个就是认证信息,如果这个数据对了,那么我可以获取到用户信息,如果这个错了,用户信息就获取不到,他会跟我说你没有权限,你的权限不足。这是一个http请求,用法就是这样的,他用在header里面。

那么这个xxxx里面是什么内容呢?

  • base64转化后的用户名和密码。
  • 比如我的用户名和密码是xiaoming和qiulong,
  • 合在一起就是:xiaoming:qiulong
  • 转化后就是:eGlhb21pbmc6cWl1bG9uZw== 我这么请求数据服务器就会给我返回正确信息,这个就是basic,
  • 为什么叫basic,因为他是最基本的信息了,用户名密码都给我就完了。
  • 这个东西他有什么缺陷呢?他是有安全风险的,你这个东西万一被截获怎么办?
    • 其实,现在大多数网站,尤其是api,就是浏览器之外的,你的应用使用的时候已经全都是https了,那么安全就交给https,我真的可以把我的用户名和密码直接传过去,因为他们都会被加密的,别人看不到的。
    • 不过呢,他确实还有个安全缺陷,有一点点,就是假如你需要这么做,你就需要把经过base64转化的用户名和密码,或者是base64之前的,保存到本地,这样你下次再去请求才能够自动化这个东西。而不是要用户每次都输入用户名和密码,对吧?你换个页面就让用户输一次,用户不疯了吗?
    • 那么你把她存到你本地,不管是存到你电脑,还是存到你手机,假如你这个设备被人给黑了,比如你的手机你去获取了root权限,然后root权限你又把他给了某个软件,然后他就可以随便操作你手机了,他把你的东西盗走就是有可能的了。
    • 其实说回来,这种安全风险倒还好,其实他把自己的手机root权限获取到,本身就放弃了一定的安全性,对吧,手机被破解了你能怪这个机制不好吗?还是有些软件在用的,而且做得比较大比较重技术的公司也有在用这个的。所以本身在安全上是没问题的。刚才我说的安全风险相对来说还算好吧。设备被破解了才有风险,那叫什么风险呢。这是第一种,不过用的公司还是少一点。挺好用的,挺简单的。

Bearer:

  • Bearer(持票人)
    • 也就是拿着尚方宝剑的人,你做事需要亮你的尚方宝剑。这种就叫做token,上面的basic长着token这种形式,但是并不能叫token,严格说起来也是,你把用户名密码揉起来base64一下也可以用作票根。不过Bearer才是真正的比较形象的token形式。
    • 本来我不是那个人,但是那个人给了我权限,那么我拿这个令牌,就可以用这个令牌去获取信息,去操作。这个是很常用的一种方式。他的格式是这个样子:
    • Authorization:Bearer<Bearer token>
    • 前面也有个头Bearer,表示我这种认证用的不是basic,而是持票这种方式,后面把持票人的token填进来就可以了。而这个token他就不是某种算法得到的,而是需要找授权方给你,有的时候,你会使用github或者使用新浪微博,去给别的软件授权的时候,并不需要你从这个网站跳过去登录一下,而是直接从你的账户信息里面,会有一个获取token,获取api token,你把这个token复制出来给某个软件就可以了。这是一种方式,token本身就可以拿出来给别人去用。另外一种是OAuth2。

OAuth2:

  • 他是一种第三方认证的机制。
  • OAuth我们现在都是用的2,1 是好几年前的,2和1差别不大,他们核心都是一样的,但是他做了一些工作,让开发者关心的事情更少,同时并不降低安全性。

OAuth2流程:第三方授权示例

  • 首先去github-setting-application里面把掘金的授权回收,

image.png

  • 然后现在去掘金点登录,选择三方github,他就会进入这样一个页面。
  • 谁是第三方?
    • 现在我是github的用户,并不是我是掘金的用户,现在我用github的时候我需要做一个第三方的授权,我要把我的一些权限授给别的网站,比如这个网站叫掘金,这个第三方是掘金,第三方是我从github跳到做认证的地方,这个地方可能会有点迷,额,我不是使用github来登录吗?第三方怎么成了掘金了?这里不是我要强调一些概念,而是你要搞清楚才能理解一些其他东西。
    • 记住,第三方是掘金,第一方和第二方是你和github。你要把信息授权给别的网站你要做这么一回事。

image.png

image.png

  • 那么我要授权给第三方的时候,我现在点一个github登录,我就到了一个github页面了,是谁过来的?
    • 是掘金给我带过来的。看上面这个授权页面地址是github.com,而这个里面有一个关键信息,就是client_id。
    • 这个client_id是github授予给掘金的一个id,他什么时候授予的呢?
    • 掘金的开发者当初找github申请下来的。这个就是github他会对掘金有一个标记,那么这个标记有什么用处呢?
    • 他的用处就是当你打开这个页面的时候, 传入client_id,那么github就会自动把掘金的图标,以及这个掘金的名字,以及他需要哪些权限,还有下面这个url地址给你,然后用户看到这些的时候,他就会去判断,我现在需要授权的目标对象,到底是不是我以为的那个对象,因为有的时候网站会做伪造,会做劫持什么的,假如你没这个一步,他可能在授权过程中他给你换了。你以为你授权给掘金了,其实你授权给别的什么坏人网站了,那么坏人就要滥用你的信息了。这个client_id就这个作用,他用来做识别的。

image.png

  • 那么接下来,我在github上点那个确定,授权给xitu,然后请求发送,页面消失,登录成功。
  • 那么这一系列过程又发生了什么呢?
  • 我点了之后,这个github就会跳回掘金的网站去,同时跳回去的时候会返回一个授权码(Authorization code)。
    • Authorization code并不是一个token,为什么他不直接给token呢?
      • 有个很关键的原因,https这个过程他并不是被强制的,他在OAuth这个过程里面不是强制你要使用https,那么我这个过程可能被拦截了,可能被别人窃取了,窃取到之后,假如Authorization code就是最终的那个码的话,你别人窃取到之后不就可以使用这个权限了吗?
      • 还有什么呢?浏览器都是不可靠的,你不知道用户在用什么浏览器,你不知道用户在用什么操作系统,Authorization code传输到第三方以后,还是有可能泄漏。github只是给你一个code,code表示我的用户已经告诉我了,他确实愿意把权限授权给你(掘金),这个是一个证明,他愿意把权限授权给你,可是这并不是钥匙,他只是个证明,你拿这个code给我,跟我要用户数据,我不会给你,你还需要真正的授权的票据,那个token给我
      • 那么token怎么获取?接下来继续说。

image.png

  • 现在,我的浏览器已经获取到这个信息了,接下来他还要去找他的服务器,他会把这个code发送给服务器,通过http也好,通过https也好,这个东西不怕被窃取,他只是证明用户愿意授权。

image.png

  • 然后,到了服务器以后,服务器就会跟github去做请求了。就是第三方的服务器会去向授权方的服务器请求。请求的时候他会附加授权的code以及一个叫client_secret的东西。
  • 这个client_secret是什么呢?
    • 他是在第三方,也就是掘金去github申请的时候跟client_id一起发过来的,这两个数据本身没有什么区别,只是他们在实际用处上有点区别,这个secret是绝对保密的,任何地方都不会看到,只有第三方的服务器拿着。这次链接也绝对是https链接,是个绝对安全的链接。那么现在,我有code证明用户愿意授权给我,又有client_secret证明我就是掘金。这个时候github就知道了,他给我足够的身份信息,并且这个信息来得足够安全,他不会被人截获,他通过https过来的,那么这个时候github就足够放心,他把真正的access token返回回去了。

image.png

  • 这个时候Server拿到这个token,现在,这个OAuth2的流程已经结束了。他不需要把你的token发给客户端,不需要发给浏览器。用户把他在github上的一些权限授予了掘金,并且掘金已经拿到token了,接下来OAuth就不再参与了。
  • 接下来,比如你的Server调取信息,比如用户头像什么的。怎么做呢?Server去请求github.com,同时附加上这个token。怎么附加呢?
    • 假设我的token是abccccc

image.png

image.png

  • 这个过程是很安全的,但是由于一些事实的限制,或者是一些安全上的不在意,还有一种什么情况呢?Server会把这个token发给客户端,这个不是说不允许,只是他会对安全有一定的影响,就是别人把你这个token拿到了,他也可以去做事。

image.png

  • 然后这么请求,也是可以的,很多软件也这么做。不过这么做,就把OAuth流程的好处给浪费掉了,你既然这样,那干脆在用户授权之后直接返回回来不就可以了吗?费这么多事干嘛呀?费这么多事不就是为了让别人截取不到吗?让你的浏览器被人黑掉,你的手机被人黑掉,你的网络被人黑掉都没关系。你的token依然是安全的,对吧?但是你这么做这些东西有一点白费了。但是这种用法还是有一定的使用的概率的,还是有些公司是这么用的。只不过他不太具有OAuth2的安全性。

image.png

第三方登录示例:微信登录

  • 说到微信登录,我先说一下使用github登录,刚才我说使用github登录这个第三方授权,他的第三方是掘金。但是我要说,第三方登录这个事比第三方授权要来得晚一点,第三方登录他的第三方真的是github,你在掘金,使用第三方登录,他的第三方真的是github,由于第三方登录这个词的出现,他导致第三方授权这个概念非常非常含糊,非常非常让人难以理解。你应该能明白为什么吧?

    • 第三方授权是什么?本来是我跟github的信息,结果分享给你了,那掘金不是第三方吗?
    • 而第三方登录是什么呢?本来我要登录掘金的,但是我用了github,那第三方就是github。
  • 其实这个登录和授权都是很直观的东西,但是你要知道他们分别是谁,分别是谁不是为了考试,不是为了面试,但是你在思考问题的时候你会非常清晰。你把这些搞明白以后,你再看一些api文档什么的,你脑子会非常清晰,你会比谁都想得明白,这个是重点。

  • 继续说微信登录,他是什么?

    • 他是一种第三方登录。
    • 比如你有一个手机软件,然后他里面有一个登录按钮, 你可以使用用户名登录,也可以使用第三方登录。比如你可以使用微信登录。那么有些人会做微信的开发,不管你有没有做过,我要说一下微信登录的手机流程是什么。

image.png

  • 第一步,你会使用微信给你的api, 你通过这个api调用微信给你的接口,去打开微信的授权界面,那个授权界面叫微信登录。「你看授权登录,第三方授权和第三方登录真的是互相之间没法说。那个界面是微信对你进行第三方授权,微信对这个第三方(你的应用)授权,但其实他叫什么?他叫微信登录。」你点这个之后,微信就会把他的页面关闭,返回给你的软件一个Authorization code(授权码)。

  • 为什么给你授权码?这是一个完整的OAuth2的流程,接下来,正规做法,就是你把这个code告诉你的服务器,然后你的服务器再拿你的这个code,以及你的secret去找微信的服务器,去要你的access token,拿到这个token之后,你们的客户端需要什么数据,你们服务器就去请求什么数据,比如你的客户端需要微信的用户名和他的头像,好,你的服务器就去拿,不是客户端拿。客户端不应该持有token,除非不得以。 就算是不得以,也不能持有secret,你去找微信服务器去拿token的这个过程,一定不能发生在客户端。

  • 我知道有些公司在这么做的,有些公司就在这么做。他们的后端人员可能会推这个事,这个事不应该我们做呀, 你看微信api里面说的明明白白呀,要你去请求,你拿到那个code再去请求不就完了。你要secret吗?我给你呀,我们这存在有啊,你去吧。其实这个过程是不对的。你的客户端拿到code,code交给服务器,其实就完了。这个是为了安全考虑,不是为了省事考虑。如果是为了省事,根本就不需要OAuth了。直接用户同意之后,把token给你就完了。还要什么用code换token的过程啊?用code换token就因为你客户端获取了这个数据,未必足够安全。这个是微信登录。微信登录他是一个完整的OAuth过程。

在自家软件里面使用Bearer token

  • 也是使用这种方式,比如我的软件,有个接口
    • (api.xxx.com/login?username=qiulong&password=123)
    • 我输入这些信息,我的服务器就直接给我返回这个token(access_token=bdcj55s),
    • 当我再次使用的时候,我不需要附加其他信息,我只要附加(Authorization:Bearer bdcj55s),
    • 这就是下次我再请求的时候,我们的做法,这个过程他并没有OAuth的过程,他就是我前面说的做OAuth不要这么干的过程。我把用户名密码传过去,你直接把我要的那个token给我,我说的那个不安全的过程。他就是一个模仿了OAuth2的这种使用token的方式他的token的用法,但是他并不是一个OAuth2的过程。要知道这个并不是OAuth。很多人不懂OAuth2的原因就是这样的。就是有些api,他在用一个简化版本的OAuth2,你再去使用一些第三方OAuth2的过程你会发现,这怎么比我们公司麻烦这么多?好烦啊,他怎么还要code啊?其实是你们公司使用的是一个简化版的流程。你们自己登录自己的账户使用这种简化版是理所应当的,对吧?不然你还用code的话,你自己的Server拿着自己的code和自己的secret去找自己Server去换那个token,那不多此一举吗?
  • 这种过程,他只是使用了Bearer token这种模式,但是他并不是OAuth2的过程。

refresh token

  • 一个刷新的票根。

image.png

  • 大概长这个样子。就是服务器返回的时候不只是access_token,还返回了一个refresh_token,他是什么呢?

image.png

  • 这个过程中返回的不只是一个access token,还返回一个refresh_token,你的server可以使用refresh_token来找github.com,然后这个github.com就会返回这个新的access_token和一个新的refresh_token,然后之前那个老的access_token就失效了。或者你那个老的access_token在经过一段时间以后,比如七天,十五天后,他也会失效。你的assess_token会自动失效,或者会被refresh_token请求强制失效。那么这个过程是什么作用?他有什么意义呢?我本来有token你为什么要刷一下换一下呢?他其实就是为了安全,就是你的access_token不管怎么样,他还是有一定概率会丢掉的。那么你这个token丢掉之后,你要用户重新过来再认证一次,这就有点不现实,用户都很懒,用户每一个获取成本都很高,喂,你的token失效了,请你过来再认证一次。谁搭理你啊?对吧,这个用户可能就流失了。那么你怎么做,你为了安全你需要快速的把这个token给失效掉,然后你再获取一个新的 token,怎么获取?refresh_token。大致是下面这样的。

image.png

  • 然后服务器就会给你返回一个新的token,并且同时把你那个旧的让他失效。这个是refresh_token,他是肯定要https的。他的流程跟获取token的流程他都应该尽量发生在服务端。