Implementación de CAS

Idea de implementación de la versión antigua de CAS

Principio fundamental (protocolo CAS 1.0)

  1. El usuario accede a la página protegida /admin/admin.aspx
  2. La configuración de permisos de web.config bloquea usuarios anónimos y redirige automáticamente a la página de inicio de sesión CasEnter.aspx
  3. CasEnter.aspx comprueba si la URL contiene el parámetro ticket
  • Sin ticket: redirige a la dirección de inicio de sesión del servidor CAS y envía la dirección actual del sitio como valor service
  • Con ticket: llama a la interfaz serviceValidate para validar el billete contra el servidor CAS
  1. CAS devuelve XML, se extrae el nombre de usuario autenticado
  2. Tras una validación correcta, se invoca FormsAuthentication.SetAuthCookie() para generar el billete local de Forms y se redirige a la página destino
  3. En accesos posteriores a directorios protegidos, ASP.NET Forms detecta el estado de la sesión

Configuración de web.config

<system.web>
  <authentication mode="Forms">
    <!-- loginUrl apunta a CasEnter.aspx como página de entrada intermediaria de CAS -->
    <forms loginUrl="CasEnter.aspx" 
           defaultUrl="admin/admin.aspx" 
           name=".LoginFormsTicket" 
           path="/" 
           timeout="40" 
           protection="All">
    </forms>
  </authentication>
  <authorization>
    <allow users="*"/>
  </authorization>
</system.web>

<!-- Restringe el directorio admin para impedir accesos anónimos -->
<location path="admin">
  <system.web>
    <authorization>
      <deny users="?"/>
    </authorization>
  </system.web>
</location>Lenguaje del código: HTML, XML (xml)

Los servidores CAS modernos fuerzan HTTPS por defecto, casUrl debe completarse con https://127.0.0.1:8443/cas/

<appSettings>
  <!-- Dirección de la nueva versión CAS7 con barra final -->
  <add key="casUrl" value="https://127.0.0.1:8443/cas/"/>
</appSettings>Lenguaje del código: HTML, XML (xml)

Código de la página CasEnter.aspx

1. CasEnter.aspx parte frontal
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="CasEnter.aspx.cs" Inherits="CasStudy.Web.CasEnter" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Inicio de sesión intermediario CAS</title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <asp:Label ID="Label1" runat="server"></asp:Label><br />
            <asp:HyperLink ID="HyperLink1" runat="server">Volver a autenticar</asp:HyperLink>
        </div>
    </form>
</body>
</html>Lenguaje del código: HTML, XML (xml)
2. CasEnter.aspx.cs lógica backend


Interfaz actualizada a CAS3.0 p3/serviceValidate
Se agrega HttpClient para reemplazar el obsoleto WebClient

Se añade compatibilidad con certificados autofirmados (imprescindible para pruebas locales con CAS moderno)
Gestión del espacio de nombres para el XML devuelto por CAS

using System;
using System.Configuration;
using System.Net;
using System.Net.Http;
using System.Xml;
using System.Web.Security;

public partial class CasEnter : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        string casHost = ConfigurationManager.AppSettings["casUrl"];
        string ticket = Request.QueryString["ticket"];
        string service = Request.Url.GetLeftPart(UriPartial.Path);

        // Sin billete, redirige a la página de inicio de sesión de CAS
        if (string.IsNullOrEmpty(ticket))
        {
            string redirectUrl = $"{casHost}login?service={Uri.EscapeDataString(service)}";
            Response.Redirect(redirectUrl);
            return;
        }

        // Validar ticket
        string username = ValidateTicket(casHost, ticket, service);
        if (string.IsNullOrEmpty(username))
        {
            Label1.Text = "¡Lo sentimos! Falló la autenticación CAS, inténtelo de nuevo.";
            HyperLink1.NavigateUrl = Request.Url.AbsolutePath;
        }
        else
        {
            // Generar billete de autenticación Forms y completar inicio de sesión local
            FormsAuthentication.SetAuthCookie(username, false);
            // Redirigir a la página destino
            Response.Redirect(FormsAuthentication.DefaultUrl);
        }
    }

    /// <summary>
    /// Validación de billete mediante CAS3.0 p3/serviceValidate
    /// </summary>
    private string ValidateTicket(string casHost, string ticket, string service)
    {
        // Las versiones nuevas de CAS recomiendan p3/serviceValidate (protocolo CAS3.0)
        string validateUrl = $"{casHost}p3/serviceValidate?ticket={Uri.EscapeDataString(ticket)}&service={Uri.EscapeDataString(service)}";

        // Solo para pruebas locales: permitir certificados SSL no confiables (eliminar en producción!)
        ServicePointManager.ServerCertificateValidationCallback += (s, cert, chain, err) => true;

        using var httpClient = new HttpClient();
        string xml = httpClient.GetStringAsync(validateUrl).Result;

        XmlDocument doc = new XmlDocument();
        doc.LoadXml(xml);
        XmlNamespaceManager nsMgr = new XmlNamespaceManager(doc.NameTable);
        // Espacio de nombres del XML devuelto por CAS3
        nsMgr.AddNamespace("cas", "http://www.yale.edu/tp/cas");

        // Buscar nodo de usuario
        XmlNode userNode = doc.SelectSingleNode("//cas:authenticationSuccess/cas:user", nsMgr);
        return userNode?.InnerText;
    }
}Lenguaje del código: HTML, XML (xml)

Implementación de CAS

Previous:

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *