请求SharePoint登录端点?wa=wsignin1.0返回403的问题求助
背景
两周前仍可通过SOAP API(而非REST)获取多个SharePoint列表数据,原身份验证流程如下:
1. 获取安全令牌
向https://login.microsoftonline.com/extSTS.srf发送SOAP请求获取安全令牌:
url = "https://login.microsoftonline.com/extSTS.srf" body = """ <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> <s:Header> <a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</a:Action> <a:ReplyTo> <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address> </a:ReplyTo> <a:To s:mustUnderstand="1">https://login.microsoftonline.com/extSTS.srf</a:To> <o:Security s:mustUnderstand="1" xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"> <o:UsernameToken> <o:Username>%s</o:Username> <o:Password>%s</o:Password> </o:UsernameToken> </o:Security> </s:Header> <s:Body> <t:RequestSecurityToken xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust"> <wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"> <a:EndpointReference> <a:Address>%s</a:Address> </a:EndpointReference> </wsp:AppliesTo> <t:KeyType>http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey</t:KeyType> <t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType> <t:TokenType>urn:oasis:names:tc:SAML:1.0:assertion</t:TokenType> </t:RequestSecurityToken> </s:Body> </s:Envelope>""" % ( escape(self.username), escape(self.password), self.domain, )
headers = {"accept": "application/json;odata=verbose"} response = requests.post(url, body, headers=headers) xmldoc = etree.fromstring(response.content) token = xmldoc.find( ".//{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd}BinarySecurityToken" ) if token is not None: return token.text else: message = xmldoc.findall( ".//{http://schemas.microsoft.com/Passport/SoapServices/SOAPFault}text" ) if len(message) < 1: raise Exception( "Error authenticating against Office 365. Was not able to find an error code. Here is " "the SOAP response from Office 365", response.content, ) raise Exception( "Error authenticating against Office 365. Error from Office 365:", message[0].text, )
2. 获取登录Cookie
使用安全令牌访问SharePoint登录端点{domain}/_forms/default.aspx?wa=wsignin1.0获取Cookie:
sectoken = self._get_security_token() url = self.domain + "/_forms/default.aspx?wa=wsignin1.0" cookies = requests.post(url, data=sectoken).cookies self.cookies = cookies
当前问题
- 获取到的Cookie为空(
<RequestsCookieJar[]>),无法完成身份验证 - 调用SharePoint的
GetList接口(访问{site}/_vti_bin/lists.asmx)返回403错误,相关代码:
def _get_fields(self, list_name): """Get Info on Current List""" # Build Request soap_request = Soap("GetList") soap_request.add_parameter("listName", list_name) headers = { "Content-Type": "text/xml; charset=UTF-8", "SOAPAction": "http://schemas.microsoft.com/sharepoint/soap/" + "GetList", } # Send Request response = requests.post( url=self.site + "/_vti_bin/lists.asmx", headers=headers, cookies=self.cookies, data=str(soap_request).encode("utf-8"), verify=True, # per defecte es true, canviar sino timeout=600, ) # Parse Response envelope = etree.fromstring( response.text.encode("utf-8"), parser=etree.XMLParser(huge_tree=False, recover=True), ) # type: etree.ElementTree _list = envelope[0][0][0][0] fields = [] for row in _list.xpath( "//*[re:test(local-name(), '.*Fields.*')]", namespaces={"re": "http://exslt.org/regular-expressions"}, )[0].getchildren(): fields.append({key: value for (key, value) in row.items()}) return response
- 浏览器访问
https://domain.sharepoint.com//%5C_forms/default.aspx?wa=wsignin1.0时,报错:贵组织的安全策略不允许使用这种旧版身份验证方法。如需帮助,请联系IT部门。 - 确认组织未进行任何设置变更,两周前流程正常运行
解决建议
1. 排查微软全局旧版认证禁用情况
微软近期在逐步淘汰旧版身份验证协议(如基于用户名密码的SOAP令牌认证),即使组织未手动调整设置,也可能因全局安全政策更新被强制禁用:
- 联系租户管理员,检查Azure AD中的旧版身份验证设置:进入Azure门户→Azure Active Directory→安全性→条件访问→策略,确认是否有禁止旧版认证的策略生效;同时检查身份验证方法中的配置,确保未阻止用户名密码认证。
- 查看Microsoft 365管理中心的消息中心,是否有关于旧版身份验证停用的官方通知。
2. 迁移到现代身份验证方案
替换原SOAP令牌认证,采用OAuth 2.0的两种主流流:
- Client Credentials流:适合后台服务场景,无需用户交互。需在Azure AD中注册应用,授予SharePoint的
Sites.Read.All等应用权限,获取Access Token后,调用SOAP API时在请求头添加Authorization: Bearer {access_token},无需依赖Cookie。 - Authorization Code流:适合需要用户登录的场景,通过用户授权获取令牌。
示例(Client Credentials流获取令牌):
import requests import json tenant_id = "你的租户ID" client_id = "你的应用客户端ID" client_secret = "你的应用客户端密钥" scope = "https://你的域名.sharepoint.com/.default" token_url = f"https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token" payload = { "grant_type": "client_credentials", "client_id": client_id, "client_secret": client_secret, "scope": scope } response = requests.post(token_url, data=payload) access_token = response.json().get("access_token")
调用GetList接口时修改请求头:
headers = { "Content-Type": "text/xml; charset=UTF-8", "SOAPAction": "http://schemas.microsoft.com/sharepoint/soap/GetList", "Authorization": f"Bearer {access_token}" }
3. 修正登录端点URL
浏览器访问的URL存在多余斜杠和转义字符:https://domain.sharepoint.com//%5C_forms/default.aspx?wa=wsignin1.0,正确端点应为https://domain.sharepoint.com/_forms/default.aspx?wa=wsignin1.0,先修正URL后重新测试原流程,确认是否因URL错误导致Cookie获取失败。
4. 检查账号MFA状态
若账号被强制启用多重身份验证(MFA),原用户名密码的SOAP认证流程会直接失效,需确认账号MFA状态,若已启用则必须使用支持MFA的现代身份验证方案。
内容的提问来源于stack exchange,提问作者Raúl Ramírez
相关产品推荐
相关产品推荐

