.NET FISHER

专注.NET, Sharepoint, MCMS, WinFX, Ajax....

导航

some comments from MS about single sign-on on multiple web applications

Posted on 2004-11-30 23:40  FISHER  阅读(859)  评论(1编辑  收藏  举报
*** Problem Description ***
Customer wanted to implement ASP.NET forms authentication across his entire
web app
which consisted of ASP.NET *and* classic ASP content.

<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
<>
*** Resolution ***

The following sample should work.  A few notes though:  This would have
been pretty
easy using simple COM Interop to call into the FormsAutentication utility
functions
however the functions require an HttpContext which is only available in an
ASP.NET
application.  As a workaround, we created and ASP.NET web service that does
the
forms auth ticket validation.

1.  First, use the ASP.NET Forms Authentication sample from the following
KB as a
base to start:

Q301240 HOW TO: Implement Forms-Based Authentication in ASP.NET Using C#
<http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q301240>

2.  Next, create a class that will manually validate a ticket that it is
passed,
return the forms authentication cookie name that is in use, and finally
return the
login url (all so that the code can be self-contained with minimum
administration
needed):

////////////// start sample code //////////////

//this method validates a ticket passed from ASP
public bool IsAuthenticated(string rawCookieData)
{
if(rawCookieData.Trim().Length <= 0)
  return false;

FormsAuthenticationTicket decryptedTicket;

try
{
  decryptedTicket = FormsAuthentication.Decrypt(rawCookieData);
}
catch
{
  //log reason for failure or whatever here if you like
  return false;
}

if (decryptedTicket.Expired)
  return false;
  
// Optionally you could change the method signature to return
// the decrypted ticket and then, you can call RenewTicketIfOld
// and then implement code on the ASP side to update the cookie
// with the newed ticket.  This would only be necessary if the
// ticket has a timeout set (this resets the timeout)
// see the MSDN docs on FormsAuthentication.RenewTicketIfOld.
 
return true;

}

// method merely returns the name of the cookie being used
public string GetCookieName()
{
return FormsAuthentication.FormsCookieName.ToString();
}

// method returns the login url used in the redirect
// this is trickier since there is no FormsAuth utility function available
to
return this so we have to manually look at web.config
private string GetLoginURL()
{
string sConfigPath = Server.MapPath(Request.ApplicationPath) +
"\\web.config";

XmlDocument doc = new XmlDocument();
doc.Load(sConfigPath);
  
try
{
  XmlNode xmlNodeForms =
doc.SelectSingleNode("configuration/system.web/authentication/forms");
  return xmlNodeForms.Attributes.GetNamedItem("loginUrl").InnerText;
}
catch
{
  throw new System.Exception("error in GetLoginURL()");
}
}



////////////// end sample //////////////

3.  Now create another .NET wrapper class that calls this web service (or
create
and compile a webproxy class)
4.  Next, use regasm.exe and gacutil.exe to make this "wrapper" class
callable from
ASP via ComInterop.
5.  The ASP code would look something like this:

Set oAuthClass = Server.CreateObject("ASPNETFormsAuth.WrapperClass")
If Not
oAuthClass.IsAuthenticated(Request.Cookies(oAuthClass.GetCookieName)) Then
     Response.Redirect("http://servername/ASPApplicationRoot/" &
oAuthClass.GetLoginURL & "?RetrunURL=" & Requset.ServerVariables("URL"))
End If

This code can be in a standalone ASP page and then can be #included at the
top of every page in the ASP app