As you know, warmup scripts are used to “wake up” SharePoint so that when the first users are in the office, they don’t encounter a very slow page load. On top of waking up the application pools of the web applications, one can also envision to wake up some services.
In a full Windows based authentication, including of course Claims & Windows, it is quite easy to do. However, in a scenario when you have a single zone with multiple authentication providers, say for instance Claims/NTLM-Kerberos & Forms/Custom Membership, things get a little more complicated.
Your PowerShell script runs under a Windows Identity. If the script performs a web request against that single zone, it’s likely to get a 302 redirection to the custom/standard login page.
There is a very well known trick to force a Windows Auth though which is _windows/default.aspx?ReturnUrl=/ in the URL, so for instance:
$WebRequest = [System.Net.HttpWebRequest]::Create( "https://yoururl/_windows/default.aspx?ReturnUrl=/" );
will force SharePoint to authenticate the user with Windows, thus with the identity running the script.
Then, you use the ReturnUrl parameter to specify where the request should be redirected after a successfull authentication. Right, so far, nothing really new but here is the tip : ReturnUrl only works for GET requests not for POST requests.
If you happen to perform a Search Query against /_vti_bin/search.aspx in SharePoint 2010, you’ll only be allowed to use the POST HTTP Verb and it’s not going to work with ReturnUrl. So the idea is to perform a first request to get an authentication cookie back and then reuse it to perform the search request. Here is a piece of PowerShell code showing that:
$keyword="test"; $body= @" <soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema'> <soap:Body> <Query xmlns='urn:Microsoft.Search'> <queryXml><QueryPacket><Query><Context><QueryText>$keyword</QueryText></Context></Query></QueryPacket></queryXml> </Query> </soap:Body></soap:Envelope> "@ $bodyBytes=[System.Text.Encoding]::UTF8.GetBytes($body) $WebRequest = [System.Net.HttpWebRequest]::Create( "https://your site/_windows/default.aspx?ReturnUrl=/" ); $WebRequest.UseDefaultCredentials = $true $WebRequest.UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET4.0C; .NET4.0E)" $WebRequest.CookieContainer = New-Object System.Net.CookieContainer $WebResponse = [System.Net.HttpWebResponse]$WebRequest.GetResponse(); $cookContainer = $WebRequest.CookieContainer; $SearchWebRequest = [System.Net.HttpWebRequest]::Create( "https://your site/_vti_bin/search.asmx"); $SearchWebRequest.Method = "POST" $SearchWebRequest.ContentLength=$bodyBytes.length; $SearchWebRequest.CookieContainer=$cookContainer; $SearchWebRequest.ContentType = "text/xml; charset=utf-8"; $RequestStream = $SearchWebRequest.GetRequestStream(); $RequestStream.Write($bodyBytes, 0, $bodyBytes.Length); $RequestStream.Close(); $webResponse=[System.Net.HttpWebResponse]$SearchWebRequest.GetResponse(); write-host $webResponse.ContentLength;
So, once the first request has been issued with the current credentials (windows), you can get the cookie container back which contains all the cookies and reassign it to the search request where you don’t even need to specify credentials anymore since the authentication information is contained in the FEDAUTH cookie.
This applies mainly to SharePoint 2010. One can also use that in 2013 but it’s way easier to just use the search REST API.