如何从本地 SharePoint 2013 和 ADFS 获取 FedAuth Cookie

Posted

技术标签:

【中文标题】如何从本地 SharePoint 2013 和 ADFS 获取 FedAuth Cookie【英文标题】:How to obtain FedAuth Cookie From On Premise SharePoint 2013 and ADFS 【发布时间】:2014-10-09 22:51:23 【问题描述】:

我有一个使用 windows server 2012 R2、ADFS 和 sharepoint 2013 设置的测试环境。我可以使用 ADFS 作为声明身份提供程序成功登录到 Sharepoint 2013。现在我正在尝试从我的 C# 应用程序登录到 Sharepoint。

我可以使用以下命令从 adfs 请求 saml 断言令牌。

现在我想帮助我将 saml 令牌发布到 SharePoint 并检索 FedAuth cookie,以便我可以被动登录到 SharePoint 2013 并从 C# 应用程序上传文档。

当我调用最后一个方法 PostSharePointSTS() 时没有设置 Cookie。

大部分代码已经得到Leandro Boffi的帮助

[TestMethod]
public void GetSamlTestMethod()

  var client = new WebClient();

  client.Headers.Add("Content-Type", "application/soap+xml; charset=utf-8");
  string username = "Administrator@2012r2.local";
  string password = "Password1";
  string adfsServer = "https://logon.2012r2.local/adfs/services/trust/2005/UsernameMixed";
  string sharepoint = "https://portal.2012r2.local/_trust/";
  var samlRequest = GetSAML()
    .Replace("[Username]", username)
    .Replace("[Password]", password)
    .Replace("[To]", adfsServer)
    .Replace("[applyTo]", sharepoint);

  var result = client.UploadString(
          address: "https://logon.2012r2.local/adfs/services/trust/2005/UsernameMixed",
          method: "POST",
          data: samlRequest);

          PostSharePointSTS( GetSAMLAssertion(result) );


private static string GetSAMLAssertion(string response)


  XDocument samlResponse = XDocument.Parse( response);

  // Check response xml for faults/errors
  if(samlResponse.Root == null)
    throw new ApplicationException("Invalid response received from authentication service.");

  XNamespace s = "http://www.w3.org/2003/05/soap-envelope";
  XNamespace psf = "http://schemas.microsoft.com/Passport/SoapServices/SOAPFault";
  XNamespace wst = "http://schemas.xmlsoap.org/ws/2005/02/trust"; // "http://docs.oasis-open.org/ws-sx/ws-trust/200512";// 
  XNamespace wsp = "http://schemas.xmlsoap.org/ws/2004/09/policy";
  XNamespace wsa = "http://www.w3.org/2005/08/addressing";
  XNamespace wsse = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
  const string saml = "urn:oasis:names:tc:SAML:1.0:assertion";

  // the logon token is in the SAML assertion element of the message body
  XDocument xDoc = XDocument.Parse(response, LoadOptions.PreserveWhitespace);
  var assertion = from e in xDoc.Descendants()
                  where e.Name == XName.Get("Assertion", saml)
                  select e;

 string samlAssertion = assertion.FirstOrDefault().ToString();     

  // for some reason the assertion string needs to be loaded into an XDocument
  // and written out for for the XML to be valid. Otherwise we get an invalid
  // XML error back from ADFSs
  XDocument doc1 = XDocument.Parse(samlAssertion);
  samlAssertion = doc1.ToString(SaveOptions.DisableFormatting);
  return samlAssertion;





   private static string GetSAML()
    
      const string saml = @"<?xml version='1.0' encoding='utf-8' ?>

<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'>[To]</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>[Username]</o:Username>
                <o:Password>[Password]</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>[applyTo]</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>";
      return saml;
    
private static void PostSharePointSTS(string assertion)


  // Submit the BinarySecurityToken to SPO and retrieve response
 var loginUri = new Uri("https://logon.2012r2.local/adfs/ls?wa=wsignin1.0&wtrealm=urn:sharepoint:portal");
  var requestCookies = new CookieContainer();

  var request = (HttpWebRequest)WebRequest.Create(loginUri);
  request.AllowAutoRedirect = false;
  request.ContentType = "application/x-www-form-urlencoded";
  request.ContentLength = assertion.Length;
  request.CookieContainer = requestCookies;
  request.Method = "POST";
  request.UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)";

  using(var requestWriter = new StreamWriter(request.GetRequestStream()))
  
    requestWriter.Write(assertion);
    requestWriter.Close();
  

  var response = (HttpWebResponse)request.GetResponse();
  switch(response.StatusCode)
  
    case HttpStatusCode.OK:
    case HttpStatusCode.Found:
    break;

    // TODO: Log error?
    //default:
    //return false;
  


当我尝试将给定的 SAML 令牌发布到 SharePOint 时,我得到以下信息。但是没有设置 cookie。

HTTP/1.1 302 Found
Content-Length: 0
Content-Type: text/html; charset=utf-8
Location: https://logon.2012r2.local:443/adfs/ls/wia?wa=wsignin1.0&wtrealm=urn:sharepoint:portal
Server: Microsoft-HTTPAPI/2.0
Date: Sat, 16 Aug 2014 10:55:51 GMT

    This response did not set any cookies.
This response did not contain a P3P Header.

Validate P3P Policies at: http://www.w3.org/P3P/validator.html
Learn more at: http://fiddler2.com/r/?p3pinfo

【问题讨论】:

您找到解决此问题的方法了吗? 【参考方案1】:

您为什么不直接使用标准的 SharePoint CSOM 库在 SharePoint 中做任何您想做的事情? CSOM 代表用户在 SharePoint 端自动执行所有必要的 ADFS 交互。

【讨论】:

你能举一个这个魔法的例子吗?我发现事实恰恰相反。事实上,有很多方法可以设置联合身份验证,它们不提供实现。 你想达到什么目的?您写道“现在我正在尝试从我的 C# 应用程序登录到 Sharepoint。”那怎么办? “登录”不是目的,您显然想在那里做一些事情:上传文件,读取列表项等。

以上是关于如何从本地 SharePoint 2013 和 ADFS 获取 FedAuth Cookie的主要内容,如果未能解决你的问题,请参考以下文章

如何使用oData和JavaScript从Sharepoint 2013中的列表检索数据

JavaScript 如何使用oData和JavaScript从Sharepoint 2013中的列表中检索数据

如何从处理此事件的方法中将单击按钮的 ID 检索到 SharePoint 2013 Web 部件中?

如何使用 CSOM 从/向 SharePoint 2013 下载/上传文件?

将 SharePoint 2013 WSP(Web 部件)迁移到 SharePoint 2019(本地)[关闭]

Sharepoint 2013 本地 NewForm 列表 javascript 逻辑未触发