You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

请求SharePoint登录端点?wa=wsignin1.0返回403的问题求助

SharePoint SOAP API身份验证失败问题

背景

两周前仍可通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 08:44:55