SharePoint 2013中的联合身份验证(使用ADFS) - 获取FedAuth cookie时的操作超时

时间:2015-10-20 12:44:18

标签: c# sharepoint-2013 adfs

我们在使用SharePoint集成代码时遇到了一些奇怪的问题。

我们已设法使用SAML令牌进行集成,请参阅下面的代码。

问题在于,有时它会在获取FedAuth cookie或向SharePoint发出请求时超时。

超时可能指向加载或网络问题,但它们是可重现的。

单元测试套件上的第一个单元测试每次都会获得cookie而没有任何问题,但是第二次单元测试失败了。

为了让这更加神秘,只要我有小提琴手捕获流量,它似乎工作正常。

更令人烦恼的是,如果我运行第二次单元测试而不是第一次,测试工作正常。

就好像SharePoint拒绝为同一个客户端发出另一个cookie,直到经过一定的时间,除非通过Fiddler。

我应该补充一点,我已经尝试了为后续请求存储cookie并为每个请求再次获取它,它似乎没有任何区别。

任何帮助都将不胜感激。

public static ClientContext CreateClientContext(SharePointClaimsConnection connection)
    {
        if (connection == null)
        {
            throw new ArgumentNullException("connection");
        }           

        logger.DebugFormat("Create Client Context for connection: {0}", connection);

        ClientContext context = new ClientContext(connection.WebUrl);

        try
        {
            if (connection.SecurityTokenServiceEndPoint != null && !String.IsNullOrEmpty(connection.Realm))
            {
                CookieInfo token = GetToken(connection);

                if (token == null)
                {
                    lock (syncRoot)
                    {
                        token = GetToken(connection);

                        if (token == null)
                        {
                            token = GetFedAuthCookie(connection);

                            if (token != null)
                            {
                                tokens[connection] = token;
                            }
                        }
                    }
                }

                if (token != null)
                {

                    context.ExecutingWebRequest += (s, e) =>
                    {
                        e.WebRequestExecutor.WebRequest.KeepAlive = true;

                        for (int i = 0; i < e.WebRequestExecutor.WebRequest.Headers.Count; i++)
                        {
                            string key = e.WebRequestExecutor.WebRequest.Headers.GetKey(i);
                            string value = e.WebRequestExecutor.WebRequest.Headers.Get(i);
                            logger.DebugFormat("Key: {0}, Value: {1}", key, value);
                        }

                        CookieContainer container = new CookieContainer();

                        foreach (var cookie in token.Cookies)
                        {
                            logger.Debug("Adding cookie: " + cookie.Name);
                            logger.Debug("Domain: " + connection.WebUrl.Host);
                            logger.Debug("Expires: " + cookie.Expires.ToString());

                            Cookie newCookie = new Cookie(cookie.Name, cookie.Value);
                            newCookie.Expires = DateTime.MaxValue;
                            newCookie.Path = "/";
                            newCookie.Secure = true;
                            newCookie.HttpOnly = true;
                            newCookie.Domain = connection.WebUrl.Host;
                            container.Add(newCookie);
                        }

                        e.WebRequestExecutor.WebRequest.CookieContainer = container;
                    };
                }
            }

            return context;
        }
        catch (Exception ex)
        {                
            if (context != null)
            {
                context.Dispose();
            }

            throw;
        }

    }

 private static CookieInfo GetFedAuthCookie(SharePointClaimsConnection connection)
    {

        string result = GetSamlToken(connection);

        //Take this token and pass it to SharePoint STS
        string stringData = String.Format(CultureInfo.InvariantCulture, "wa=wsignin1.0&wctx={0}&wresult={1}",
            HttpUtility.UrlEncode(new Uri(connection.WebUrl, "/_layouts/Authenticate.aspx?Source=%2F").ToString()),
            HttpUtility.UrlEncode(result));
        HttpWebRequest sharepointRequest = HttpWebRequest.Create(new Uri(connection.WebUrl, "/_trust/")) as HttpWebRequest;
        sharepointRequest.Method = "POST";
        sharepointRequest.ContentType = "application/x-www-form-urlencoded";
        sharepointRequest.CookieContainer = new CookieContainer();
        sharepointRequest.AllowAutoRedirect = false; // This is important

        using (Stream newStream = sharepointRequest.GetRequestStream())
        {
            byte[] data = Encoding.UTF8.GetBytes(stringData);
            newStream.Write(data, 0, data.Length);
        }

        HttpWebResponse webResponse = sharepointRequest.GetResponse() as HttpWebResponse;

        if (webResponse.Cookies["FedAuth"] == null)
        {
            return null;
        }

        return new CookieInfo()
        {
            Cookies = webResponse.Cookies.Cast<Cookie>().ToList(),
        };
    }

    private static string GetSamlToken(SharePointClaimsConnection connection)
    {
       string result;

        Uri STSService = new Uri(connection.SecurityTokenServiceEndPoint, WindowsTransport);

        using (WSTrustChannelFactory trustChannelFactory = new WSTrustChannelFactory(
            new WindowsWSTrustBinding(SecurityMode.Transport),
            new EndpointAddress(STSService)))
        {
            trustChannelFactory.TrustVersion = System.ServiceModel.Security.TrustVersion.WSTrust13;
            trustChannelFactory.Credentials.SupportInteractive = false;
            trustChannelFactory.ConfigureChannelFactory<IWSTrustChannelContract>();

            //Request Security Token
            RequestSecurityToken rst = new RequestSecurityToken();
            rst.KeyType = KeyTypes.Bearer;
            rst.RequestType = RequestTypes.Issue;
            rst.AppliesTo = new EndpointAddress(connection.Realm);

            var channel = trustChannelFactory.CreateChannel();
            WSTrust13RequestSerializer trustSerializer = new WSTrust13RequestSerializer();

            using (Message message = Message.CreateMessage(
                MessageVersion.Default, WSTrust13Constants.Actions.Issue,
                new RequestBodyWriter(trustSerializer, rst)))
            {
                Message response2 = channel.EndIssue(channel.BeginIssue(message, null, null));
                XmlDictionaryReader reader = response2.GetReaderAtBodyContents();
                result = reader.ReadOuterXml();
            }
        }

        return result;
    }       

0 个答案:

没有答案