所谓第三方登录,实质就是 OAuth 授权。用户想要登录 A 网站,A 网站让用户提供第三方网站的数据,证明自己的身份。获取第三方网站的身份数据,就需要 OAuth 授权。
举例来说,A 网站允许 GitHub 登录,背后就是下面的流程。
- A 网站让用户跳转到 GitHub。
- GitHub 要求用户登录,然后询问"A 网站要求获得 xx 权限,你是否同意?"
- 用户同意,GitHub 就会重定向回 A 网站,同时发回一个授权码。
- A 网站使用授权码,向 GitHub 请求令牌。
- GitHub 返回令牌.
- A 网站使用令牌,向 GitHub 请求用户数据。
那为什么不直接返回token?而要中间经过code再倒腾一遍呢?知乎上有位大哥回答得挺好。
问题:
为什么oauth2中的授权码模式 在获取token之前非要先到资源服务器获取一个code 然后才使用资源服务器的code去资源服务器去申请token?
看了很多资料说是因为 用户在确认授权之后 资源服务器会跳转到我们指定的一个回调url, 如果直接返回token的话,谁都可以在浏览器中看到这个token 那就没有安全性可言了
但是我有个想法不知是否可行 那就是为什么 资源服务器非要跳转到第三方站点给的回调url呢? 我的url如果是个接口 资源服务器完全可以不通过浏览器跳转 而是直接回调我的接口 直接吧token给我的服务器, 然后我的服务器存储好token之后 自己决定如何跳转不就行了? 这样岂不是比授权模式简单也比隐式模式安全
回答:
首先,从产品交互上,我们需要浏览器跳转到“认证服务器”,让用户明确表态同不同意“第三方站点”的授权请求。这个时候,浏览器访问的地址已经到“认证服务器”去了,不跳转回来的话,网页不在“第三方站点”的控制中,怎么进行授权成功后的下一步交互呢?
授权码模式的安全考量,是基于产品交互能完成的前提下,考虑如何不在浏览器这种暴露 url 的环境里做到安全的。
如果你想表达的是“认证服务器”跳转回来,但是不带 code,而是通过 Server 对 Server 将 token 直接给“第三方服务器”。
这样会造成一系列问题:
Http 协议是无状态的,“第三方服务器”无法从一个 Server 对 Server 的请求轻易区分这个 token 对着自己当前哪个 Session。
如果依赖第一步里,“第三方服务器”跳转到“认证服务器”时传递的 GET 参数来作为 Session 身份区分,又涉及到跳转本身就是明文,可能被篡改的问题,需要协定复杂的签名协议来保证安全,这和 OAuth2 希望设计简洁验证模式的初衷违背。
假设安全问题解决了,已跳转回来的“第三方服务器”网页需要等待一个不知道何时才会过来的“认证服务器” Server 回调,才能告诉用户到底授权成功没有。远不如同步主动去请求“认证服务器”获取方便。
总结:1. github重定向回来的参数是明文的。2. 这样设计更方便
评论