domingo, 15 de febrero de 2009

Exchange, directo al grano con OwaAuth

Durante la semana pasada he estado realizando una pequeña POC para el acceso a OWA (Outloook Web Access) via OwaAuth.dll y creo que, en cierto modo, estoy en la necesidad de que no pase al olvido, (si Juan, por si acaso, jejeje...).

¿Que es eso de OwaAuth.dll?

Se trata de la ISAPI de Exchange para el Logon en Owa. Esta es quizás una gran desconocida para muchos y aunque pasa desapercibida puede ser que en alguna ocasión sea necesario tener que hacer uso de ella para un propósito "un tanto distinto" :-D.

 

Owa necesita un "sessionid" y un "cadata" para poder acceder y obtener información de cada una de sus páginas, pues bien, owaauth.dll es la encargada de obtener estos dos datos en una primera petición http de tipo POST, y, a partir de aquí, haciendo uso de estos en las peticiones sucesivas cada página web de Owa retornará el código HTML sin ningún tipo de preámbulo.

Paso a paso:

public string GetPostData(Uri uri)
{
// Setting data to create a request body.
Dictionary<string, string> props = new Dictionary<string, string>();
props.Add(
"destination",
uri.Scheme
+ Uri.SchemeDelimiter + HttpUtility.UrlEncode(uri.Host + "/exchange/" + _user + "/"));
props.Add(
"flags", "4"); /* 0 */
props.Add(
"forcedownlevel", "0");
props.Add(
"trusted", "4"); /* 0 */
props.Add(
"username", HttpUtility.UrlEncode(String.Format(@"{0}\{1}", _domain, _user)));
props.Add(
"password", HttpUtility.UrlEncode(_password));
props.Add(
"submitCreds", "Log+On");
props.Add(
"isUtf8", "1");

ASCIIEncoding encoding
= new ASCIIEncoding();

string postData = String.Empty;
foreach (string key in props.Keys)
{
string pValue = null;
props.TryGetValue(key,
out pValue);
postData
+= string.Format("{0}={1}&", key, pValue);
}
if (props.Keys.Count > 0)
postData
= postData.Substring(0, postData.Length - 1);

return postData;
}




public CookieCollection Authenticate(string url)
{
string postData = GetPostData(new Uri(url));
// Get Response - Cookie
var response = HttpManager.SendRequest(
url, postData,
null,
RequestMethod.POST, _user, _password, _domain,
"application/x-www-form-urlencoded");

if (response.Cookies.Count < 2)
return null;

return response.Cookies;
}




 



El método "SendRequest" es el encargado de realizar:




  1. La primera petición de tipo "POST" y contentType "application/x-www-form-urlencoded" y,


  2. Cada petición de tipo "GET" y contentType "text/xml".



public static HttpWebResponse SendRequest(string url, string postData,
CookieCollection cookieCol, RequestMethod requestMethod,
string user, string pwd, string domain, string contentType)
{
ServicePointManager.ServerCertificateValidationCallback
= delegate(Object obj, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
{
return true;
};

Uri uri
= new Uri(url);

var request
= (HttpWebRequest)HttpWebRequest.Create(uri);

request.Method
= requestMethod.ToString();
request.CookieContainer
= new CookieContainer();
request.ContentType
= contentType;
request.AllowAutoRedirect
= false;
// request.ServicePoint.Expect100Continue = false;
request.KeepAlive = true;
request.UserAgent
= "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1;" +
".NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022)";
request.Accept
= "image/gif, image/x-xbitmap, image/jpeg, image/pjpeg,"
+ "application/x-ms-application, application/x-ms-xbap, application/vnd.ms-xpsdocument, application/xaml+xml, */*";

byte[] body = null;
if (requestMethod == RequestMethod.POST)
{
// BODY
body = Encoding.ASCII.GetBytes(postData);
request.ContentLength
= body.Length;
}

// Cookies
if (cookieCol != null)
{
foreach (Cookie c in cookieCol)
// request.Headers.Add(c.Name, c.Value);
request.CookieContainer.Add(c);
}

// Security
CredentialCache credentialCache = new System.Net.CredentialCache();
credentialCache.Add(uri,
"Basic", /* Basic */
new System.Net.NetworkCredential(user, pwd, domain)
);

request.Credentials
= credentialCache;

if (requestMethod == RequestMethod.POST)
{
// Response
var stream = request.GetRequestStream();
stream.Write(body,
0, body.Length);

stream.Close();
}

return (HttpWebResponse)request.GetResponse();
}


Esto ha sido todo por esta vez, espero como siempre,  haber dado un pasito más.



Saludos @SundayHome

Juanlu



This page is powered by Blogger. Isn't yours?