【网络】登录与授权

本文介绍了账号登录与授权相关
登录:身份认证,确认“你是你”,用户“把我的权限授予我自己” 授权:把权限授予用户,可以持有令牌
登录
Cookie和Authorization都是Headers里的内容。
Cookie
起源:购物车,在 NetScape 网景浏览器时期。某电商网站希望有购物车功能,现在的购物车数据是存在服务器的,当时的人希望将购物车数据存在客户端本地。那么即使浏览器开发者与网站开发者的身份,开发这个就非常方便。
流程:服务器希望你记住什么,就把这个发过来,并标记这个是需要保存在本地的。客户端就将这些数据存在本地。浏览器下次访问相关域的时候,客户端就会自动附加这些数据,服务器不需要再次发送。
移动开发中使用cookie非常少了。
- 服务器需要客户端保存的内容,放在
Set-Cookie headers⾥返回,客户端会自动保存。 - 客户端保存的
Cookies,会在之后的所有请求⾥都携带进Cookie header⾥发回给服务器。 - 客户端保存 Cookie 是按照服务器域名来分类的,例如 shop.com 发回的 Cookie 保存下来以后,在之后向 games.com 的请求中并不会携带。
- 客户端保存的 Cookie 在超时后会被删除、没有设置超时时间的 Cookie (称作 SessionCookie)在浏览器关闭后就会⾃动删除;另外,服务器也可以主动删除还未过期的客户端Cookies。

作用:一般都是客户端给自己作标记,服务器拿本地的 Cookie 来对比。HTTP是无状态的,使用这个机制可以让服务器标识不同的用户。例如会话管理,登录状态,购物车,用户偏好,分析用户行为。
用户tracking流程图:
![]()
XSS(Cross-site scripting) 跨站脚本攻击
如果Cookie里有用户关键信息,比如密码等。那么本地有恶意的JavaScript脚本的话,就可以将这些Cookie发走,窃取用户数据。 应对:在Header里加入HttpOnly关键字。那本地脚本就看不到这个Cookie了。
XSRF 跨站请求伪造
即在⽤户不知情的情况下访问 已经保存了 Cookie 的⽹站,以此来越权操作⽤户账户(例如盗取⽤户资⾦)。应对⽅式主要是 从服务器安全⻆度考虑,就不多说了。
Referer校验
Authoriztion
Basic
使用的不多 格式:Authorization: Basic <username:password(Base64ed)> 有安全风险,用户名和密码相当于明文传输,万一被截获。
Bearer
“持有者” 格式:Authorization: Bearer
Oauth2
例如:使用github登录稀土掘金,第三方是掘金。即将授权的令牌授予给要用的第三方的网站。 流程:
- 第三⽅⽹站向授权⽅⽹站申请第三⽅授权合作,拿到 client id 和 client secret
- ⽤户在使⽤第三⽅⽹站时,点击「通过 XX (如 GitHub) 授权」按钮,第三⽅⽹站将⻚⾯跳转到授权⽅⽹站,并传⼊ client id 作为⾃⼰的身份标识
- 授权⽅⽹站根据 client id ,将第三⽅⽹站的信息和第三⽅⽹站需要的⽤户权限展示给⽤户,并询问⽤户是否同意授权
- ⽤户点击「同意授权」按钮后,授权⽅⽹站将⻚⾯跳转回第三⽅⽹站,并传⼊ Authorization code 作为⽤户认可的凭证。
- 第三⽅⽹站客户端将 Authorization code(只是表明用户同意授权) 发送回第三方⾃⼰的服务器
- 第三方网站的服务器将 Authorization code 和⾃⼰的 client secret(第三方向授权方申请时附加的表明自己的身份) ⼀并发送给授权⽅的服务器,说用户已经同意了。注意这个secret是需要绝对安全的。授权⽅服务器在验证通过后,返回 access token给第三方的服务器。OAuth 流程结束。
- 在上⾯的过程结束之后,第三⽅⽹站的服务器(或者有时客户端也会)就可以使⽤授权的 access token 作为⽤户授权的令牌,向授权⽅⽹站发送请求来获取⽤户信息或操作⽤户账户。但这已经在 OAuth 流程之外。
可以看到,最大的好处就是token是保密的,只在两个服务器方进行交互,保证登录安全。
易混淆:第三方登录
我和掘金之间的登录操作,利用了github登录,那么github属于第三方。
例子:微信登录(第三方登录)
流程:
- 第三⽅ App 向腾讯申请第三⽅授权合作,拿到 client id 和 client secret
- 用户在使⽤第三⽅ App 时,点击「通过微信登录」,第三⽅ App 将使⽤微信 SDK 跳转到微信,并传⼊⾃⼰的 client id 作为⾃⼰的身份标识
- 微信通过和服务器交互,拿到第三⽅ App 的信息,并限制在界⾯中,然后询问⽤户是否同意授权该 App 使⽤微信来登录
- ⽤户点击「使⽤微信登录」后,微信和服务器交互将授权信息提交,然后跳转回第三⽅App,并传⼊ Authorization code 作为⽤户认可的凭证
- 第三⽅ App 调⽤⾃⼰服务器的「微信登录」Api,并传⼊ Authorization code,然后等待服务器的响应。让服务器去和微信的服务器换取token。
- 服务器在收到登录请求后,拿收到的 Authorization code 去向微信的第三⽅授权接⼝发送请求,将 Authorization code 和⾃⼰的 client secret ⼀起作为参数发送,微信在验证通过后,返回 access token
- 服务器在收到 access token 后,⽴即拿着 access token 去向微信的⽤户信息接⼝发送请求,微信验证通过后,返回⽤户信息
- 服务器在收到⽤户信息后,在⾃⼰的数据库中为⽤户创建⼀个账户,并使⽤从微信服务器拿来的⽤户信息填⼊⾃⼰的数据库,以及将⽤户的 ID 和⽤户的微信 ID 做关联
- ⽤户创建完成后,服务器向客户端的请求发送响应,传送回刚创建好的⽤户信息
- 客户端收到服务器响应,⽤户登录成功
与github授权登录没有区别,只是叫法与概念不同。也是微信把自己的token授权给第三方的网站使用。
自己的服务器
使用Bearer token(流程需要加深理解,与OAuth第三方授权的区别)
有的 App 会在 Api 的设计中,将登录和授权设计成类似 OAuth2 的过程,但简化掉Authorization code 概念。即:登录接⼝请求成功时,会返回 access token,然后客户端在之后的请求中,就可以使⽤这个 access token 来当做 bearer token 进⾏⽤户操作了。
就是一种简化版的OAuth授权,直接使用code和自家服务器换取token。
refresh token
⽤法:access token 有失效时间,在它失效后,调⽤ refresh token 接⼝,传⼊ refresh_token 来获取新的 access token。
{
"token_type": "Bearer",
"access_token": "xxxxx",
"refresh_token": "xxxxx",
"expires_time": "xxxxx"
}
⽬的:安全。当 access token 失窃,由于它有失效时间,因此坏⼈只有较短的时间来「做坏事」;同时,由于(在标准的 OAuth2 流程中)refresh token 永远只存在与第三⽅服务的服务器中,因此 refresh token ⼏乎没有失窃的⻛险。