Создание настраиваемой страницы входа для SharePoint 2010 с проверкой подлинности на основе форм, часть 2

Создание настраиваемой страницы входа для SharePoint 2010 с проверкой подлинности на основе форм, часть 2

ОБНОВИТЕ ПРЕДИСЛОВИЕ К ЭТОМУ СООБЩЕНИЮ И ОТКРОЙТЕ КОММЕНТАРИЙ ДЛЯ ВЛАДЕЛЬЦА САЙТА:

С тех пор как сайт блога был обновлен до последней версии, будь она неладна, форматирование стало просто отвратительным. Мне приходится тратить уйму времени, чтобы привести в божеский вид жалкую разметку (точнее, ее отсутствие) новой версии. ПОЖАЛУЙСТА, СООБЩИТЕ ВЕБ-МАСТЕРУ, ЧТО ЭТИ УЖАСНО ОТФОРМАТИРОВАННЫЕ СООБЩЕНИЯ СОВЕРШЕННО НЕВОЗМОЖНО ЧИТАТЬ! А я тем временем при первой же возможности попытаюсь приложить документ Word с исходным сообщением. Кто сказал, что технологии не пахнут?? Ладно, ближе к делу...

В первой части серии, с которой можно ознакомиться по адресу http://blogs.msdn.com/b/sharepoint_ru/archive/2010/11/17/sharepoint-2010-1.aspx, я рассказал, как создать совершенно новую страницу входа на основе форм. Предполагалось, что нам необходимо было реализовать возможности, не поддерживаемые в стандартном пользовательском интерфейсе, например двухфакторную проверку подлинности. В этом сообщении мы рассмотрим другой сценарий. В данном случае возможностей стандартного пользовательского интерфейса вполне достаточно, однако во время входа в систему нам необходимо выполнить “определенные” дополнительные действия.

В данном конкретном случае все пользователи перед получением доступа к сайту должны принять условия его использования. Итак, давайте приступим к созданию новой страницы входа. Я собираюсь добавить обработчик события входа в систему, а в этом событии будет выполняться проверка на наличие куки-файла, указывающего на то, что пользователь принял условия использования сайта. Если пользователь еще не принял условия использования, он перенаправляется на страницу, где необходимо установить соответствующий флажок, после чего снова откроется страница входа. При последующем входе в систему я увижу, что на компьютере пользователя уже есть куки-файл условий использования, и перенаправлю пользователя на запрошенный ресурс: домашнюю страницу, документ и т. д.

Для начала я создам новую страницу входа. Я добавил в проект новую ASPX-страницу. В данном проекте необходимо добавить ссылки на сборки Microsoft.SharePoint и Microsoft.SharePoint.IdentityModel. Подробные сведения о том, как добавить ссылку на сборку Microsoft.SharePoint.IdentityModel, см. в части 1, ссылка на которую приведена выше. В файле с выделенным кодом страницы я снова собираюсь задействовать множество операторов using. Все эти операторы перечислены ниже.

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;

Поскольку мы создаем страницу входа с проверкой подлинности на основе форм, она должна быть унаследована от класса FormsSignInPage. Объявление класса приведено ниже.

public partial class AgreeLogin : FormsSignInPage

Первое, что необходимо сделать в коде, — это переопределить событие загрузки страницы. Я добавлю обработчик события входа в систему для элемента управления Login ASP.NET. Переопределенное событие загрузки страницы приведено ниже.

protected override void OnLoad(EventArgs e)

{

try

       {

             base.OnLoad(e);

             this.signInControl.LoggingIn +=

                   new LoginCancelEventHandler(signInControl_LoggingIn);

}

catch (Exception ex)

       {

       Debug.WriteLine(ex.Message);

       }

}

Примечание: я поместил код в блок try…catch, чтобы в случае нарушения разметки страницы, как будет показано ниже, при вызове метода base.OnLoad(e) выдавалось сообщение об ошибке. Ниже приведена реализация обработчика события 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);

       }

}

Итак, при входе в систему я проверяю наличие куки-файла, который указывает на то, что пользователь принял условия использования сайта. Если куки-файл не найден, я перенаправляю пользователя на страницу AgreeTerms.aspx. Я включаю полную строку запроса, полученную страницей входа, поскольку в ней указывается запрошенный пользователем ресурс. Таким образом, я знаю, куда перенаправить пользователя после того, как он примет условия использования. Важно отметить, что для моего веб-приложения SharePoint необходимо внести изменения в файл web.config, чтобы обеспечить анонимный доступ к условиям использования. В противном случае, если бы эта страница была защищенным ресурсом, как все остальные страницы сайта, возник бы бесконечный цикл: у пользователя нет куки-файла, он перенаправляется на страницу AgreeTerms.aspx, а поскольку эта страница защищена, пользователь перенаправляется обратно на страницу входа и т. д. Итак, я изменяю файл web.config, добавляя в него сразу же после закрывающего тега </system.web> следующую запись:

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

<system.web>

<authorization>

<allow users="*" />

</authorization>

</system.web>

</location>

Теперь страницу AgreeTerms.aspx можно открывать без проверки подлинности. Не буду приводить здесь пользовательский интерфейс страницы, приведу лишь его описание в файле с выделенным кодом, которое выглядит довольно просто:

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;

}

}

Все довольно очевидно: если пользователь устанавливает флажок, я предоставляю ему куки-файл и вызываю метод Response.Redirect для перенаправления пользователя на запрошенный ресурс. Пользователь перенаправляется на страницу входа, на этот раз я вижу куки-файл, поэтому все должно работать без лишних проволочек. Если пользователь не согласен с условиями использования, он никуда не переходит.

Это все, что касается кода, однако необходимо учитывать еще один ОЧЕНЬ важный фактор, а именно разметку страницы входа. Как я уже упомянул выше, в случае неправильной разметки могут возникнуть серьезные проблемы. Начнем с начальной разметки:

<%@ 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>

Единственное, что необходимо изменить, — это самую первую строку, директиву @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" %>

Текст, выделенный желтым, необходимо изменить на строгое имя настраиваемой сборки.

После сведения всех файлов воедино и их компиляции просто зарегистрируйте сборку в глобальном кэше сборок и скопируйте страницы ASPX в каталог макетов. Последнее, что необходимо сделать, — изменить страницу входа для зоны веб-приложений, где используется проверка подлинности на основе форм. Последовательно выберите пункты "Центр администрирования" (Central administration), "Управление приложениями" (Application Management) и "Управление веб-приложениями" (Manage web applications). Выберите веб-приложение и нажмите на панели инструментов кнопку "Поставщики проверки подлинности" (Authentication Providers). Щелкните ссылку на зону, которую необходимо изменить, в открывшемся диалоговом окне установите переключатель в положение "Настраиваемая страница входа" (Custom Sign In Page) и введите URL-адрес страницы входа. В моем случае необходимо ввести _layouts/AgreeLogin.aspx. Сохраните изменения. Теперь можно входить на сайт.

В конце статьи я хочу показать, как выглядит вход на сайт с помощью настраиваемых страниц; надеюсь, у вас тоже все получится!

1. Исходная страница входа

2. Страница с условиями использования

3. Окончательный вход на сайт

 

Это локализованная запись блога. Исходная статья находится по адресу Writing A Custom Forms Login Page for SharePoint 2010 Part 2