通过OAuth2登录Microsoft返回200而非302,程序化认证失败求助
搞定Python2 requests调用Microsoft OAuth2授权端点的问题
嘿,先给你点透核心问题:直接用requests请求/oauth2/authorize端点是拿不到授权码的,这跟重定向请求头半毛钱关系都没有。
为啥浏览器里能正常跑?因为浏览器会帮你展示Microsoft的登录页面,让你输入账号密码完成认证,之后才会跳转到你指定的redirect_uri并带上授权码。但requests是个无界面的HTTP工具,它没法处理这个需要用户手动操作的登录环节——哪怕它默认就允许重定向(allow_redirects=True是默认配置,不用额外加请求头),最终也只能拿到登录页面的HTML代码,根本到不了带授权码的重定向URL。
那该怎么解决?给你两个靠谱方案:
方案一:用浏览器自动化工具(适合需要用户在当前设备登录的场景)
比如用Selenium,它能打开真实的浏览器窗口,模拟用户操作。你可以让它加载授权URL,等用户完成登录后,抓取重定向后的URL提取授权码。Python2的示例代码大概是这样:
from selenium import webdriver import time # 初始化Chrome浏览器(记得装对应版本的chromedriver) driver = webdriver.Chrome() # 替换成你的完整授权URL auth_url = "https://login.microsoftonline.com/0000-0000-0000-0000/oauth2/authorize?response_type=code&client_id=0000-0000-0000-0000-0000&response_mode=query&redirect_uri=YOUR_REDIRECT_URI&scope=YOUR_REQUIRED_SCOPES" driver.get(auth_url) # 留30秒让用户手动完成登录(也可以加自动填充代码,但生产环境别这么干,不安全) time.sleep(30) # 获取登录后的重定向URL current_url = driver.current_url # 提取授权码 if "code=" in current_url: auth_code = current_url.split("code=")[1].split("&")[0] print("拿到授权码啦:", auth_code) driver.quit()
方案二:用设备授权流(适合无界面脚本/后台服务)
如果你的应用是跑在没有界面的服务器上,没法用浏览器,那可以用Microsoft支持的设备授权流。这个流程会让你输出一个验证码和URL,用户在任意设备的浏览器里打开这个URL输入验证码完成登录,你的脚本只需要轮询Microsoft的端点就能拿到授权码。这种方式完全不需要界面,更适合自动化场景。
最后再提几个注意点:
- 确保Azure AD里配置的
redirect_uri和你请求里的参数完全一致,差一点都不行; - Python2已经彻底停止维护了,赶紧迁移到Python3吧,不然以后踩坑都没地方找解决方案;
- 授权码是一次性的,拿到后要立刻用它请求访问令牌,千万别泄露出去,不然别人能冒充你的应用。
内容的提问来源于stack exchange,提问作者Ismail Addou




