Creación de una página de inicio de sesión de formularios personalizada para SharePoint 2010 Parte 2

Creación de una página de inicio de sesión de formularios personalizada para SharePoint 2010 Parte 2

NUEVO PREFACIO A ESTA ENTRADA Y COMENTARIO ABIERTO AL PROPIETARIO DEL SITIO:

Desde que este sitio blog se actualizó a la última versión de lo que diablos sea esto, el formato se fue al demonio. Por lo general, dedico una buena cantidad de tiempo a intentar corregir el patético marcado (o la falta de marcado) de esta nueva versión. ¡¡¡POR FAVOR CONSIDERE LA POSIBILIDAD DE CONTACTAR AL WEB MASTER Y AVISARLE LO DIFÍCIL QUE ES LEER ESTAS ENTRADAS CON ESTE FORMATO TAN ESPANTOSO! Mientras tanto, intentaré adjuntar un documento de Word con la entrada original tal como la escribí siempre que sea posible. ¿Quién dijo que la tecnología no apesta?? Aquí vamos...

En la parte 1 de esta serie, que puede encontrar en http://blogs.msdn.com/b/sharepoint_sp/archive/2010/11/24/creaci-243-n-de-una-p-225-gina-de-inicio-de-sesi-243-n-de-formularios-personalizada-para-sharepoint-2010-parte-1.aspx, describí cómo crear una página de inicio de sesión de formularios totalmente nueva. En ese escenario, necesitábamos algo que no estaba disponible en la UI integrada, por ejemplo, autenticación de dos factores. En esta entrada voy a describir un escenario distinto. En este caso la UI integrada es adecuada pero queremos hacer algo más en el momento del inicio de sesión.

Para este escenario específico, quiero que todos los usuarios acepten los términos de uso del sitio antes de que puedan tener acceso a él. Entonces, voy a comenzar creando una nueva página de inicio de sesión. Voy a agregar un controlador para el evento de inicio de sesión y, en ese evento, voy a ver si tienen una cookie que indica que han aceptado los términos de uso. Si no la tienen, los redirigiré a una página en la que pueden activar una casilla para indicar que están de acuerdo y, entonces, los redirigiré de vuelta a la página de inicio de sesión. Cuando vuelvan a iniciar sesión, veré que tienen la cookie de términos de uso y, entonces, puedo enviarlos al recurso que solicitaron, como la página principal, un documento, etc.

Para empezar, voy a crear una nueva página de inicio de sesión. Agregué una nueva página ASPX a mi proyecto. En este proyecto voy a necesitar agregar referencias a Microsoft.SharePoint y a Microsoft.SharePoint.IdentityModel. Para obtener detalles sobre cómo agregar la referencia a Microsoft.SharePoint.IdentityModel, vea la parte 1, cuyo vínculo aparece más arriba. En el código subyacente de mi página voy a usar un grupo de instrucciones Using otra vez. Éstas son las que he usado:

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Web.UI;

using System.Web.UI.WebControls;

using Microsoft.SharePoint.IdentityModel.Pages;

using System.Diagnostics;

Debido a que la página que estoy creando es una página de inicio de sesión para la autenticación basada en formularios, necesita heredar de FormsSignInPage. Mi declaración de clase tiene este aspecto:

public partial class AgreeLogin : FormsSignInPage

Lo primero que voy a hacer en código es invalidar el evento de carga de página. Allí agregaré un controlador para el evento de inicio de sesión para el control de inicio de sesión de ASP.NET de la página. Aquí se ve el aspecto que tiene la invalidación para la carga de página:

protected override void OnLoad(EventArgs e)

{

try

       {

             base.OnLoad(e);

             this.signInControl.LoggingIn +=

                   new LoginCancelEventHandler(signInControl_LoggingIn);

}

catch (Exception ex)

       {

       Debug.WriteLine(ex.Message);

       }

}

Tenga en cuenta que lo puse en un bloque Try/Catch porque si comete un error en el marcado de la página, como explicaré a continuación, obtendrá un error al llamar a base.OnLoad(e). A continuación, le mostraré la implementación del controlador de eventos LoggingIn:

void signInControl_LoggingIn(object sender, LoginCancelEventArgs e)

{

//look for a cookie; if not there then redirect to our accept terms page

       const string AGREE_COOKIE = "SignedTermsAgreement";

    try

       {

       //we want to check for our cookie here

              HttpCookieCollection cookies = HttpContext.Current.Request.Cookies;

              HttpCookie ck = cookies[AGREE_COOKIE];

              if (ck == null)

              //user doesn't have the cookie indicating that they've signed the

              //terms of use so redirect them

              Response.Redirect("AgreeTerms.aspx?" +

                     Request.QueryString.ToString());

}

       catch (Exception ex)

       {

       Debug.WriteLine("There was an error processing the request: " +

              ex.Message);

       }

}

Aquí, cuando comienzo a iniciar sesión, primero busco la cookie que me indica que el usuario ha aceptado los términos de uso del sitio. Si no encuentro la cookie, entonces redirijo al usuario a mi página AgreeTerms.aspx. Incluyo la cadena de consulta completa que recibió la página de inicio de sesión porque me indica qué recurso solicitaba el usuario cuando llegó a la página de inicio de sesión. Entonces, sabré dónde enviarlo de vuelta después de que haya aceptado los términos de uso. Algo importante para recordar es que debo realizar un cambio en el archivo web.config para la aplicación web de SharePoint para que el acceso a la página de términos de uso puede ser anónimo. De lo contrario, si fuera un recurso seguro, como cada otra página del sitio, quedaría atrapado en un bucle interminable y diría que no tiene la cookie. Entonces, lo redirigiría a la página AgreeTerms.aspx, pero como es segura, lo redirigiría a mi página de inicio de sesión personalizada, y así sucesivamente. Modifiqué el archivo web.config para incluir esta entrada debajo de la etiqueta </system.web> de cierre:

<location path="_layouts/AgreeTerms.aspx">

<system.web>

<authorization>

<allow users="*" />

</authorization>

</system.web>

</location>

Ahora puedo llegar a mi página AgreeTerms.aspx sin autenticación. No los aburriré con la UI de la página ahora, pero en el código subyacente de esta página es muy sencillo:

protected void SubmitBtn_Click(object sender, EventArgs e)

{

const string AGREE_COOKIE = "SignedTermsAgreement";

try

       {

       //make sure the checkbox is checked

if ((AgreeChk.Checked) && (Request.Browser.Cookies))

              {

              //create the cookie

HttpCookie ck = new HttpCookie(AGREE_COOKIE, "true");

//set the expiration so it's persisted

ck.Expires = DateTime.Now.AddYears(3);

//write it out

HttpContext.Current.Response.Cookies.Add(ck);

//get the src attribute from the query string and redirect there

Response.Redirect(Request.QueryString["Source"]);

}

else

StatusLbl.Text = "You must agree to the terms of use before continuing.";

}

catch (Exception ex)

       {

       string msg = "There was an error processing the request: " + ex.Message;

       Debug.WriteLine(msg);

       StatusLbl.Text = msg;

}

}

Esto debería ser bastante claro; si activa la casilla, le doy la cookie y uso el método Response.Redirect para redirigirlo al origen que solicitó originalmente. Esto lo enviará de vuelta a la página de inicio de sesión y, esta vez, cuando inicie sesión veremos la cookie y todo funcionará a las mil maravillas. Si no acepta los términos de uso, no podrá ir a ningún lado.

Esto es todo lo que hay en cuanto a código. Pero hay algo más que es MUY importante y es el marcado de la página de inicio de sesión. Como ya describí antes, si el marcado tiene errores, tendrá todo tipo de problemas. Por eso, en primer lugar, éste es el marcado con el que debería empezar:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="AgreeLogin.aspx.cs" Inherits="FormsLoginPage.AgreeLogin,FormsLoginPage, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cf32e76ff986e00f" MasterPageFile="~/_layouts/simple.master" %>

<%@ Assembly Name="Microsoft.SharePoint.ApplicationPages, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"%>

<%@ Import Namespace="Microsoft.SharePoint.ApplicationPages" %> <%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Import Namespace="Microsoft.SharePoint" %>

<%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<asp:Content ContentPlaceHolderId="PlaceHolderPageTitle" runat="server">

    <SharePoint:EncodedLiteral ID="ClaimsFormsPageTitle" runat="server" text="<%$Resources:wss,login_pagetitle%>" EncodeMethod='HtmlEncode'/>

</asp:Content>

<asp:Content ContentPlaceHolderId="PlaceHolderPageTitleInTitleArea" runat="server">

    <SharePoint:EncodedLiteral ID="ClaimsFormsPageTitleInTitleArea" runat="server" text="<%$Resources:wss,login_pagetitle%>" EncodeMethod='HtmlEncode'/>

</asp:Content>

<asp:Content ContentPlaceHolderId="PlaceHolderSiteName" runat="server"/>

<asp:Content ContentPlaceHolderId="PlaceHolderMain" runat="server">

<SharePoint:EncodedLiteral runat="server" EncodeMethod="HtmlEncode" ID="ClaimsFormsPageMessage" />

 <asp:login id="signInControl" FailureText="<%$Resources:wss,login_pageFailureText%>" runat="server" width="100%">

    <layouttemplate>

        <asp:label id="FailureText" class="ms-error" runat="server"/>

        <table class="ms-input">

          <colgroup>

          <col width="25%"/>

          <col width="75%"/>

          </colgroup>

        <tr>

            <td nowrap="nowrap"><SharePoint:EncodedLiteral ID="EncodedLiteral3" runat="server" text="<%$Resources:wss,login_pageUserName%>" EncodeMethod='HtmlEncode'/></td>

            <td><asp:textbox id="UserName" autocomplete="off" runat="server" class="ms-long ms-login-textbox"/></td>

        </tr>

        <tr>

            <td nowrap="nowrap"><SharePoint:EncodedLiteral ID="EncodedLiteral4" runat="server" text="<%$Resources:wss,login_pagePassword%>" EncodeMethod='HtmlEncode'/></td>

            <td><asp:textbox id="password" TextMode="Password" autocomplete="off" runat="server" class="ms-long ms-login-textbox"/></td>

        </tr>

        <tr>

            <td colspan="2" align="right"><asp:button id="login" commandname="Login" text="<%$Resources:wss,login_pagetitle%>" runat="server" /></td>

        </tr>

        <tr>

            <td colspan="2"><asp:CheckBox id="RememberMe" text="<%$SPHtmlEncodedResources:wss,login_pageRememberMe%>" runat="server" /></td>

        </tr>

        </table>

    </layouttemplate>

 </asp:login>

</asp:Content>

Lo único que realmente debe cambiar es la primera línea: la directiva @Page.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="AgreeLogin.aspx.cs" Inherits="FormsLoginPage.AgreeLogin,FormsLoginPage, Version=1.0.0.0, Culture=neutral, PublicKeyToken=cf32e76ff986e00f" MasterPageFile="~/_layouts/simple.master" %>

La parte resaltada en amarillo debe cambiarse al nombre seguro del ensamblado personalizado.

Una vez que haya hecho todo esto, simplemente registre el ensamblado en el GAC y copie las páginas ASPX en el directorio de diseños. El último paso antes de intentarlo es cambiar la página de inicio de sesión por la zona de la aplicación web en la que usa FBA. Vaya a Administración central, Administración de aplicaciones, Administrar aplicaciones web. Seleccione la aplicación web y, a continuación, haga clic en el botón Proveedores de autenticación en la barra de herramientas. Haga clic en el vínculo a la zona que desea cambiar y, en el diálogo que aparece, haga clic en el botón de radio Página de inicio de sesión personalizada y escriba la dirección URL a su página de inicio de sesión. En mi caso era_layouts/AgreeLogin.aspx. Guarde los cambios y estará listo para iniciar sesión en su sitio.

Por último, aquí puede ver cuando inicié sesión con mis páginas personalizadas. ¡Espero que este artículo le resulte útil también!

1. Inicio de sesión inicial

2. Página de términos de uso

3. Por último, llegada al sitio

 

Esta entrada de blog es una traducción. Encontrará el artículo original en Writing A Custom Forms Login Page for SharePoint 2010 Part 2