代码之家  ›  专栏  ›  技术社区  ›  Iñaki Elcoro

Sharepoint Office 365 OAuth服务对list.asmx的身份验证

  •  5
  • Iñaki Elcoro  · 技术社区  · 9 年前

    我正在尝试从外部网站访问Office 365中的Sharepoint列表数据。我在Azure Active Directory中注册了我的应用程序,我完成了创建和信任证书以及获取访问令牌的所有过程。

    Add-Type -Path ".\Microsoft.IdentityModel.Clients.ActiveDirectory.dll"
    
    $authenticationContext = New-Object Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext -ArgumentList "https://login.microsoftonline.com/{myTenantId}/", $false
    
    $cer = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
    $cer.Import(".\WithPrivateKey.pfx", "privateKey", [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::MachineKeySet)
    
    $clientAssertion = New-Object Microsoft.IdentityModel.Clients.ActiveDirectory.ClientAssertionCertificate -ArgumentList "{myClientId}", $cer
    
    $authenticationResult = $authenticationContext.AcquireToken("https://{tenantName}.sharepoint.com", $clientAssertion)
    
    $headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
    $headers.Add("Authorization", "Bearer " + $authenticationResult.AccessToken)
    

    通过在请求头中显示访问令牌,我可以成功地调用Sharepoint REST Api。

    $response = Invoke-RestMethod -Uri https://{myTenantName}.sharepoint.com/sites/devSite/_vti_bin/ListData.svc/TestList -Method Get -Headers $headers 
    

    然而,我不能用同样的方法访问asmx端点,例如列表。asmx,每当我试图调用这些服务上的任何方法时,我都会得到401未授权

    $body = '<?xml version="1.0" encoding="utf-8"?>
    <soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
      <soap12:Body>
        <GetList xmlns="http://schemas.microsoft.com/sharepoint/soap/">
          <listName>TestList</listName>
        </GetList>
      </soap12:Body>
    </soap12:Envelope>'
    
    $response = Invoke-WebRequest -Uri https://{myTenantName}.sharepoint.com/sites/site/_vti_bin/Lists.asmx -Method Post -ContentType 'application/soap+xml' -Headers $headers -Body $body
    
    2 回复  |  直到 9 年前
        1
  •  13
  •   Iñaki Elcoro    9 年前

    在深入研究了.net Sharepoint客户端sdk之后,我发现SharepointOnlineCredential类是如何做到的,从而允许访问Sharepoint SOAP服务。

    因此,正如费雪已经说过的,Azure AD令牌对于访问Sharepoint SOAP服务是无效的(尽管令牌对于允许访问REST服务是有效的…)。要访问Sharepoint Online服务,您需要通过请求用户同意或直接使用已知用户和密码来使用某种声明身份验证。

    由于我们不能在我们的php应用程序中使用.net SDK,我们已经研究了SDK如何在直接使用用户凭据时创建请求以获得身份验证:

    首先将身份验证凭据作为SAML WSSecurity POST请求发送到身份验证端点 https://login.microsoftonline.com/rst2.srf :

    POST https://login.microsoftonline.com/rst2.srf 
    Content-Type: application/soap+xml; charset=utf-8
    Content-Length: [calculate]
    Host: login.microsoftonline.com
    
    <?xml version="1.0" encoding="UTF-8"?>
    <S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:wst="http://schemas.xmlsoap.org/ws/2005/02/trust">
      <S:Header>
        <wsa:Action S:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</wsa:Action>
        <wsa:To S:mustUnderstand="1">https://login.microsoftonline.com/rst2.srf</wsa:To>
        <ps:AuthInfo xmlns:ps="http://schemas.microsoft.com/LiveID/SoapServices/v1" Id="PPAuthInfo">
          <ps:BinaryVersion>5</ps:BinaryVersion>
          <ps:HostingApp>Managed IDCRL</ps:HostingApp>
        </ps:AuthInfo>
        <wsse:Security>
                <wsse:UsernameToken wsu:Id="user">
                    <wsse:Username>[user]</wsse:Username>
                    <wsse:Password>[password]</wsse:Password>
                </wsse:UsernameToken>                
    </wsse:Security>
      </S:Header>
      <S:Body>
        <wst:RequestSecurityToken xmlns:wst="http://schemas.xmlsoap.org/ws/2005/02/trust" Id="RST0">
          <wst:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</wst:RequestType>
          <wsp:AppliesTo>
            <wsa:EndpointReference>
              <wsa:Address>sharepoint.com</wsa:Address>
            </wsa:EndpointReference>
          </wsp:AppliesTo>
          <wsp:PolicyReference URI="MBI"></wsp:PolicyReference>
        </wst:RequestSecurityToken>
      </S:Body>
    </S:Envelope>
    

    xml格式的响应将包含安全令牌:

    ....
    <wst:RequestedSecurityToken>
        <wsse:BinarySecurityToken Id="Compact0">t=EwA4A06hBwAUNfDkMme61kIdXqvj9tWnUbHtXWEAAREB5clgLb8J/VvxRFIKLUnd9SRyoBHmTHFk0viit2FMlGXak5NJKJhicT8MiZmgA2HoTrJM1EgXCNUpmWqrX1LQRNfs0PHEV4XncjI9lnphsSTiFSCDjmdCKtW4TmV8n18xJHvBtDUWdvCT2lBti8/gf1oiqD5lQBPtxr+d4OwNtJHADEKpC/YIoatcKqgxI480tlWOZHpEL1wifo5EDMDRRc985ObMCZ31fPdSpA7WIbDzlZYX9ou6Cq7EybrIHsAcr5cPIJ8y0FRUacma9+dMxqr/lILAIyAYz/GdTNffa2Q3zJOSWW5RcnigtCApHgf83HjW8DqC6NgTrXs6rpUDZgAACC/4JZlSLB3JCALIntkKmNtRl2JLvwUljkXrP5jg5ipK/J/fGF3oc46aP/YT3VnrrD6TCV5ZECki5ycYZ6JR5RDK6OSqI9c5FDfFS/YmSCcdcaJ1cG2Ug3Oz3w14mznYGwmvrgyGvw35aoyjnKZALw8OQ2Ddi97gbe03L4rrM7CxTGwEPgoKCK7USkwxZT+myLJASVhd29+eNsTqd7wuphhLrzbgYZ+7swlJb3oIJw/2T7YvJ4fTPByaLxGaBt7iry74aSh/RnXdH3snOQnsr63bXqqoDJGcj7A3aIpElw2LlW2/PGh84zke3corp2q/jg7PEKCnV8PYN2xiwSfqY9vNCny14xhHEPsK8FWDBOPDpgeC18qz+FpTN0rGUMXl20bxJGxGqnQ+s8k0Gu9yTxoZKWPSeVihJk6qUQo6KJb/NE/QRco94QDUjMYi+gccGN0D1ouUe+O0fb0InXeM+98qfXJLQAjoUtgS8rRJUAqFk5XVwebGbx0ICRv3Q/wiJ7T5yUryMBTtwbaGf/07QuGTv9CW2UTsV9zT1nMSRDfUpelZrgZt6huLnDRLC8yVHfXjndMwONdymxWcD9sLb8EcNmTUFHDfBrv8XFb50PNJAV4qvK8CgVmWu2C2GWXoZfYkaR6o6jpliQdT5NcNnb9wNy36OqDnIWl0ZNM1SOzVX0yQOLeaf8+1bslaafyYMAbhcAI=&amp;p=
       </wsse:BinarySecurityToken>
    </wst:RequestedSecurityToken>                
    ...
    

    然后,使用从先前响应中提取的安全令牌,您需要向租户凭据端点发送GET请求: https://yourtenantname.sharepoint.com/_vti_bin/idcrl.svc/

    您需要发送一个Authorization头,格式为: BPOSIDCRL+空格+标记 。例如:

    GET https://yourtenantname/_vti_bin/idcrl.svc/ 
    Host: yourtenant.sharepoint.com
    Authorization: BPOSIDCRL t=EwA4A06hBwAUNfDkMme61kIdXqvj9tWnUbHtXWEAAREB5clgLb8J/VvxRFIKLUnd9SRyoBHmTHFk0viit2FMlGXak5NJKJhicT8MiZmgA2HoTrJM1EgXCNUpmWqrX1LQRNfs0PHEV4XncjI9lnphsSTiFSCDjmdCKtW4TmV8n18xJHvBtDUWdvCT2lBti8
    

    对这个请求的响应将设置一个cookie,我们需要在接下来对soap服务的请求中捕获并使用该cookie:

    Set-Cookie: SPOIDCRL=77u/PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48U1A+VHJ1ZSwwaC5mfG1lbWJlcnNoaXB8MTAwMzdmZmU5NTc2YzdlZUBsaXZlLmNvbSwwIy5mfG1lbWJlcnNoaXB8Y2xvdWRAYXNlbWJsaWFkZXYub25taWNyb3NvZnQuY29tLDEzMTAxMjE4ODQ0Mzc0NDcxMjsxMzA5NTg5NTQ0NTAwMDAwMDAsRmFsc2UsUCtRcmlFSFRkRnZCNkJEREZFek1mK3RVaGlzZTZtdnl1R0N4aXpjaWpyRUdxZk1BN1RpdTJNdGN0VE42TVNjdi9Cbjd2OXRxS2VPaTBzWTdlTnRqNkFESmRubFM2S0ttVjdoeHRWNjdtY3FlQVQzYWJGeDFEVFd5dEJsOWZ3MDJkZ2JTakV3eUM3WTRIWXg0ek5UYUtvUTZacGFXR0NjZ0svZEtEbloya3ozdGFBblVPM1gvUkxBeUorYkZac2RGclBCRGF4aDNTMGpBTml2VTBzb0pJR0FFRmdsQzVaMWhxU28rekZFMU5UV01oMXphMjNPYUU0TjJUNHVjd1BlaEREKzR4Ry9yMWdXMC9zOWdTaGxTMlc1U29iVDhTY2NyYi80aG9Xb1Y2TWxva0t1bXBNOWc4cCtxb0xFL3dtaElDUm9MRGhQSXR1anhoSjlqb2lZY1RBPT0saHR0cHM6Ly9hc2VtYmxpYWRldi5zaGFyZXBvaW50LmNvbS9fdnRpX2Jpbi9pZGNybC5zdmMvPC9TUD4=; path=/; secure; HttpOnly
    

    最后,通过将此cookie附加到Sharepoint Services的每个请求,我们可以得到经过验证的响应:

    POST https://yourtenantname.sharepoint.com/_vti_bin/Lists.asmx HTTP/1.1
    Host: yourtenantname.sharepoint.com
    Content-Type: application/soap+xml; charset=utf-8
    Content-Length: [calculate]
    Cookie: SPOIDCRL=77u/PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48U1A+VHJ1ZSwwaC5mfG1lbWJlcnNoaXB8MTAwMzdmZmU5NTc2YzdlZUBsaXZlLmNvbSwwIy5mfG1lbWJlcnNoaXB8Y2xvdWRAYXNlbWJsaWFkZXYub25taWNyb3NvZnQuY29tLDEzMTAxMjExNjM5MjM3NTM1ODsxMzA5NTg5NTQ0NTAwMDAwMDAsRmFsc2UsdEFEQUZZSnZiMFF6cWxFSFlKOGRPN1d1cnJ5RzJvcGxTelBueWFMUzhrNitjenBGT0JVK292M1VkSWhydGU3TXFMOHRJaFFzazRrNHd5REFqMklDUDcyMWpES3hKWmZRZjdaUlZQeisrUi92c09Qak13em5ITkg4bHVEQXdKcVlLdE16NStoaU84cUtTRzNZWEJYbWF4SDk1cDZtSDlaMVRzaFVDRXZMZ3ZIbkt6aWlPclh4UDE2RDBmZHlTRWxsU0Radmt2Tkg0UHBLT2VGbjI5S25qSk9veDVha21TZVlIbTY2ZnF5S0tpOUJmMHdjRmlyelNRZzBWZTc4NW1JZ1ZaQUY2VTArVEI0QVRvVXRVVFFqTnd4ODJEZE9jbWlqQ25NUTUzUHUrWEFIT25lenFVb1dPTXovVWk5V2VSTUMvMWZiOUpsUmZMNlZaNjNaZDRVazB3PT0saHR0cHM6Ly9hc2VtYmxpYWRldi5zaGFyZXBvaW50LmNvbS9fdnRpX2Jpbi9pZGNybC5zdmMvPC9TUD4=; path=/; secure; HttpOnly
    
    <?xml version="1.0" encoding="utf-8"?>
    <soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
      <soap12:Body>
        <GetListCollection xmlns="http://schemas.microsoft.com/sharepoint/soap/" />
      </soap12:Body>
                    </soap12:Envelope>
    
        2
  •  0
  •   Fei Xue    9 年前

    ADAL从Azure AD获取的令牌仅用于Office 365 REST API(上面的代码使用OAuth2.0,它为REST API获取JSON湿令牌)。此令牌不适用于SharePoint web服务。

    要使用SharePoint web服务,我们需要使用 SharePoint声明身份验证。有关SharePoint身份验证的详细信息,请参阅以下链接:

    https://msdn.microsoft.com/en-us/library/hh147177.aspx#SPO_RA_OverviewSPAuthentication