Опубликован: 07.05.2010 | Доступ: свободный | Студентов: 1678 / 62 | Оценка: 4.56 / 4.06 | Длительность: 34:11:00
Лекция 18:

Безопасность

< Лекция 17 || Лекция 18: 123456789

Создание и удаление пользователей

Для создания и удаления пользователей следует применить перегруженные статические методы 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">
        
        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 border="0" cellpadding="5" cellspacing="0" 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>
  • Выполните страницу AddUserMembership.aspx и убедитесь в работоспособности рассматриваемого механизма добавления пользователей в БД SQL Server

Теперь рассмотрим вопрос удаления пользователей. Он намного проще, чем создание. Нужно только применить метод 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 border="0" cellpadding="5" cellspacing="0" 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>
  • Испытайте страницу удаления пользователей
< Лекция 17 || Лекция 18: 123456789