Опубликован: 13.07.2010 | Доступ: свободный | Студентов: 889 / 20 | Оценка: 4.40 / 4.20 | Длительность: 77:34:00
Самостоятельная работа 37:

Безопасность: аутентификация с помощью форм

< Самостоятельная работа 36 || Самостоятельная работа 37: 12345678

Упражнение 5. Административная страница создания пользователей в БД

Для создания и удаления пользователей следует применить перегруженные статические методы CreateUser() и DeleteUser() класса Membership. Нужно создать административные страницы, содержащие требуемые поля для ввода информации. Поля можно контролировать валидаторами, хотя это и необязательно, поскольку эти страницы административные, пользоваться такими страницами будут администраторы, которые будут строго соблюдать правила ввода.

Метод CreateUser() имеет несколько перегрузок, из которых простейшая принимает только имя и пароль. В то же время более полные перегрузки требуют ввода контрольного вопроса и ответа на него. В самой полной перегрузке метод CreateUser() содержит экземпляр перечисления MembershipCreateStatus в качестве выходного параметра, позволяющий проанализировать причину ошибки в случае ее возникновения. По умолчанию требуется применять наиболее полную перегрузку метода CreateUser(), включающую контрольный вопрос и ответ, чтобы избежать выброса исключения MembershipCreateUserException.

Удаление пользователя выполняется методом Membership.DeleteUser(string), которому передается в качестве параметра уникальное имя пользователя. Пользователь безвозвратно удаляется из всех таблиц вместе со всей связанной с ним информацией.

В качестве примера создадим собственную страницу добавления, имеющую аналогичную функциональность с WAT, и отдельно страницу удаления пользователя в БД. Для простоты эти страницы мы переделаем из страницы регистрации MyLogin.aspx.

  • Скопируйте страницу MyLogin.aspx и присвойте копии имя AddUserMembership.aspx

Провайдер базы данных не добавляет новых пользователей, если пароль имеет длину менее 7 символов и если среди них нет хотя-бы одного неалфавитно-цифрового символа. Для проверки выполнения этого условия, а также для тренировки, закрепим за полем пароля кодируемый элемент проверки достоверности CustomValidator. С помощью этого элемента реализуем проверку достоверности на клиенте и на сервере.

Неалфавитно-цифровые символы представим в виде ASCII -кодов согласно следующей таблице

Набор неалфавитно-цифровых символов ASCII
  0 1 2 3 4 5 6 7 8 9
0                    
1                    
2                    
3       ! " # $ % & '
4 ( ) * + , . /      
5                 : ;
6 < = > ? @          
7                    
8                    
9   [ \ ] ^ _        
10                    
11                    
12       { | } ~      

Строка ASCII -кодов неалфавитно-цифровых символов на JavaScript будет такой:

var nonAlphanumericCharactersString = String.fromCharCode(33,34,35,36,37,38,39,40,41,42,43,44,45,46,                                 58,59,60,61,62,63,64,91,92,93,94,95,123,124,125,126);

  • Переделайте интерфейсную и скриптовую части страницы, чтобы она стала такой
<%@ Page Language="C#" EnableViewState="false" %>
    
<script runat="server">
    // Блок на C# по умолчанию 
    protected void Page_Load(object sender, EventArgs e)
    {
        // Вынесли из интерфейсной части из-за большой ширины листинга
        passwordValidator.ErrorMessage = 
            "Пароль должен иметь длину не менее 7 символов"
            + " и содержать хотя бы один неалфавитно-цифровой символ";
    }
    
    protected void AddUserMembership_Click(object sender, EventArgs e)
    {
        this.Validate();// Исполнить валидаторы на сервере
        if (!this.IsValid)// Оценить флаг достоверности
            return;// Отправить назад как есть
    
        // Создаем экземпляр перечисления
        MembershipCreateStatus status;
    
        // Попытка добавить
        try
        {
            Membership.CreateUser(
                username.Text,
                password.Text,
                email.Text,
                question.Text,
                answer.Text,
                true,
                out status
                );
    
            lblResult.Text = String.Empty;
            switch (status)
            {
                case MembershipCreateStatus.DuplicateUserName:
                    lblResult.Text = "Дублированное имя пользователя<br/>";
                    goto default;
                case MembershipCreateStatus.ProviderError:
                    lblResult.Text = "Ошибка Поставщика<br/>";
                    goto default;
                default: // Дальше лень анализировать
                    lblResult.Text += "Пользователь не создан";
                    lblResult.ForeColor = System.Drawing.Color.Red;
                    break;
                case MembershipCreateStatus.Success:
                    // Выдаем успешную информацию
                    lblResult.Text = "Пользователь " + username.Text 
                        + " создан успешно!";
                    // Рекурсивно очищаем все текстовые поля ввода
                    EmptyTextBox(form1.Controls);
                    lblResult.Text += "<br/>Поля ввода очищены";
                    break;
            }
        }
        // Откат
        catch (MembershipCreateUserException ex)
        {
            lblResult.Text = "<h2 style='color: Red'>Ошибка создания пользователя</h2>";
            System.Diagnostics.Debug.WriteLine("Exception: "
                + ex.Message);
        }
    }
    
    private void EmptyTextBox(ControlCollection controls)
    {
        foreach (Control ctrl in controls)
        {
            if (ctrl is TextBox)
                ((TextBox)ctrl).Text = String.Empty;
    
            // Идем в глубину иерархической цепочки и ищем дочерние элементы
            if (ctrl.Controls != null)
                EmptyTextBox(ctrl.Controls);
        }
    }
</script>
    
<script language="C#" runat="server">
// Еще один блок с явным указанием C#, хотя можно атрибут языка и не указывать
    
    // Проверка допустимости пароля на сервере 
    // Обработчик события ServerValidate элемента CustomValidator
    protected void passwordValidator_ServerValidate(object source, ServerValidateEventArgs args)
    {
        string data = args.Value;
    
        // Установить начальное значение флага достоверности
        args.IsValid = false;
    
        // Проверить длину пароля 
        if (data.Length < 7)
            return;
    
        // Проверить наличие неалфавитноцифрового символа
        // Формируем массив неалфавитноцифровых символов по их кодам,
        // чтобы не связываться с интерпретируемыми символами
        int[] nonAlphanumericCharactersCode =
            {33,34,35,36,37,38,39,40,41,42,43,44,45,46,
             58,59,60,61,62,63,64,91,92,93,94,95,123,124,125,126};
        
        // Перебираем символы пользовательского ввода
        foreach (char ch in data)
        {
            for (int i = 0; i < nonAlphanumericCharactersCode.Length; i++)
                if (ch == Convert.ToChar(nonAlphanumericCharactersCode[i]))
                {
                    // Пароль допустим 
                    args.IsValid = true;
                    return;
                }
        }
    }
</script>
    
<script language="javascript" type="text/javascript">
    // Проверка допустимости пароля на клиенте. Работает при включенном
    // по умолчанию свойстве EnableClientScript элемента CustomValidator
        
    function ValidatePassword(source, args)
    {
        // Расщепить строку на массив символов с пустым разделителем
        var data = args.Value.split("");
        
        // Установить начальное значение флага достоверности
        args.IsValid = false;
        
        // Проверить длину пароля 
        if(data.length < 7)
            return;
            
        // Проверить наличие неалфавитноцифрового символа
        // Формируем строку неалфавитноцифровых символов по их кодам,
        // чтобы не связываться с интерпретируемыми символами
        var nonAlphanumericCharactersString = 
            String.fromCharCode(33,34,35,36,37,38,39,40,41,42,43,44,45,46,
                                58,59,60,61,62,63,64,91,92,93,94,95,123,124,125,126);             
        for(var ch in data)
        {
            if(nonAlphanumericCharactersString.indexOf(data[ch]) != -1)
            {
                // Пароль допустим 
                args.IsValid = true;           
                return;
            }
        }
    }
</script>
    
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title>Добавление пользователей в БД</title>
</head>
<body>
    <form id="form1" runat="server">
        <div style="text-align: center">
            <h2 id="H2_1" runat="server">
                Введите учетную запись для добавления пользователя</h2>
            <asp:Panel ID="MainPanel" runat="server" BorderColor="Silver" BorderStyle="Ridge"
                BorderWidth="2px" Height="90px" Width="364px">
                <table cellpadding="5" style="width: 137%">
                    <tr>
                        <td>
                            &nbsp;&nbsp;&nbsp;
                        </td>
                        <td align="right" height="43" style="width: 224px">
                            Имя&nbsp;пользователя:
                        </td>
                        <td>
                            &nbsp;<asp:TextBox ID="username" runat="server" />
                        </td>
                        <td>
                            <asp:RequiredFieldValidator ID="usernameRequiredValidator" 
                                runat="server" ControlToValidate="username" 
                                ErrorMessage='Не заполнено поле "Имя пользователя"' 
                                Display="Dynamic">*</asp:RequiredFieldValidator>
                        </td>
                    </tr>
                    <tr>
                        <td>
                            &nbsp;&nbsp;&nbsp;
                        </td>
                        <td align="right" height="43" style="width: 224px">
                            &nbsp;Пароль:
                        </td>
                        <td>
                            &nbsp;<asp:TextBox ID="password" runat="server" />
                        </td>
                        <td>
                            <asp:RequiredFieldValidator ID="passwordRequiredValidator" 
                                runat="server" ControlToValidate="password" 
                                ErrorMessage='Не заполнено поле "Пароль"' 
                                Display="Dynamic">*</asp:RequiredFieldValidator>
                            <asp:CustomValidator ID="passwordValidator" runat="server" 
                                ControlToValidate="password"
                                Display="Dynamic" 
                                ClientValidationFunction="ValidatePassword" 
                                OnServerValidate="passwordValidator_ServerValidate">*</asp:CustomValidator>
                        </td>
                    </tr>
                    <tr>
                        <td>
                            &nbsp;&nbsp;&nbsp;
                        </td>
                        <td align="right" height="43" style="width: 224px">
                            E-mail:</td>
                        <td>
                            &nbsp;<asp:TextBox ID="email" runat="server"></asp:TextBox>
                        </td>
                        <td>
                            <asp:RequiredFieldValidator ID="emailRequiredValidator" 
                                runat="server" ControlToValidate="email" 
                                ErrorMessage='Не заполнено поле "E-mail"' 
                                Display="Dynamic">*</asp:RequiredFieldValidator>
                            <asp:RegularExpressionValidator ID="emailValidator" runat="server" 
                                ControlToValidate="email" ErrorMessage="Неверный E-mail" 
                                ValidationExpression="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*" 
                                Display="Dynamic">*</asp:RegularExpressionValidator>
                        </td>
                    </tr>
                    <tr>
                        <td>
                            &nbsp;&nbsp;&nbsp;
                        </td>
                        <td align="right" height="43" style="width: 224px">
                            Контрольный вопрос:</td>
                        <td>
                            &nbsp;<asp:TextBox ID="question" runat="server"></asp:TextBox>
                        </td>
                        <td>
                            <asp:RequiredFieldValidator ID="questionRequiredValidator" 
                                runat="server" ControlToValidate="question" 
                                ErrorMessage='Не заполнено поле "Контрольный вопрос"' 
                                Display="Dynamic">*</asp:RequiredFieldValidator>
                        </td>
                    </tr>
                    <tr>
                        <td>
                            &nbsp;&nbsp;&nbsp;
                        </td>
                        <td align="right" height="43" style="width: 224px">
                            Контрольный ответ:</td>
                        <td>
                            &nbsp;<asp:TextBox ID="answer" runat="server"></asp:TextBox>
                        </td>
                        <td>
                            <asp:RequiredFieldValidator ID="answerRequiredValidator" 
                                runat="server" ControlToValidate="answer" 
                                ErrorMessage='Не заполнено поле "Контрольный ответ"' 
                                Display="Dynamic">*</asp:RequiredFieldValidator>
                        </td>
                    </tr>
                    <tr>
                        <td colspan="4" align="center">
                            <asp:Button ID="btnAddUser" runat="server" 
                                Text="Добавить" OnClick="AddUserMembership_Click" />
                        </td>
                    </tr>
                </table>
            </asp:Panel>
            <asp:Label ID="lblResult" runat="server" Font-Bold="True" 
                Font-Size="Large" ForeColor="Blue" />
        </div>
        <asp:ValidationSummary ID="ValidationSummary1" runat="server" />
    </form>
</body>
</html>
Листинг 37.16. Административная страница AddUserMembership.aspx добавления пользователей в БД
  • Выполните страницу AddUserMembership.aspx и убедитесь в работоспособности рассматриваемого механизма добавления пользователей в БД SQL Server

Упражнение 6. Административная страница удаления пользователей из БД

Теперь рассмотрим вопрос удаления пользователей. Он намного проще, чем создание. Нужно только применить метод System.Web.Security.Membership.DeleteUser(), который имеет две перегрузки:

  • public static bool DeleteUser( string username ) - удаляет по имени пользователя все связанные с ним данные из всех таблиц БД
  • public static bool DeleteUser( string username, bool deleteAllRelatedData ) - удаляет пользователя только из таблицы aspnet_Users, если флаг равен false. Иначе удаляет все связанные с пользователем данные при флаге равном true

Обе перегрузки возвращают true, если пользователь успешно удален, иначе false.

  • Разработайте из копии страницы MyLogin.aspx административную страницу удаления пользователей DeleteUserMembership.aspx, которая будет примерно такой
<%@ Page Language="C#" EnableViewState="false" %>
    
<script runat="server">
    
    protected void DeleteUser_Click(object sender, EventArgs e)
    {
        if (Membership.DeleteUser(username.Text))
        {
            lblResult.Text="Пользователь " + username.Text 
                + " успешно удален";
            username.Text = "";
        }
        else
        {
            lblResult.Text = "Пользователь не удален";
            lblResult.ForeColor = System.Drawing.Color.Red;
        }
    }
</script>
    
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
    <title>Удаление пользователей из БД</title>
</head>
<body>
    <form id="form1" runat="server">
        <div style="text-align: center">
            <h2>
                Введите имя удаляемого пользователя</h2>
            <asp:Panel ID="MainPanel" runat="server" BorderColor="Silver" 
                BorderStyle="Ridge"
                BorderWidth="2px" Height="90px" Width="412px">
                <table cellpadding="5" style="width: 100%">
                    <tr>
                        <td align="right" height="43" style="width: 167px">
                            Имя&nbsp;пользователя:</td>
                        <td>
                            &nbsp;<asp:TextBox ID="username" runat="server" />
                        </td>
                    </tr>
                </table>
                <asp:Button ID="Button1" runat="server" Text="Удалить" 
                    OnClick="DeleteUser_Click" /></asp:Panel>
            <asp:Label ID="lblResult" runat="server" Font-Bold="True" 
                Font-Size="Large" ForeColor="Blue">
            </asp:Label>
        </div>
    </form>
</body>
</html>
Листинг 37.16. Админ. страница DeleteUserMembership.aspx удаления пользователей из БД
  • Испытайте страницу удаления пользователей
< Самостоятельная работа 36 || Самостоятельная работа 37: 12345678