This code uses the mainstream Microsoft user-supplied authentication mechanism for ASP.NET applications and uses CAS 2+ validation in case proxies are involved.
ASP.NET runs in an environment called the CLR just as JSP runs in a JVM. It is configured by a Web.Config file in the directory just as Servlets are configured by web.xml. One configuration option in both Web.Config and web.xml is how the pages and applications in the directory are secured. One of the ASP.NET options is to use "Forms Authentication", where access to a set of pages requires authentication through a login page. Typically a Web.Config is generated automatically by Visual Studio. Change the existing authentication to:
<authentication mode="Forms" >
<forms name="casauth" loginUrl="login.aspx" />
</authentication>
<authorization>
<deny users="?" />
</authorization>
This tells ASP.NET to require authentication for all access to the directory and to internally reroute every unauthenticated user to the login.aspx page. Now in Visual Studio create a login.aspx page with CS as the language. I suggest dragging a Label object to it from the Toolbox, which will become Label1.
In the login.aspx.cs file, add System.IO, System.Net, System.Web, and System.Xml to the list of using statements (imports for you Java folk). The rest is to code a Page_Load event handler. You can probably improve on:
// Local specific CAS host
private const string CASHOST = "https://secure.its.yale.edu/cas/";
// After the page has been loaded, this routine is called.
protected void Page_Load(object sender, EventArgs e)
{
// Look for the "ticket=" after the "?" in the URL
string tkt = Request.QueryString["ticket"];
// This page is the CAS service=, but discard any query string residue
string service = Request.Url.GetLeftPart(UriPartial.Path);
// First time through there is no ticket=, so redirect to CAS login
if (tkt == null || tkt.Length == 0)
// Second time (back from CAS) there is a ticket= to validate
string validateurl = CASHOST + "serviceValidate?" +
"ticket="tkt"&"+
"service="+service;
StreamReader Reader = new StreamReader( new WebClient().OpenRead(validateurl));
string resp = Reader.ReadToEnd();
// I like to have the text in memory for debugging rather than parsing the stream
// Some boilerplate to set up the parse.
NameTable nt = new NameTable();
XmlNamespaceManager nsmgr = new XmlNamespaceManager(nt);
XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None);
XmlTextReader reader = new XmlTextReader(resp, XmlNodeType.Element, context);
string netid = null;
// A very dumb use of XML. Just scan for the "user". If it isn't there, its an error.
while (reader.Read()) {
if (reader.IsStartElement())
}
// if you want to parse the proxy chain, just add the logic above
reader.Close();
// If there was a problem, leave the message on the screen. Otherwise, return to original page.
if (netid == null)
else
}
Now in any page in the application, the netid is accessible as Context.User.Identity.Name.