OAuth2 授权码模式为什么不直接返回access_token

2023-11-02

https://www.cnblogs.com/erichi101/p/13497971.html

OAuth2的实际应用中,最常见的就是授权码模式了。 
微博是这种模式,微信也是这种模式。 
总结来说,就是简单的二步: 

1.获取code  
2.根据code,去获取access_token  

 


以微博为例

http://open.weibo.com/wiki/%E6%8E%88%E6%9D%83%E6%9C%BA%E5%88%B6%E8%AF%B4%E6%98%8E):

假设我们开发一个网站(称为client;相对应的,微博就是server了),网站允许用户以微博账号登录,且需要读取用户的微博信息(账号、评论等等)。 
显然,这过程中需要用户授权。 

第一步: 

  1. https://api.weibo.com/oauth2/authorize?client_id=YOUR_CLIENT_ID&response_type=code&redirect_uri=YOUR_REGISTERED_REDIRECT_URI  


第二步: 

  1. https://api.weibo.com/oauth2/access_token?client_id=YOUR_CLIENT_ID&client_secret=YOUR_CLIENT_SECRET&grant_type=authorization_code&redirect_uri=YOUR_REGISTERED_REDIRECT_URI&code=CODE  



这其中有几个问题: 
1.
获取code时,传递的二个变量(clent_idredirect_url),没有一个是跟用户有关的,那微博怎么知道我们请求的是哪个用户的授权呢? 
这个问题现在看来很可笑,但刚开始确实是蒙圈了。 
其实,在第一步的URI发出后,是要求用户跳转到server端登录的。这很好理解,如果用户不登录,那你怎么知道是哪个用户呢,他又怎么给你授权呢? 
此外,可以看到,第一步的URI,放在我们网站页面的任何位置都可以;它也不要求传递跟session相关的任何信息。 
这个URI对应的页面是微博开发的,跟我们网站没关系。 
事实上,这个URI可以直接拷贝到浏览器里发起请求;这个时候,是浏览器跟微博的一个交互,我们的网站是一无所知的。 
那什么时候我们得知用户给我们授权了呢? 
第一步URI的请求,浏览器得到的是一个http的重定向响应,这个重定向指向的就是我们的网站;此时浏览器向我们的网站发起请求: 
类似于: 
 

https://client.example.com/cb?code=SplxlOBeZQQYbYS6WxSbIA&state=xyz


站在我们网站后台程序的角度来看,我们是忽然(在此这前,它一无所知)收到一个code了,而这个code,是跟微博的一个用户一一对应的,我们拿这个code向微博发起请求,就能获得用户的授权,获得access_token,再发起另一请求,就可以获取用户信息了。 

2.
为什么在第一个URI请求发出后,微博的302重定向响应中,没有直接返回access_token,而是只返回一个code呢? 
其实最初我的疑问更可笑:我想,为什么微博不直接返回access_token给我们网站呢? 
这个问题的答案是,发起第一步的URI请求的,是浏览器!还记得前面我说的我们的网站是一无所知吗?此时微博是与浏览器在通信,而不是我们的网站,当然不能把参数传返回到我们网站了。 
微博只能通过返回一个302响应,让浏览器重新向我们网站发起请求,把code传到我们网站来。 

回到第二个问题。 
该博客下有人是这样回答的: 

1、为什么授权码模式需要这个授权码 当然是为了安全性 首先在OAuth体系中access_token是作为访问获取资源的唯一凭据 如果在AS授权完成之后 直接通过重定向传回access_token 那么HTTP 302不是安全的 Attacker有可能会获取到access_token 但是如果只返回Authorization code 就算别人获得了也没什么卵用 因为Authorization code不能获取到资源 在client向AS请求access_token的过程中 是通过HTTPS来保证安全的 而且获得access_token是需要client secret与Authorization code一起的 Attacker知道了Authorization code但并不知道client secret 同样也不能获得到access_token 所以client与AS是有责任保护好client secret的  
获得了access_token之后 向RS发起请求 RS其实会与AS交互 来校验access_token 所以你想直接伪造一个access_token 那也是不ok的  
  
2、突然想到漏说了一块 关于为什么不直接用HTTPS重定向回client  
3、是因为不是所有client server都支持HTTPS~所以为了通用性 和安全性 才衍生出来这么一个Auth code  
4、但是AS肯定是实现HTTPS的 所以在client向AS提起request 是木有问题的~  


我自己的理解,是这样的: 
直接返回access_token有可能被黑客拦截到,而拿到access_token就可以获得用户信息了,非常不安全。 
那最容易想到的是,微博通过https返回access_token啊,https会对access_token加密,那不就可以了吗? 
为什么这个方法不可行呢? 
因为有可能我们的网站不支持https!站在微博的角度来看,千千万万的第三方网站,你要求每个网站都支持https,是不太现实的。 
stackoverflow
上的一个回答(http://stackoverflow.com/questions/13387698/why-is-there-an-authorization-code-flow-in-oauth2-when-implicit-flow-works-s)说这是一个巨大的痛苦“a huge pain” 

那为什么返回code再去获取access_token就安全了呢? 
因为这时候再去获取access_token,就是https请求了,发起方为我们的网站,接收方为微博,而微博作为OAuth server,肯定提供https 
但是,另一个问题来了,黑客拿到了code,它也向微博发起请求去获取access_token是不是就可以了呢? 
也是不可以的。 
因为向微博请求access_token时,还要带上我们网站的密码client secret)。 
这个密码,是我们网站在微博开放平台上注册时获得的(同时会得到一个client_id,这个值在第一步的URI里用到了)。 
这一点在该博客没有提出来,最容易让人困惑。 

3.
为什么简化模式(implicit grant type)是可行的? 
这个在stackoverflow有回答,前面也提到过: 
http://stackoverflow.com/questions/13387698/why-is-there-an-authorization-code-flow-in-oauth2-when-implicit-flow-works-s 


这就涉及到一个知识点: 
浏览器不会把URL当中的“hash fragment”发给服务器。hash fragment是只留在浏览器的地址栏的,它可以被网页的js读取到:window.location.hash 
既然hash fragment没有发给服务器,那即使黑客拦截到请求,也获取不到它。 
什么是hash fragment?就是URL当中#号后面的那一部分。 
博客中的示例: 

HTTP/1.1 302 Found  
Location: http://example.com/cb#access_token=2YotnFZFEjr1zCsicMWpAA&state=xyz&token_type=example&expires_in=3600  

 



可以得知,“#access_token=2YotnFZFEjr1zCsicMWpAA”这一部分是留在浏览器这边的。 
当浏览器接收到到该响应时,向http://example.com/cb发起请求,而后者的响应页面当中,应当有读取hash fragment的代码。 
这样,client就拿到了access_token了。 

解决了这三个问题,我本想到实际场景中抓包看看的,但遗憾的是,不管是蘑菇街还是聚美优品,这些允许以微博账号登录的网站,都只看到获取code那一步,没有看到获取access_token那一步。 
或许改天有空可以自己在微博开放平台上注册一个应用来验证一下。 
不过网上有人验证过微博的: 
https://segmentfault.com/a/1190000000666685 


此外还有一些关于微信OAuth2的实际例子: 
http://www.cnblogs.com/txw1958/p/weixin71-oauth20.html 
http://zeusjava.com/2015/04/22/wechat-get-userinfo/ 

都讲得比较详细。 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OAuth2 授权码模式为什么不直接返回access_token 的相关文章

随机推荐

  • Linux 添加Match User 重启sshd出现job for ssh.service failed

    最近在做一个sftp的需求 需要添加一个sftp用户来传输文件到linux的指定路径 通过网络学习 需要新增一个ftp账户 需要在 etc ssh sshd config中新增几条命令 Subsystem sftp internal sft
  • 信息网络向价值网络演进过程中产品形态的思考

    随着Facebook品牌更名Meta 持续火爆了一年多的元宇宙概念迎来了互联网巨头的正名 全球互联网生态产品将迎来怎样的新一轮大跃进 本文整理自Contentbox VP Castbox亚洲地区负责人杨霄在量江湖 拍乐云主办的 社交产品如何
  • java 加解密实例(对称——非对称)

    加密算法有很多种 这里只大约列举几例 1 消息摘要 数字指纹 既对一个任意长度的一个数据块进行计算 产生一个唯一指纹 MD5 SHA1 发送给其他人你的信息和摘要 其他人用相同的加密方法得到摘要 最后进行比较摘要是否相同 2 单匙密码体制
  • git本地仓库基本操作--查看提交历史和版本回退前进

    1
  • 版本问题导致 导入vue报错:Uncaught TypeError: Vue is not a constructor

    版本问题导致 导入vue报错 Uncaught TypeError Vue is not a constructor 浏览器控制台错误信息 问题代码 某博客带来的启发 解决方案 附录 vue2生产环境部分代码 vue3生产环境部分代码 浏览
  • window7 配置telnet 服务

    第一步 点击开始 选择控制面板 第二步 选择 程序 选择打开或关闭windows 功能 在选择对话框中勾选Telnet客户端和Telnet服务端 第三步 点击 计算机 管理 属性 修改Telnet服务的启动方式 第四步 判断Telnet服务
  • [LeetCode] Reverse Linked List I II - 链表翻转问题

    题目概述 Reverse a singly linked list 翻转一个单链表 如 1 gt 2 输出 2 gt 1 1 gt 2 gt 3 输出3 gt 2 gt 1 题目解析 本人真的比较笨啊 首先想到的方法就是通过判断链尾是否存在
  • MySQL中的正斜杠和反斜杠

    目录 问题背景 问题提出 1 为什么书上的这种方法得不到正确的数据呢 2 是因为DBMS的问题嘛 3 如何在MySQL上得到正确的数据呢 问题总结 问题背景 今天数据库老师留了一道实验题 如下 14 查询 A C 课程的课程号和学分 如果没
  • 初识C++Primer plus

    写在前面 从事c 编程转眼也快一年了 一直从事工厂数据采集工作 然而就与硬件交互效率来说 无疑c c 与硬件更加契合 就很任性的买了一本c Primer plus 第六版 希望自己在博客里能坚持下去 将自己所悟所感写在这里与大家分享 分割线
  • 飞驰的高铁-第15届蓝桥杯第一次STEMA测评Scratch真题精选

    导读 超平老师的 Scratch蓝桥杯真题解析100讲 已经全部完成 后续会不定期解读蓝桥杯真题 这是Scratch蓝桥杯真题解析第150讲 飞驰的高铁 本题是2023年8月20日举行的第15届蓝桥杯STEMA测评Scratch编程中级组编
  • 源码大杀器:怎样查看源码

    一 以SpringBoot来分析下 首先获取到源码 二 点击GitHub获取源码 三 下载源码 SpringSpace 11 24 24 ls emptydemo springdemo gs accessing data jpa maste
  • 【Python网络爬虫与信息提取】Scrapy爬虫框架

    1 理论知识 pip install scrapy i http pypi douban com simple trusted host pypi douban com scrapy h scrapy startproject python
  • 第五章 初始化与清理(下)

    第五章 初始化与清理 现在总结的东西很多都需要用代码来帮助理解了 所以会有大量的测试代码 不过这中方式非常有用 如果认真敲过一遍之后 并且将这些代码弄清楚了 我相信你一定会对书中描述的内容有一个更清楚的认识 我是在eclipse工具上进行测
  • requests.session()会话保持

    可能大家对session已经比较熟悉了 也大概了解了session的机制和原理 但是我们在做爬虫时如何会运用到session呢 就是接下来要讲到的会话保持 首先说一下 为什么要进行会话保持的操作 requests库的session会话对象可
  • Flink如何连接hive

    回顾在上篇文章中 笔者使用的 CDH 版本为 5 16 2 其中 Hive 版本为 1 1 0 CDH 5 x 系列 Hive 版本都不高于 1 1 0 是不是不可理解 Flink 源代码本身对 Hive 1 1 0 版本兼容性不好 存在不
  • 测绘eps软件快捷键_行业内三款常用软件快捷键汇总整理及自定义设置

    今天小编要和各位看官分享的是测绘行业内三款常用软件的快捷键 这三款常用软件分别是CASS CAD EPS ARCGIS 快捷键是提高绘图速度 提升作业效率的不二法宝 小编也经常在给朋友们说一定要学会使用快捷键 特别是左手键的用法 今天我们就
  • 学习python过程中的心得体会和收获,也说一下好处坏处

    首先 Python是一种流行的编程语言 用于数据分析 机器学习 人工智能等领域 Python的语法简单易懂 易于学习和理解 这使得它成为许多初学者的首选编程语言 对于初学者来说 建议从基础开始学习 例如语法 数据类型 控制流等 同时 也要多
  • Linux下使用《du》命令查看某文件及目录的大小

    du ah max depth 1 这个是我想要的结果 a表示显示目录下所有的文件和文件夹 不含子目录 h表示以人类能看懂的方式 max depth表示目录的深度 du sh 目录 查看目录的大小 du sh 文件 查看文件大小 du命令用
  • Go语言学习史诗级教程-带你领略GoLang语言新世界

    Go基础 下载Go语言开发工具 下载Go语言环境 下载地址 https golang google cn dl 下载Go语言开发工具 下载地址 https www jetbrains com go 第一个Go语言代码 package mai
  • OAuth2 授权码模式为什么不直接返回access_token

    https www cnblogs com erichi101 p 13497971 html OAuth2的实际应用中 最常见的就是 授权码模式 了 微博是这种模式 微信也是这种模式 总结来说 就是简单的二步 1 获取code 2 根据c