Безопасность включает в себя ряд мероприятий, необходимых для предотвращения несанкционированного доступа к сайту и
Основные задачи по защите сайта следующие:
Аутентификация нового пользователя начинается с его регистрации. Пользователю предлагается страница регистрации с текстовыми полями, через которую у него запрашиваются некоторые идентификационные данные. По этим данным создается и сохраняется
Теперь при запросе ограниченного ресурса пользователь предъявит свое удостоверение, которое система верифицирует и примет решение: если удостоверение пользователя подтверждается, ему предоставляется доступ к Web-ресурсу, иначе будет предложена регистрация. Процесс аутентификации может выглядеть примерно так

В приложениях ASP.NET аутентификация может быть реализована одним из следующих способов:
System.Web.Security.FormsAuthenticationModuleSystem.Web.Security.WindowsAuthenticationModuleSystem.Web.Security.PassportAuthenticationModuleСистемы коммуникации шифруются с помощью системы SSL (
Обычно сервер, которому клиент собирается пересылать важные данные, маркируется сертификатом. Сертификат - это некоторый паспорт сервера, подтверждающий тот факт, что ему можно доверять. Организация, которой принадлежит сервер, приобретает сертификат у известного
Наиболее популярными центрами
Инсталированный на
Клиент (браузер) доверяет CA и поэтому готов доверять подписанной CA информации. В свою очередь, CA сохраняет информацию о каждом зарегистрированном пользователе. Начало работы по защищенному каналу связи начинается так:
Аутентификация (распознавание) на основе форм реализуется в пространстве имен System.Web.Security классами:
FormsAuthenticationModuleFormsAuthenticationFormsAuthenticationEventArgsFormsAuthenticationTicketFormsIdentityВыбор этого режима устанавливается только в одном единственном месте -
<authentication mode="Forms" />
Аутентификацию форм можно выполнять и с помощью API-интерфейсов Membership и Roles (об этом позже).
Аутентификация форм основана на удостоверениях (
Для реализации аутентификации форм нужно выполнить следующее:
В файле web.config виртуального корневого каталога сайта необходимо определить нужные параметры аутентификации, как System.Web.Configuration.FormsAuthenticationConfiguration, из следующего набора:
| Опция | Значение по умолчанию | Описание |
|---|---|---|
Name |
.ASPXAUTH |
Имя |
LoginUrl |
|
Определяет страницу регистрации пользователя при запросе защищенной страницы ( - |
|
30 |
Время жизни |
SlidingExpiration |
false |
Включает режим скользящего устаревания |
Cookieless |
UseDeviceProfile |
Указывает способ пересылки удостоверения пользователя |
Protection |
All |
Задает уровень безопасности None - не - только - только подписыватьAll - |
RequireSSL |
false |
При включении требует передачи через |
EnableCrossAppRedirects |
false |
Разрешает переадресацию между приложениями при использовании аутентификации форм. Оба приложения должны опираться на одно и то же хранилище удостоверений |
DefaultUrl |
default.aspx |
Указывает страницу, на которую направляется пользователь после успешной регистрации, если он напрямую запросил страницу регистрации, указанную в LoginUrl |
|
пусто | Может указывать |
Path |
/ |
Путь для |
Перечисленные свойства устанавливаются как атрибуты дочернего дескриптора <forms> секции <. Вот пример использования полного набора этих атрибутов в файле web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<compilation debug="true" />
<authentication mode="Forms">
<forms
name="MyCookieName"
loginUrl="MyLogin.aspx"
timeout="20"
slidingExpiration="true"
cookieless="AutoDetect"
protection="All"
requireSSL="false"
enableCrossAppRedirects="false"
defaultUrl="MyDefault.aspx"
domain=""
path="/"
/>
</authentication>
</system.web>
</configuration>
Хоть это и не самый лучший способ хранения удостоверений пользователей, зато самый простой. Вообще, удостоверения можно хранить где угодно, только нужно предусмотреть соответствующий код их сравнения с введенными на странице регистрации данными. Если удостоверения хранятся в файле web.config, то их нужно помещать в дочерний для <forms> дескриптор <credentials>. Вот пример для трех пользователей
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<compilation debug="true" />
<authentication mode="Forms">
<forms
name="MyCookieName"
loginUrl="MyLogin.aspx"
timeout="20"
slidingExpiration="true"
cookieless="AutoDetect"
protection="All"
requireSSL="false"
enableCrossAppRedirects="false"
defaultUrl="MyDefault.aspx"
domain=""
path="/"
>
<credentials passwordFormat="Clear">
<user name="Admin" password="Root" />
<user name="Petja" password="Xa-xa" />
<user name="Vasja" password="Xo-xo" />
</credentials>
</forms>
</authentication>
</system.web>
</configuration>
Рассмотрим пример
Пользователей в <credentials>, так и программно.
Создайте пустой проект Web-приложения командой
Добавьте к приложению
Заполните (рис ) Код конфигурационного файла<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<compilation debug="true" />
<authentication mode="Forms">
<forms
name="MyCookieName"
loginUrl="MyLogin.aspx"
defaultUrl="MyDefault.aspx"
protection="All"
timeout="20"
path="/"
requireSSL="false"
slidingExpiration="true"
cookieless="AutoDetect"
domain=""
enableCrossAppRedirects="false">
<credentials passwordFormat="Clear">
<user name="Admin" password="Root" />
<user name="Петя" password="Уфamp;Уф" />
<user name="Вася" password='!$-*?"' />
</credentials>
</forms>
</authentication>
</system.web>
</configuration>
Добавьте к проекту страницу без отделенного кода с именем LoginAddUsers.aspx и заполните ее следующим кодом(рис ) Страница LoginAddUsers.aspx<%@ Page Language="C#" %>
<%@ Import Namespace="System.Web.Configuration" %>
<script runat="server">
protected void btnAddUsers_Click(object sender, EventArgs e)
{
// Учетные записи для новых аутентифицированных пользователей
string[,] authUsers = {
{"user1", "password1"},
{"user2", "password2"},
{"user3", "password3"}
};
// Загрузить содержимое корневого Web.config
Configuration myConfig = System.Web.Configuration.
WebConfigurationManager.OpenWebConfiguration("~/");
// Найти содержимое секции system.web
ConfigurationSectionGroup systemWeb = myConfig.SectionGroups["system.web"];
// Найти содержимое секции authentication
System.Web.Configuration.AuthenticationSection authSec =
(System.Web.Configuration.AuthenticationSection)
systemWeb.Sections["authentication"];
// Установить параметр passwordFormat
authSec.Forms.Credentials.PasswordFormat = System.Web.Configuration.FormsAuthPasswordFormat.Clear;
// Добавить новых пользователей
for (int i = 0; i < authUsers.Length / 2; i++)
authSec.Forms.Credentials.Users.Add(new System.Web.Configuration.FormsAuthenticationUser(
authUsers[i, 0], authUsers[i, 1]));
// Обновить файл Web.config
myConfig.Save();
// Отсылаем сообщение
lblUsersResult.Text = "Новые пользователи добавлены!!!";
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div style="text-align: center">
<h1>Административная страница добавления учетных записей в Web.config</h1>
<p>
<asp:Button ID="btnAddUsers" runat="server" Text="Добавить" OnClick="btnAddUsers_Click" /></p>
<p>
<asp:Label ID="lblUsersResult" runat="server"></asp:Label></p>
</div>
</form>
</body>
</html>
Обратите внимание. Чтобы не использовать длинные имена классов в страницах с совмещенным кодом, можно подключить вначале страницы <%@ Import Namespace="System.Web.Configuration" %>
В режиме редактирования страницы LoginAddUsers.aspx выполните команду File/View in BrowserЭта страница программно добавит новых пользователей в файл Web.config. Также будут скорректированы имена старых пользователей путем приведения символов к нижнему регистру. Но это не существенно, поскольку ASP.NET при сравнении имен регистр символов не учитывает.
Добавьте в (рис ) Окончательный вид файла Web.config<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<compilation debug="true" />
<authentication mode="Forms">
<forms
name="MyCookieName"
loginUrl="MyLogin.aspx"
defaultUrl="MyDefault.aspx"
protection="All"
timeout="20"
path="/"
requireSSL="false"
slidingExpiration="true"
cookieless="AutoDetect"
domain=""
enableCrossAppRedirects="false">
<credentials passwordFormat="Clear">
<user name="admin" password="Root" />
<user name="петя" password="Уфamp;Уф" />
<user name="вася" password="!$-*?quot;" />
<user name="user1" password="password1" />
<user name="user2" password="password2" />
<user name="user3" password="password3" />
</credentials>
</forms>
</authentication>
<authorization>
<deny users="?"/>
</authorization>
</system.web>
</configuration>
Добавьте к проекту две страницы без отделенного кода с именами Default.aspx и MyDefault.aspx со следующим кодом(рис ) Страница Default.aspx<%@ Page Language="C#" %>
<script runat="server">
protected void SignOutAction_Click(object sender, EventArgs e)
{
// Уничтожить cookie-набор
FormsAuthentication.SignOut();
// Направить на страницу регистрации
//FormsAuthentication.RedirectToLoginPage();
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h1>
Страница с ограниченным доступом Default.aspx</h1>
<p>
<asp:Button ID="SignOutAction" runat="server"
Text="Отменить регистрацию" OnClick="SignOutAction_Click" />
<asp:HyperLink ID="HyperLink1" runat="server"
NavigateUrl="~/MyDefault.aspx">На страницу MyDefault.aspx...
</asp:HyperLink></p>
</div>
</form>
</body>
</html>
<%@ Page Language="C#" %>
<script runat="server">
protected void SignOutAction_Click(object sender, EventArgs e)
{
// Уничтожить cookie-набор
FormsAuthentication.SignOut();
// Направить на страницу регистрации
//FormsAuthentication.RedirectToLoginPage();
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h1>
Страница с ограниченным доступом MyDefault.aspx</h1>
<p>
<asp:Button ID="SignOutAction" runat="server"
OnClick="SignOutAction_Click" Text="Отменить регистрацию" />
<asp:HyperLink ID="HyperLink1" runat="server"
NavigateUrl="~/Default.aspx">На страницу Default.aspx...
</asp:HyperLink></p>
</div>
</form>
</body>
</html>
Страница регистрации предоставляет пользователю интерфейс для ввода имени и пароля, принимает их и сравнивает с удостоверениями, хранящимися на сервере. Если удостоверения хранятся прямо в
Страница регистрации должна включать в себя
Создайте новую страницу с именем MyLogin.aspx без отделенного кода
Заполните страницу элементами управления и настройте их согласно таблице| Элемент | Свойство | Значение | Пояснение |
|---|---|---|---|
|
ID |
MainPanel |
Родительская панель для оформления рамкой |
BorderColor |
Silver |
Цвет рамки | |
|
|
Тип рамки | |
TextBox |
ID |
UsernameText |
Текстовое |
RequiredFieldValidator |
ID |
UsernameRequiredValidator |
Проверка достоверности, чтобы привязанное поле не было пустым |
ControlToValidate |
UsernameText |
Привязка к контролируемому элементу ввода | |
|
|
Место под элемент выделять только при |
|
ErrorMessage |
Не заполнено поле "Имя пользователя" | Отображать в элементе ValidationSummary при ошибке |
|
|
Пустое |
||
Text |
* |
Надпись на визуализированном |
|
RegularExpressionValidator |
ID |
UsernameValidator |
|
ControlToValidate |
UsernameText |
Привязка к контролируемому элементу ввода | |
|
|
Место под элемент выделять только при |
|
ErrorMessage |
Неверное |
Отображать в элементе ValidationSummary при ошибке |
|
|
Допустимы буквы, цифры, пробелы и подчеркивания | ||
ValidationExpression |
[а-яА-Я\w| ]* |
[] - диапазон пропускаемых символов[]* - символы диапазона могут встречаться в контролируемом вводе сколько угодно раза-яА-Я - пропускать все буквы русского алфавита\w - пропускать все латинские буквы, цифры и знаки подчеркивания. Это | - знак ИЛИ, после которого стоит пробел, означает, что пропускать и пробелы |
|
Text |
* |
Надпись на визуализированном |
|
TextBox |
ID |
PasswordText |
Текстовое |
TextMode |
Password |
Ввод отображается звездочками | |
RequiredFieldValidator |
ID |
PwdRequiredValidator |
Проверка достоверности, чтобы привязанное поле не было пустым |
ControlToValidate |
PasswordText |
Привязка к контролируемому элементу ввода | |
|
|
Место под элемент выделять только при |
|
ErrorMessage |
Не заполнено поле "Пароль" | Отображать в элементе ValidationSummary при ошибке |
|
|
Пустое |
||
Text |
* |
Надпись на визуализированном |
|
RegularExpressionValidator |
ID |
PwdValidator |
|
ControlToValidate |
PasswordText |
Привязка к контролируемому элементу ввода | |
|
|
Место под элемент выделять только при |
|
ErrorMessage |
Неверный пароль | Отображать в элементе ValidationSummary при ошибке |
|
|
Используются недопустимые символы | ||
ValidationExpression |
[а-яА-Я\w|!"$ |
[] - диапазон пропускаемых символов[]* - символы диапазона могут встречаться в контролируемом вводе сколько угодно раза-яА-Я - пропускать все буквы русского алфавита\w - пропускать все латинские буквы, цифры и знаки подчеркивания. Это | - знак ИЛИ, после которого стоит пробел и ряд других символов, разрешенных для ввода |
|
Text |
* |
Надпись на визуализированном |
|
|
ID |
Button1 |
Кнопка Submit |
Text |
Отправить | Надпись | |
|
ID |
lblResult |
Метка сообщения для заполнения в коде |
ValidationSummary |
ID |
ValidationSummary1 |
Элемент отображения сообщений об ошибках, обнаруженных |
Интерфейсная часть страницы MyLogin.aspx в режиме проектирования будет такой

Код страницы MyLogin.aspx будет таким
<%@ Page Language="C#" EnableViewState="false" %>
<script runat="server">
protected void LoginAction_Click(object sender, EventArgs e)
{
this.Validate();// Исполнить валидаторы на сервере
if (!this.IsValid)// Оценить флаг достоверности
return;// Отправить назад как есть
// Извлечь из web.config и сравнить с введенным
if (FormsAuthentication.Authenticate(UsernameText.Text, PasswordText.Text))
{
// Создать временный cookie-набор (второй параметр false),
// записать в него метку аутентификации и перенаправить
// на исходную запрошенную страницу или MyDefault.aspx
FormsAuthentication.RedirectFromLoginPage(UsernameText.Text, false);
}
else
{
HtmlGenericControl message = new HtmlGenericControl();
message.InnerHtml = "<h2 style='color: Red'>Неверное имя или пароль!</h2>";
form1.Controls.Add(message);
}
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Untitled Page</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>
nbsp;nbsp;nbsp;
</td>
<td align="right" height="43" style="width: 167px">
Имяnbsp;пользователя:</td>
<td>
nbsp;<asp:TextBox ID="UsernameText" runat="server" />
</td>
<td>
<asp:RequiredFieldValidator ID="UsernameRequiredValidator"
runat="server" ControlToValidate="UsernameText"
Display="Dynamic"
ErrorMessage='Не заполнено поле "Имя пользователя"'
ToolTip="Пустое поле ввода">*
</asp:RequiredFieldValidator>
<asp:RegularExpressionValidator ID="UsernameValidator"
runat="server" ControlToValidate="UsernameText"
Display="Dynamic" ErrorMessage="Неверное имя пользователя"
ToolTip="Допустимы буквы, цифры, пробелы и подчеркивания"
ValidationExpression="[а-яА-Я\w| ]*">*
</asp:RegularExpressionValidator>
</td>
</tr>
<tr>
<td>
nbsp;nbsp;nbsp;
</td>
<td align="right" height="43" style="width: 167px">
nbsp;Пароль:</td>
<td>
nbsp;<asp:TextBox ID="PasswordText" runat="server"
TextMode="Password" />
</td>
<td>
<asp:RequiredFieldValidator ID="PwdRequiredValidator"
runat="server" ControlToValidate="PasswordText"
Display="Dynamic" ErrorMessage='Не заполнено поле "Пароль"'
ToolTip="Пустое поле ввода">*
</asp:RequiredFieldValidator>
<asp:RegularExpressionValidator ID="PwdValidator" runat="server"
ControlToValidate="PasswordText"
Display="Dynamic" ErrorMessage="Неверный пароль"
ToolTip="Используются недопустимые символы"
ValidationExpression='[а-яА-Я\w| !"$amp;/()=\-?\*]*'>*
</asp:RegularExpressionValidator>
</td>
</tr>
</table>
<asp:Button ID="Button1" runat="server" Text="Отправить"
OnClick="LoginAction_Click" />
</asp:Panel>
<asp:Label ID="lblResult" runat="server" />
</div>
<asp:ValidationSummary ID="ValidationSummary1" runat="server" />
</form>
</body>
</html>
При такой инфраструктуре аутентификации любой пользователь, открывший сеанс с приложением, какую бы страницу он не запросил, будет направляться на страницу регистрации до тех пор, пока не введет свои данные, хранящиеся в удостоверении
В нашем файле Web.config до настоящего момента пароли хранились в виде
В секции <credentials> имеется параметр passwordFormat. Он предназначен для указания ASP.NET, в каком формате хранятся значения паролей и какой алгоритм
Параметр passwordFormat может принимать одно из трех следующих значений:
Clear - пароль не MD5 - пароль SHA1 - для Для предварительного
string hashedPwd = FormsAuthentication.HashPasswordForStoringInConfigFile(clearTextPassword, "MD5");
Добавьте к проекту страницу HashPasswordPage.aspx и наполните ее следующим кодом(рис ) Код страницы HashPasswordPage.aspx хеширования паролей в Web.config <%@ Page Language="C#" %>
<script runat="server">
protected void btnHashedPwd_Click(object sender, EventArgs e)
{
// Загрузить содержимое корневого Web.config
Configuration myConfig = System.Web.Configuration.
WebConfigurationManager.OpenWebConfiguration("~/");
// Найти содержимое секции system.web
ConfigurationSectionGroup systemWeb = myConfig.SectionGroups["system.web"];
// Найти содержимое секции authentication
System.Web.Configuration.AuthenticationSection authSec =
(System.Web.Configuration.AuthenticationSection)
systemWeb.Sections["authentication"];
// Установить параметр passwordFormat, сообщающий, что было хеширование по MD5
authSec.Forms.Credentials.PasswordFormat = System.Web.Configuration.FormsAuthPasswordFormat.MD5;
// Извлекаем из коллекции Users старые имена и пароли
int count = authSec.Forms.Credentials.Users.Count;
string[] name = new string[count];
string[] clearTextPwd = new string[count];
int i = 0;
foreach (System.Web.Configuration.FormsAuthenticationUser user in authSec.Forms.Credentials.Users)
{
name[i] = user.Name;
clearTextPwd[i] = user.Password;
i++;
}
// Очищаем коллекцию Users
authSec.Forms.Credentials.Users.Clear();
// Добавляем старые имена и новые хешированные пароли
for (i = 0; i < count; i++)
{
// Хешируем исходный пароль
string hashedPwd = FormsAuthentication.HashPasswordForStoringInConfigFile(clearTextPwd[i], "MD5");
// Добавляем в коллекцию Users
authSec.Forms.Credentials.Users.Add(
new System.Web.Configuration.FormsAuthenticationUser(name[i], hashedPwd));
}
// Обновляем файл Web.config
myConfig.Save();
// Отсылаем сообщение
lblHashResult.Text = "Хеширование завершено.<br />"
+ "Повторно не выполнять - будет хеш на хеш!!!";
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div style="text-align: center">
<h1>Административная страница хеширования паролей в Web.config</h1>
<p>
<asp:Button ID="btnHashedPwd" runat="server" OnClick="btnHashedPwd_Click" Text="Хешировать" /></p>
<p>
<asp:Label ID="lblHashResult" runat="server"></asp:Label></p>
</div>
</form>
</body>
</html>
Выполните страницу HashPasswordPage.aspx, но только один раз, чтобы повторно не хешировать уже В результате мы получим вариант
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<compilation debug="true" />
<authentication mode="Forms">
<forms
name="MyCookieName"
loginUrl="MyLogin.aspx"
defaultUrl="MyDefault.aspx"
protection="All"
timeout="20"
path="/"
requireSSL="false"
slidingExpiration="true"
cookieless="AutoDetect"
domain=""
enableCrossAppRedirects="false"
>
<credentials passwordFormat="MD5">
<user name="admin" password="FA03EB688AD8AA1DB593D33DABD89BAD" />
<user name="петя" password="B63974E3EE7B0920FE24DFB8E82FAE81" />
<user name="вася" password="44D4B2D42E830BE0DD43E6830D957C5D" />
<user name="user1" password="7C6A180B36896A0A8C02787EEAFB0E4C" />
<user name="user2" password="6CB75F652A9B52798EB6CF2201057C73" />
<user name="user3" password="819B0643D6B89DC9B579FDFC9094F28E" />
</credentials>
</forms>
</authentication>
<authorization>
<deny users="?"/>
</authorization>
</system.web>
</configuration>
Исходные пароли, вводимые пользователями при регистрации, остались прежними. Но в
До сих пор мы использовали временные
Постоянные
true (вместо false ) в методеFormsAuthentication.RedirectFromLoginPage(строка, true);
FormsAuthentication.SetAuthCookie(строка, true);
HttpCookie authCookie = FormsAuthentication.GetAuthCookie(строка, true); this.Response.Cookies.Add(authCookie);
Установленный таким способом
FormsAuthentication.SignOut();
Можно также изменить временной статус постоянного
Добавьте к проекту страницу ModifyPersistentCookieAuth.aspx без файла отделенного кода и заполните ее так(рис ) Страница создания на браузере постоянного cookie-набора аутентификации<%@ Page Language="C#" EnableViewState="false" %>
<script runat="server">
Label message;
protected void Page_Load(object sender, EventArgs e)
{
// Дескриптор центрирования
HtmlGenericControl center = new HtmlGenericControl("center");
form1.Controls.Add(center);
// Текстовая метка с заголовком
Label label = new Label();
center.Controls.Add(label);
label.Text = "<h2>Закрепить аутентификацию за браузером</h2>";
// Кнопки
Button createPersistentCookie = new Button();
center.Controls.Add(createPersistentCookie);
createPersistentCookie.Text = "Создать бессрочный AuthCookie";
createPersistentCookie.Click += new EventHandler(createPersistentCookie_Click);
center.Controls.Add(new HtmlGenericControl("br"));
Button createTemporaryCookie = new Button();
center.Controls.Add(createTemporaryCookie);
createTemporaryCookie.Text = "Создать срочный AuthCookie";
createTemporaryCookie.Click += new EventHandler(createTemporaryCookie_Click);
center.Controls.Add(new HtmlGenericControl("br"));
Button deleteCookie = new Button();
center.Controls.Add(deleteCookie);
deleteCookie.Text = "Удалить AuthCookie";
deleteCookie.Click += new EventHandler(deleteCookie_Click);
center.Controls.Add(new HtmlGenericControl("br"));
// Текстовая метка с сообщением
message = new Label();
center.Controls.Add(message);
message.Text = String.Empty;
}
void createPersistentCookie_Click(object sender, EventArgs e)
{
// Создать бессрочный cookie
HttpCookie authCookie = FormsAuthentication.GetAuthCookie("xx", true);
// Отослать на браузер
this.Response.Cookies.Add(authCookie);
// Сообщить пользователю
message.Text = "Бессрочный AuthCookie создан!";
}
void createTemporaryCookie_Click(object sender, EventArgs e)
{
// Создать бессрочный cookie
HttpCookie authCookie = FormsAuthentication.GetAuthCookie("xx", true);
// Настроить его как временный сроком на 10 дней
authCookie.Expires = DateTime.Now.AddDays(10);
// Отослать на браузер
this.Response.Cookies.Add(authCookie);
// Сообщить пользователю
message.Text = "Срочный AuthCookie создан!";
}
void deleteCookie_Click(object sender, EventArgs e)
{
// Удалить cookie-набор регистрации
FormsAuthentication.SignOut();
// Сообщить пользователю
message.Text = "AuthCookie удален!";
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
</form>
</body>
</html>
Интерфейс страницы в режиме выполнения будет таким
При закреплении

API Membership является готовой инфраструктурой в ASP.NET, предназначенной для организации управления Membership.
Чаще всего к корневому каталогу сайта допускаются все ананимные пользователи без регистрации, а защищенные ресурсы, требующие аутентификацию, размещаются в
Для использования API Membership нужно выполнитиь следующие шаги:
SQL Server 2005 создает базы данных и работает с ними как с отдельными файлами с расширением .mdf. По умолчанию эти файла размещаются в каталоге
C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data
Мы сами можем вручную создать файл базы данных для хранения удостоверений и добавить в нее таблицы с необходимыми полями. Но это может не стыковаться с API Membership, поскольку он ожидает базу данных определенной структуры. К тому же нужно будет прописывать в
Создайте новый пустой проект командой
Откройте окно копирования проектов командой Тестовые страницы Default.aspx и MyDefault.aspx из предыдущего проекта, сконфигурированные для проверки аутентификации, будут следующими
<%@ Page Language="C#" %>
<script runat="server">
protected void SignOutAction_Click(object sender, EventArgs e)
{
// Уничтожить cookie-набор
FormsAuthentication.SignOut();
// Направить на страницу регистрации
//FormsAuthentication.RedirectToLoginPage();
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h1>
Страница с ограниченным доступом Default.aspx</h1>
<p>
<asp:Button ID="SignOutAction" runat="server"
Text="Отменить регистрацию" OnClick="SignOutAction_Click" />
<asp:HyperLink ID="HyperLink1" runat="server"
NavigateUrl="~/MyDefault.aspx">На страницу MyDefault.aspx...
</asp:HyperLink></p>
</div>
</form>
</body>
</html>
<%@ Page Language="C#" %>
<script runat="server">
protected void SignOutAction_Click(object sender, EventArgs e)
{
// Уничтожить cookie-набор
FormsAuthentication.SignOut();
// Направить на страницу регистрации
//FormsAuthentication.RedirectToLoginPage();
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h1>
Страница с ограниченным доступом MyDefault.aspx</h1>
<p>
<asp:Button ID="SignOutAction" runat="server"
OnClick="SignOutAction_Click" Text="Отменить регистрацию" />
<asp:HyperLink ID="HyperLink1" runat="server"
NavigateUrl="~/Default.aspx">На страницу Default.aspx...
</asp:HyperLink></p>
</div>
</form>
</body>
</html>
Код страницы регистрации MyLogin.aspx мы рассмотрим чуть позже, вместе с введенными изменениями.
Откройте в новом проекте скопированный файл web.config и удалите из него секцию В результате
<?xml version="1.0" encoding="utf-8"?> <configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"> <system.web> <compilation debug="true" /> <authentication mode="Forms"> <forms name="MyCookieName" loginUrl="MyLogin.aspx" defaultUrl="MyDefault.aspx" protection="All" timeout="20" path="/" requireSSL="false" slidingExpiration="true" cookieless="AutoDetect" domain="" enableCrossAppRedirects="false"> </forms> </authentication> <!-- Временно закомментировали, чтобы не требовал регистрации <authorization> <deny users="?"/> </authorization> --> </system.web> </configuration>
Запустите утилиту WAT командой Website/ASP.NET Configuration и обратите внимание, как долго она запускаетсяЗамечание. Эта утилита может не запускаться, если абсолютный путь к созданному проекту имеет пробелы или кириллицу. В этом случае переместите проект в другое место файловой системы компьютера.
В панели Solution Explorer щелкните на кнопке RefreshМы видим, что утилита WAT так долго запускалась потому, что добавила к проекту каталог App_Data (если до этого его еще не было) и создала в нем базу данных ASPNETDB.MDF, готовую для хранения удостоверений и согласованную с API Membership

В панели Такой способ хранения удостоверений пользователей в локальной базе данных вместе с приложением очень удобен, поскольку позволяет перемещать сайт в любое место сервера или разворачивать на любом сервере без дополнительных настроек подключения SQL Server. Да и Membership будут согласованы с хранилищем удостоверений.
Утилита WAT автоматически создает хранилище удостоверений только в том случае, если обнаружит в корневом
<authentication mode="Forms">
Если на момент запуска утилиты WAT файл конфигурации в
Для того, чтобы проверить работоспособность созданной локальной базы данных, выполните следующее:
Запустите утилиту WAT командой Website/ASP.NET Configuration
На вкладке Home щелкните на
На вкладке Provider щелкните на
В сгенерированном страницей ManageConsolidatedProviders.aspx отклике щелкните на 
В результате страница пришлет ответ, что созданная нами локальная база данных функционирует нормально.
Важно отметить, что хоть утилита WAT автоматически создала базу данных для поддержки
На данном этапе мы рассмотрим интерактивный способ добавления пользователей с применением утилиты WAT. В дальнейшем можно будет создать свои административные страницы для программного добавления пользователей в это хранилище, используя классы Membership. При этом нужно помнить, что хранилище удостоверений будет размещаться на удаленном сервере и поддерживать его мы будем как удаленные пользователи либо через WAT, либо через собственные административные страницы, также хранящиеся на сервере.
Для создания новых аутентифицированных пользователей через утилиту WAT выполните следующее:
В панели Solution Explorer щелкните на пиктограмме ASP.NET Configuration, чтобы запустить утилиту WAT
Перейдите на вкладку Security и щелкните на Появится следующий отклик утилиты WAT

Сообщение на странице предлагает ввести
В утилите за
Заполните поля страницы для добавления в хранилище одного пользователя со следующими характеристиками| User Name: | |
| Password: | RootRoot |
| Confirm Password: | RootRoot |
| E-mail: | |
| Security Question: | У Вас продается славянский шкаф ? |
| Security Answer: | Шкаф уже продан, осталась только тумбочка ! |
После этого действия новый пользователь будет создан в базе данных.
В появившемся отклике щелкните на кнопке Continue, чтобы вернутся к интерфейсу добавления следующего пользователя, либо закройте WATНа данном этапе для проверки аутентификации с использованием API Membership и хранилища
Модифицируйте страницу регистрации MyLogin.aspx, чтобы код стал таким(рис ) Код страницы регистрации MyLogin.aspx<%@ Page Language="C#" EnableViewState="false" %>
<script runat="server">
protected void LoginAction_Click(object sender, EventArgs e)
{
this.Validate();// Исполнить валидаторы на сервере
if (!this.IsValid)// Оценить флаг достоверности
return;// Отправить назад как есть
// Извлечь из базы данных и сравнить с введенным
if (Membership.ValidateUser(UsernameText.Text, PasswordText.Text))
{
// Создать временный cookie-набор (второй параметр false),
// записать в него метку аутентификации и перенаправить
// на исходную запрошенную страницу или MyDefault.aspx
// с созданием coockie-набора только на период сеанса
FormsAuthentication.RedirectFromLoginPage(UsernameText.Text, false);
}
else
{
HtmlGenericControl message = new HtmlGenericControl();
message.InnerHtml = "<h2 style='color: Red'>Неверное имя или пароль!</h2>";
form1.Controls.Add(message);
}
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Untitled Page</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>
nbsp;nbsp;nbsp;
</td>
<td align="right" height="43" style="width: 167px">
Имяnbsp;пользователя:</td>
<td>
nbsp;<asp:TextBox ID="UsernameText" runat="server" />
</td>
<td>
<asp:RequiredFieldValidator ID="UsernameRequiredValidator"
runat="server" ControlToValidate="UsernameText"
Display="Dynamic"
ErrorMessage='Не заполнено поле "Имя пользователя"'
ToolTip="Пустое поле ввода">*
</asp:RequiredFieldValidator>
<asp:RegularExpressionValidator ID="UsernameValidator"
runat="server" ControlToValidate="UsernameText"
Display="Dynamic" ErrorMessage="Неверное имя пользователя"
ToolTip="Допустимы буквы, цифры, пробелы и подчеркивания"
ValidationExpression="[а-яА-Я\w| ]*">*
</asp:RegularExpressionValidator>
</td>
</tr>
<tr>
<td>
nbsp;nbsp;nbsp;
</td>
<td align="right" height="43" style="width: 167px">
nbsp;Пароль:</td>
<td>
nbsp;<asp:TextBox ID="PasswordText" runat="server"
TextMode="Password" />
</td>
<td>
<asp:RequiredFieldValidator ID="PwdRequiredValidator"
runat="server" ControlToValidate="PasswordText"
Display="Dynamic" ErrorMessage='Не заполнено поле "Пароль"'
ToolTip="Пустое поле ввода">*
</asp:RequiredFieldValidator>
<asp:RegularExpressionValidator ID="PwdValidator" runat="server"
ControlToValidate="PasswordText"
Display="Dynamic" ErrorMessage="Неверный пароль"
ToolTip="Используются недопустимые символы"
ValidationExpression='[а-яА-Я\w| !"$amp;/()=\-?\*]*'>*
</asp:RegularExpressionValidator>
</td>
</tr>
</table>
<asp:Button ID="Button1" runat="server" Text="Отправить"
OnClick="LoginAction_Click" />
</asp:Panel>
<asp:Label ID="lblResult" runat="server" />
</div>
<asp:ValidationSummary ID="ValidationSummary1" runat="server" />
</form>
</body>
</html>
Запустите приложение с любой страницы и введите | User Name: | |
| Password: | RootRoot |
С помощью утилиты WAT добавьте в хранилище еще несколько пользователей и убедитесь, что аутентификация на основе Membership и хранилища удостоверений в При добавлении новых пользователей следует иметь ввиду, что реляционной таблицы aspnet_Users и является основой для формирования поля как
В панели Server Explorer установите ASPNETDB
Для таблиц aspnet_Users и aspnet_Membership выполните команду Show Table Data контекстного меню
После таких действий откроются таблицы aspnet_Users и aspnet_Membership, в которых можно найти информацию о созданных пользователях. Для того, чтобы увидеть структуру таблиц, следует выполнить для них команду Open Table Definition контекстного меню.
Интерфейс API Membership включает в себя следующие классы пространства имен System.Web.Security:
Membership - статический класс, имеющий ряд полезных методов MembershipCreateUserException - исключение, генерируемое ошибкой MembershipPasswordException - исключение при невозможности извлечения пароляMembershipUser - объект этого класса содержит всю информацию о пользователе и возвращается методом Membership.GetUser()MembershipUserCollection - коллекция пользователей, извлекаемая методом Membership.GetAllUsers()MembershipProvider - MembershipProviderCollection - коллекция доступных для приложения поставщиков на данной машинеSqlMembershipProvider - поставщик для работы с базами данных SQL ServerActiveDirectoryMembershipProvider - поставщик для работы со службой Active DirectoryActiveDirectoryMembershipUser - класс поддержки пользователя, расширенный для работы со службой Active DirectoryИспользуя API Membership, можно программно решать, например, следующие задачи:
Для создания и удаления пользователей следует применить перегруженные CreateUser() и класса Membership. Нужно создать административные страницы, содержащие требуемые поля для ввода информации. Поля можно контролировать
Метод CreateUser() имеет несколько перегрузок, из которых простейшая принимает только имя и пароль. В то же время более полные CreateUser() содержит экземпляр перечисления MembershipCreateStatus в качестве CreateUser(), включающую контрольный вопрос и ответ, чтобы избежать выброса исключения MembershipCreateUserException.
Удаление пользователя выполняется методом Membership., которому передается в качестве параметра
В качестве примера создадим собственную страницу добавления, имеющую аналогичную функциональность с WAT, и отдельно страницу удаления пользователя в
Скопируйте страницу MyLogin.aspx и присвойте копии имя AddUserMembership.aspxCustomValidator. С помощью этого элемента реализуем проверку достоверности на клиенте и на сервере.
Неалфавитно-цифровые символы представим в виде
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | ||||||||||
| 1 | ||||||||||
| 2 | ||||||||||
| 3 | ! | " | # | $ | % | ' | ||||
| 4 | ( | ) | * | + | , | . | / | |||
| 5 | : | ; | ||||||||
| 6 | < | = | > | ? | @ | |||||
| 7 | ||||||||||
| 8 | ||||||||||
| 9 | [ | \ | ] | ^ | _ | |||||
| 10 | ||||||||||
| 11 | ||||||||||
| 12 | { | | | } | ~ |
Строка
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);
Переделайте интерфейсную и кодовую части страницы, чтобы она стала такой(рис ) Административная страница AddUserMembership.aspx добавления пользователей в БД<%@ 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 и убедитесь в работоспособности рассматриваемого механизма добавления пользователей в Теперь рассмотрим вопрос удаления пользователей. Он намного проще, чем создание. Нужно только применить метод 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, которая будет примерно такой(рис ) Административная страница 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>
Испытайте страницу удаления пользователейДля получения списка пользователей применяют метод Membership.GetAllUsers(), а для извлечения конкретного пользователя - метод Membership.GetUser().
Рассмотрим пример, в котором будем использовать элемент для представления пользователей в виде таблицы.
Добавьте к проекту страницу GetUsersMembership.aspx и назначьте ее стартовой
Заполните страницу следующим кодом(рис ) Код страницы GetUsersMembership.aspx для извлечения пользователей<%@ Page Language="C#" EnableViewState="false" %>
<script runat="server">
// Вынесли поле для видимости в обработчиках
MembershipUserCollection myUsers = new MembershipUserCollection();
protected void Page_Load(object sender, EventArgs e)
{
// Скрываем таблицу деталей
tableDetails.Visible = false;
lblUser.Visible = false;
if (checkUser.Checked)
{
// Извлекаем одного пользователя
if (txtUser.Text.Length == 0)
{
lblUsersList.Text = "Введите имя пользователя";
return;
}
try // Попытка
{
string user = Server.HtmlEncode(txtUser.Text);
myUsers = new MembershipUserCollection();
myUsers.Add(Membership.GetUser(user));
}
catch // Откат
{
lblUsersList.Text = "Пользователь не найден";
return;
}
}
else
{
// Извлекаем всех пользователей
myUsers = Membership.GetAllUsers();
}
// Подключаем к сетке извлеченную информации и наполняем элемент
UsersGridView.DataSource = myUsers;
UsersGridView.DataBind();
}
// Обработчик щелчков на ссылки столбца отображения деталей
protected void UsersGridView_SelectedIndexChanged(object sender, EventArgs e)
{
if (UsersGridView.SelectedIndex >= 0)
{
// Заполняем интерфейсные элементы отображаемой информацией,
// адресуясь к конкретному пользователю по ключевому имени,
// заданному параметром DataKeyNames="UserName" элемента GridView
MembershipUser currentUser =
myUsers[(string)UsersGridView.SelectedValue];
lblUserName.Text = currentUser.UserName;
lblEmail.Text = currentUser.Email;
lblPasswordQuestion.Text = currentUser.PasswordQuestion;
lblLastLoginDate.Text = currentUser.LastLoginDate.ToLongDateString();
txtComment.Text = currentUser.Comment;
checkIsApproved.Checked = currentUser.IsApproved;
checkIsLockedOut.Checked = currentUser.IsLockedOut;
// Включаем видимость таблицы деталей
tableDetails.Visible = true;
lblUser.Visible = true;
}
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h2>
<asp:Label ID="lblUsersList" runat="server" Font-Bold="true"
Text="Список зарегистрированных пользователей"></asp:Label>
</h2>
<p>Конкретный пользователь:
<asp:CheckBox ID="checkUser" runat="server" />
<asp:TextBox ID="txtUser" runat="server"></asp:TextBox>
<asp:Button ID="btnUser" runat="server" Text="Получить" /></p>
<asp:GridView ID="UsersGridView" runat="server"
DataKeyNames="UserName"
AutoGenerateColumns="False"
OnSelectedIndexChanged="UsersGridView_SelectedIndexChanged">
<Columns>
<asp:BoundField DataField="UserName" HeaderText="Имя" />
<asp:BoundField DataField="Email" HeaderText="email" />
<asp:BoundField DataField="CreationDate" HeaderText="Создан" />
<asp:CommandField ShowSelectButton="True" HeaderText="Детали"
SelectText="Показать" />
</Columns>
</asp:GridView>
<h2>
<asp:Label ID="lblUser" runat="server"
Text="Подробности для выделенного пользователя"
Visible="False" Font-Bold="true"></asp:Label>
</h2>
<table id="tableDetails" border="1" bordercolor="#0000FF"
width="100%" runat="server">
<tr>
<td width="50%">
Пользователь:</td>
<td>
<asp:Label ID="lblUserName" runat="server"></asp:Label></td>
</tr>
<tr>
<td width="50%">
email:</td>
<td>
<asp:Label ID="lblEmail" runat="server"></asp:Label></td>
</tr>
<tr>
<td width="50%">
Контрольный вопрос:</td>
<td>
<asp:Label ID="lblPasswordQuestion" runat="server"></asp:Label></td>
</tr>
<tr>
<td width="50%">
Дата последней регистрации:</td>
<td>
<asp:Label ID="lblLastLoginDate" runat="server"></asp:Label></td>
</tr>
<tr>
<td valign="top" width="50%">
Комментарии:</td>
<td>
<asp:TextBox ID="txtComment" runat="server" TextMode="MultiLine"
Width="100%"></asp:TextBox></td>
</tr>
<tr>
<td width="50%">
Проверенный:</td>
<td>
<asp:CheckBox ID="checkIsApproved" runat="server" /></td>
</tr>
<tr>
<td width="50%">
Заблокирован:</td>
<td>
<asp:CheckBox ID="checkIsLockedOut" runat="server" /></td>
</tr>
</table>
</div>
</form>
</body>
</html>
Интерфейсная часть страницы представлена элементом и текстовыми метками, спозиционированными в серверной таблице. Значения параметров элемента представляют собой имена полей таблиц aspnet_Users и aspnet_Membership базы данных

Установка в элементе управления свойства DataKeyNames=" позволяет извлекать значения поля через , что очень удобно при получении подробностей о конкретном пользователе из коллекции пользователей.
Метод Membership.GetUser() возвращает объект запрошенного пользователя, свойства которого мы отображаем в текстовых элементах, скомпонованных в таблице. Привязка к свойствам объекта пользователя выполняется в обработчике события SelectedIndexChanged элемента управления .
Результат работы страницы GetUsersMembership.aspx будет примерно таким

Извлечение пароля напрямую через свойство не предусмотрено в классе MembershipUser. Для этого существует метод MembershipUser.GetPassword(), который работает только тогда, когда поставщик SqlMembershipProvider сконфигурирован с параметром enablePasswordRetrieval="true" в
Наша задача - перенастроить поставщик по умолчанию, создав для этого поставщик того же типа, но с другими настройками. Новый поставщик в той же базе данных будет иметь доступ только к своим данным. Включение параметра enablePasswordRetrieval="true" несовместимо с настройкой passwordFormat=", а должно иметь значения " или "
Измените (рис ) Конфигурационный файл с новыми настройками поставщика SqlMembershipProvider<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<system.web>
<compilation debug="true" />
<authentication mode="Forms">
<forms
name="MyCookieName"
loginUrl="MyLogin.aspx"
defaultUrl="MyDefault.aspx"
protection="All"
timeout="20"
path="/"
requireSSL="false"
slidingExpiration="true"
cookieless="AutoDetect"
domain=""
enableCrossAppRedirects="false">
</forms>
</authentication>
<!-- Временно закомментировали, чтобы не требовал регистрации
<authorization>
<deny users="?"/>
</authorization>
-->
<membership defaultProvider="MyMembershipProvider">
<providers>
<add name="MyMembershipProvider" connectionStringName="MyMembershipConnString"
enablePasswordReset="true" requiresQuestionAndAnswer="true"
requiresUniqueEmail="false" enablePasswordRetrieval="true" passwordFormat="Clear"
type="System.Web.Security.SqlMembershipProvider"
/>
</providers>
</membership>
</system.web>
<connectionStrings>
<add name="MyMembershipConnString"
connectionString="Data Source=localhost; Initial Catalog=ASPNETDB; user id=sa; password=;"
/>
</connectionStrings>
</configuration>
Добавьте новых пользователей с помощью нашей административной страницы AddUserMembership.aspx
Получите из страницы GetUsersMembership.aspx копию с именем GetUsersMyMembershipProvider.aspx, назначьте ее стартовой и добавьте в интерфейсную часть текстовую метку lblPassword для отображения пароля
Добавьте в обработчик события SelectedIndexChanged строку заполнения меткиlblPassword.Text = currentUser.GetPassword();
Если у нас есть экземпляр класса MembershipUser, то мы можем обновить его свойства, имеющие аксессор set, а именно:
Comment Email IsApprovedLastActivityDateLastLoginDateДля этого используется Membership.UpdateUser().
Получите из страницы GetUsersMembership.aspx копию с именем UpdateUserMembership.aspx
Скорректируйте страницу UpdateUserMembership.aspx, чтобы обновляемые параметры таблицы деталей размещались в текстовых полях
Закрепите за полем txtEmail элементы проверки достоверности RequiredFieldValidator и RegularExpressionValidatorОкончательный код страницы UpdateUserMembership.aspx будет таким
<%@ Page Language="C#" EnableViewState="false" %>
<%@ Import Namespace="System.Web.Security" %>
<script runat="server">
// Вынесли поле для видимости в обработчиках
MembershipUserCollection myUsers = new MembershipUserCollection();
protected void Page_Load(object sender, EventArgs e)
{
// Скрываем таблицу деталей
tableDetails.Visible = false;
lblUser.Visible = false;
// Извлекаем всех пользователей
myUsers = Membership.GetAllUsers();
// Подключаем к сетке извлеченную информации и наполняем элемент
UsersGridView.DataSource = myUsers;
UsersGridView.DataBind();
}
// Обработчик щелчков на ссылки столбца отображения деталей
protected void UsersGridView_SelectedIndexChanged(object sender, EventArgs e)
{
if (UsersGridView.SelectedIndex >= 0)
{
// Заполняем интерфейсные элементы отображаемой информацией,
// адресуясь к конкретному пользователю по ключевому имени,
// заданному параметром DataKeyNames="UserName" элемента GridView
MembershipUser currentUser =
myUsers[(string)UsersGridView.SelectedValue];
lblUserName.Text = currentUser.UserName;
txtEmail.Text = currentUser.Email;
lblPasswordQuestion.Text = currentUser.PasswordQuestion;
lblLastLoginDate.Text = currentUser.LastLoginDate.ToLongDateString();
txtComment.Text = currentUser.Comment;
checkIsApproved.Checked = currentUser.IsApproved;
checkIsLockedOut.Checked = currentUser.IsLockedOut;
// Включаем видимость таблицы деталей
tableDetails.Visible = true;
lblUser.Visible = true;
}
}
protected void btnUpdate_Click(object sender, EventArgs e)
{
if (UsersGridView.SelectedIndex >= 0)
{
// Адресуемся к выделенному пользователю
MembershipUser currentUser =
myUsers[(string)UsersGridView.SelectedValue];
// Избавляемся от возможных управляющих символов
// в пользовательском вводе
currentUser.Email = Server.HtmlEncode(txtEmail.Text);
currentUser.Comment = Server.HtmlEncode(txtComment.Text);
currentUser.IsApproved = checkIsApproved.Checked;
// Сбрасываем в базу данных
Membership.UpdateUser(currentUser);
// Обновить содержимое GridView из БД, поскольку
// этот обработчик выполнится после Page_Load
myUsers = Membership.GetAllUsers();// Извлекаем пользователей
UsersGridView.DataBind();
}
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h2>
<asp:Label ID="lblUsersList" runat="server" Font-Bold="true"
Text="Список зарегистрированных пользователей"></asp:Label>
</h2>
<asp:GridView ID="UsersGridView" runat="server"
DataKeyNames="UserName"
AutoGenerateColumns="False"
OnSelectedIndexChanged="UsersGridView_SelectedIndexChanged">
<Columns>
<asp:BoundField DataField="UserName" HeaderText="Имя" />
<asp:BoundField DataField="Email" HeaderText="email" />
<asp:BoundField DataField="CreationDate" HeaderText="Создан" />
<asp:CommandField ShowSelectButton="True" HeaderText="Детали"
SelectText="Показать" />
</Columns>
</asp:GridView>
<h2>
<asp:Label ID="lblUser" runat="server"
Text="Подробности для выделенного пользователя"
Visible="False" Font-Bold="true"></asp:Label>
</h2>
<table id="tableDetails" border="1" bordercolor="#0000FF"
width="100%" runat="server">
<tr>
<td width="50%">
Пользователь:</td>
<td>
<asp:Label ID="lblUserName" runat="server"></asp:Label></td>
</tr>
<tr>
<td width="50%">
<font color="#0000FF">email:</font></td>
<td>
<asp:TextBox ID="txtEmail" runat="server" Width="100%">
</asp:TextBox>
<asp:RequiredFieldValidator
ID="RequiredFieldValidator1" runat="server"
ControlToValidate="txtEmail" Display="Dynamic">*
</asp:RequiredFieldValidator>
<asp:RegularExpressionValidator ID="RegularExpressionValidator1"
runat="server" ControlToValidate="txtEmail"
Display="Dynamic"
ValidationExpression="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*">*
</asp:RegularExpressionValidator></td>
</tr>
<tr>
<td width="50%">
Контрольный вопрос:</td>
<td>
<asp:Label ID="lblPasswordQuestion" runat="server"></asp:Label></td>
</tr>
<tr>
<td width="50%">
Дата последней регистрации:</td>
<td>
<asp:Label ID="lblLastLoginDate" runat="server"></asp:Label></td>
</tr>
<tr>
<td valign="top" width="50%">
<font color="#0000FF">Комментарии:</font></td>
<td>
<asp:TextBox ID="txtComment" runat="server" TextMode="MultiLine"
Width="100%"></asp:TextBox></td>
</tr>
<tr>
<td width="50%">
<font color="#0000FF">Проверенный:</font></td>
<td>
<asp:CheckBox ID="checkIsApproved" runat="server" /></td>
</tr>
<tr>
<td width="50%">
Заблокирован:</td>
<td>
<asp:CheckBox ID="checkIsLockedOut" runat="server" /></td>
</tr>
<tr>
<td colspan="2" align="center">
<asp:Button ID="btnUpdate" runat="server" Text="Обновить"
OnClick="btnUpdate_Click" /></td>
</tr>
</table>
</div>
</form>
</body>
</html>
Безопасность включает в себя ряд мероприятий, необходимых для предотвращения несанкционированного доступа к сайту и
Основные задачи по защите сайта следующие:
Аутентификация нового пользователя начинается с его регистрации. Пользователю предлагается страница регистрации с текстовыми полями, через которую у него запрашиваются некоторые идентификационные данные. По этим данным создается и сохраняется
Теперь при запросе ограниченного ресурса пользователь предъявит свое удостоверение, которое система верифицирует и примет решение: если удостоверение пользователя подтверждается, ему предоставляется доступ к Web-ресурсу, иначе будет предложена регистрация. Процесс аутентификации может выглядеть примерно так

В приложениях ASP.NET аутентификация может быть реализована одним из следующих способов:
System.Web.Security.FormsAuthenticationModuleSystem.Web.Security.WindowsAuthenticationModuleSystem.Web.Security.PassportAuthenticationModuleСистемы коммуникации шифруются с помощью системы SSL (
Обычно сервер, которому клиент собирается пересылать важные данные, маркируется сертификатом. Сертификат - это некоторый паспорт сервера, подтверждающий тот факт, что ему можно доверять. Организация, которой принадлежит сервер, приобретает сертификат у известного
Наиболее популярными центрами
Инсталированный на
Клиент (браузер) доверяет CA и поэтому готов доверять подписанной CA информации. В свою очередь, CA сохраняет информацию о каждом зарегистрированном пользователе. Начало работы по защищенному каналу связи начинается так:
Аутентификация (распознавание) на основе форм реализуется в пространстве имен System.Web.Security классами:
FormsAuthenticationModuleFormsAuthenticationFormsAuthenticationEventArgsFormsAuthenticationTicketFormsIdentityВыбор этого режима устанавливается только в одном единственном месте -
<authentication mode="Forms" />
Аутентификацию форм можно выполнять и с помощью API-интерфейсов Membership и Roles (об этом позже).
Аутентификация форм основана на удостоверениях (
Для реализации аутентификации форм нужно выполнить следующее:
В файле web.config виртуального корневого каталога сайта необходимо определить нужные параметры аутентификации, как System.Web.Configuration.FormsAuthenticationConfiguration, из следующего набора:
| Опция | Значение по умолчанию | Описание |
|---|---|---|
Name |
.ASPXAUTH |
Имя |
LoginUrl |
|
Определяет страницу регистрации пользователя при запросе защищенной страницы ( - |
|
30 |
Время жизни |
SlidingExpiration |
false |
Включает режим скользящего устаревания |
Cookieless |
UseDeviceProfile |
Указывает способ пересылки удостоверения пользователя |
Protection |
All |
Задает уровень безопасности None - не - только - только подписыватьAll - |
RequireSSL |
false |
При включении требует передачи через |
EnableCrossAppRedirects |
false |
Разрешает переадресацию между приложениями при использовании аутентификации форм. Оба приложения должны опираться на одно и то же хранилище удостоверений |
DefaultUrl |
default.aspx |
Указывает страницу, на которую направляется пользователь после успешной регистрации, если он напрямую запросил страницу регистрации, указанную в LoginUrl |
|
пусто | Может указывать |
Path |
/ |
Путь для |
Перечисленные свойства устанавливаются как атрибуты дочернего дескриптора <forms> секции <. Вот пример использования полного набора этих атрибутов в файле web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<compilation debug="true" />
<authentication mode="Forms">
<forms
name="MyCookieName"
loginUrl="MyLogin.aspx"
timeout="20"
slidingExpiration="true"
cookieless="AutoDetect"
protection="All"
requireSSL="false"
enableCrossAppRedirects="false"
defaultUrl="MyDefault.aspx"
domain=""
path="/"
/>
</authentication>
</system.web>
</configuration>
Хоть это и не самый лучший способ хранения удостоверений пользователей, зато самый простой. Вообще, удостоверения можно хранить где угодно, только нужно предусмотреть соответствующий код их сравнения с введенными на странице регистрации данными. Если удостоверения хранятся в файле web.config, то их нужно помещать в дочерний для <forms> дескриптор <credentials>. Вот пример для трех пользователей
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<compilation debug="true" />
<authentication mode="Forms">
<forms
name="MyCookieName"
loginUrl="MyLogin.aspx"
timeout="20"
slidingExpiration="true"
cookieless="AutoDetect"
protection="All"
requireSSL="false"
enableCrossAppRedirects="false"
defaultUrl="MyDefault.aspx"
domain=""
path="/"
>
<credentials passwordFormat="Clear">
<user name="Admin" password="Root" />
<user name="Petja" password="Xa-xa" />
<user name="Vasja" password="Xo-xo" />
</credentials>
</forms>
</authentication>
</system.web>
</configuration>
Рассмотрим пример
Пользователей в <credentials>, так и программно.
Создайте пустой проект Web-приложения командой
Добавьте к приложению
Заполните (рис ) Код конфигурационного файла<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<compilation debug="true" />
<authentication mode="Forms">
<forms
name="MyCookieName"
loginUrl="MyLogin.aspx"
defaultUrl="MyDefault.aspx"
protection="All"
timeout="20"
path="/"
requireSSL="false"
slidingExpiration="true"
cookieless="AutoDetect"
domain=""
enableCrossAppRedirects="false">
<credentials passwordFormat="Clear">
<user name="Admin" password="Root" />
<user name="Петя" password="Уфamp;Уф" />
<user name="Вася" password='!$-*?"' />
</credentials>
</forms>
</authentication>
</system.web>
</configuration>
Добавьте к проекту страницу без отделенного кода с именем LoginAddUsers.aspx и заполните ее следующим кодом(рис ) Страница LoginAddUsers.aspx<%@ Page Language="C#" %>
<%@ Import Namespace="System.Web.Configuration" %>
<script runat="server">
protected void btnAddUsers_Click(object sender, EventArgs e)
{
// Учетные записи для новых аутентифицированных пользователей
string[,] authUsers = {
{"user1", "password1"},
{"user2", "password2"},
{"user3", "password3"}
};
// Загрузить содержимое корневого Web.config
Configuration myConfig = System.Web.Configuration.
WebConfigurationManager.OpenWebConfiguration("~/");
// Найти содержимое секции system.web
ConfigurationSectionGroup systemWeb = myConfig.SectionGroups["system.web"];
// Найти содержимое секции authentication
System.Web.Configuration.AuthenticationSection authSec =
(System.Web.Configuration.AuthenticationSection)
systemWeb.Sections["authentication"];
// Установить параметр passwordFormat
authSec.Forms.Credentials.PasswordFormat = System.Web.Configuration.FormsAuthPasswordFormat.Clear;
// Добавить новых пользователей
for (int i = 0; i < authUsers.Length / 2; i++)
authSec.Forms.Credentials.Users.Add(new System.Web.Configuration.FormsAuthenticationUser(
authUsers[i, 0], authUsers[i, 1]));
// Обновить файл Web.config
myConfig.Save();
// Отсылаем сообщение
lblUsersResult.Text = "Новые пользователи добавлены!!!";
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div style="text-align: center">
<h1>Административная страница добавления учетных записей в Web.config</h1>
<p>
<asp:Button ID="btnAddUsers" runat="server" Text="Добавить" OnClick="btnAddUsers_Click" /></p>
<p>
<asp:Label ID="lblUsersResult" runat="server"></asp:Label></p>
</div>
</form>
</body>
</html>
Обратите внимание. Чтобы не использовать длинные имена классов в страницах с совмещенным кодом, можно подключить вначале страницы <%@ Import Namespace="System.Web.Configuration" %>
В режиме редактирования страницы LoginAddUsers.aspx выполните команду File/View in BrowserЭта страница программно добавит новых пользователей в файл Web.config. Также будут скорректированы имена старых пользователей путем приведения символов к нижнему регистру. Но это не существенно, поскольку ASP.NET при сравнении имен регистр символов не учитывает.
Добавьте в (рис ) Окончательный вид файла Web.config<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<compilation debug="true" />
<authentication mode="Forms">
<forms
name="MyCookieName"
loginUrl="MyLogin.aspx"
defaultUrl="MyDefault.aspx"
protection="All"
timeout="20"
path="/"
requireSSL="false"
slidingExpiration="true"
cookieless="AutoDetect"
domain=""
enableCrossAppRedirects="false">
<credentials passwordFormat="Clear">
<user name="admin" password="Root" />
<user name="петя" password="Уфamp;Уф" />
<user name="вася" password="!$-*?quot;" />
<user name="user1" password="password1" />
<user name="user2" password="password2" />
<user name="user3" password="password3" />
</credentials>
</forms>
</authentication>
<authorization>
<deny users="?"/>
</authorization>
</system.web>
</configuration>
Добавьте к проекту две страницы без отделенного кода с именами Default.aspx и MyDefault.aspx со следующим кодом(рис ) Страница Default.aspx<%@ Page Language="C#" %>
<script runat="server">
protected void SignOutAction_Click(object sender, EventArgs e)
{
// Уничтожить cookie-набор
FormsAuthentication.SignOut();
// Направить на страницу регистрации
//FormsAuthentication.RedirectToLoginPage();
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h1>
Страница с ограниченным доступом Default.aspx</h1>
<p>
<asp:Button ID="SignOutAction" runat="server"
Text="Отменить регистрацию" OnClick="SignOutAction_Click" />
<asp:HyperLink ID="HyperLink1" runat="server"
NavigateUrl="~/MyDefault.aspx">На страницу MyDefault.aspx...
</asp:HyperLink></p>
</div>
</form>
</body>
</html>
<%@ Page Language="C#" %>
<script runat="server">
protected void SignOutAction_Click(object sender, EventArgs e)
{
// Уничтожить cookie-набор
FormsAuthentication.SignOut();
// Направить на страницу регистрации
//FormsAuthentication.RedirectToLoginPage();
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h1>
Страница с ограниченным доступом MyDefault.aspx</h1>
<p>
<asp:Button ID="SignOutAction" runat="server"
OnClick="SignOutAction_Click" Text="Отменить регистрацию" />
<asp:HyperLink ID="HyperLink1" runat="server"
NavigateUrl="~/Default.aspx">На страницу Default.aspx...
</asp:HyperLink></p>
</div>
</form>
</body>
</html>
Страница регистрации предоставляет пользователю интерфейс для ввода имени и пароля, принимает их и сравнивает с удостоверениями, хранящимися на сервере. Если удостоверения хранятся прямо в
Страница регистрации должна включать в себя
Создайте новую страницу с именем MyLogin.aspx без отделенного кода
Заполните страницу элементами управления и настройте их согласно таблице| Элемент | Свойство | Значение | Пояснение |
|---|---|---|---|
|
ID |
MainPanel |
Родительская панель для оформления рамкой |
BorderColor |
Silver |
Цвет рамки | |
|
|
Тип рамки | |
TextBox |
ID |
UsernameText |
Текстовое |
RequiredFieldValidator |
ID |
UsernameRequiredValidator |
Проверка достоверности, чтобы привязанное поле не было пустым |
ControlToValidate |
UsernameText |
Привязка к контролируемому элементу ввода | |
|
|
Место под элемент выделять только при |
|
ErrorMessage |
Не заполнено поле "Имя пользователя" | Отображать в элементе ValidationSummary при ошибке |
|
|
Пустое |
||
Text |
* |
Надпись на визуализированном |
|
RegularExpressionValidator |
ID |
UsernameValidator |
|
ControlToValidate |
UsernameText |
Привязка к контролируемому элементу ввода | |
|
|
Место под элемент выделять только при |
|
ErrorMessage |
Неверное |
Отображать в элементе ValidationSummary при ошибке |
|
|
Допустимы буквы, цифры, пробелы и подчеркивания | ||
ValidationExpression |
[а-яА-Я\w| ]* |
[] - диапазон пропускаемых символов[]* - символы диапазона могут встречаться в контролируемом вводе сколько угодно раза-яА-Я - пропускать все буквы русского алфавита\w - пропускать все латинские буквы, цифры и знаки подчеркивания. Это | - знак ИЛИ, после которого стоит пробел, означает, что пропускать и пробелы |
|
Text |
* |
Надпись на визуализированном |
|
TextBox |
ID |
PasswordText |
Текстовое |
TextMode |
Password |
Ввод отображается звездочками | |
RequiredFieldValidator |
ID |
PwdRequiredValidator |
Проверка достоверности, чтобы привязанное поле не было пустым |
ControlToValidate |
PasswordText |
Привязка к контролируемому элементу ввода | |
|
|
Место под элемент выделять только при |
|
ErrorMessage |
Не заполнено поле "Пароль" | Отображать в элементе ValidationSummary при ошибке |
|
|
Пустое |
||
Text |
* |
Надпись на визуализированном |
|
RegularExpressionValidator |
ID |
PwdValidator |
|
ControlToValidate |
PasswordText |
Привязка к контролируемому элементу ввода | |
|
|
Место под элемент выделять только при |
|
ErrorMessage |
Неверный пароль | Отображать в элементе ValidationSummary при ошибке |
|
|
Используются недопустимые символы | ||
ValidationExpression |
[а-яА-Я\w|!"$ |
[] - диапазон пропускаемых символов[]* - символы диапазона могут встречаться в контролируемом вводе сколько угодно раза-яА-Я - пропускать все буквы русского алфавита\w - пропускать все латинские буквы, цифры и знаки подчеркивания. Это | - знак ИЛИ, после которого стоит пробел и ряд других символов, разрешенных для ввода |
|
Text |
* |
Надпись на визуализированном |
|
|
ID |
Button1 |
Кнопка Submit |
Text |
Отправить | Надпись | |
|
ID |
lblResult |
Метка сообщения для заполнения в коде |
ValidationSummary |
ID |
ValidationSummary1 |
Элемент отображения сообщений об ошибках, обнаруженных |
Интерфейсная часть страницы MyLogin.aspx в режиме проектирования будет такой

Код страницы MyLogin.aspx будет таким
<%@ Page Language="C#" EnableViewState="false" %>
<script runat="server">
protected void LoginAction_Click(object sender, EventArgs e)
{
this.Validate();// Исполнить валидаторы на сервере
if (!this.IsValid)// Оценить флаг достоверности
return;// Отправить назад как есть
// Извлечь из web.config и сравнить с введенным
if (FormsAuthentication.Authenticate(UsernameText.Text, PasswordText.Text))
{
// Создать временный cookie-набор (второй параметр false),
// записать в него метку аутентификации и перенаправить
// на исходную запрошенную страницу или MyDefault.aspx
FormsAuthentication.RedirectFromLoginPage(UsernameText.Text, false);
}
else
{
HtmlGenericControl message = new HtmlGenericControl();
message.InnerHtml = "<h2 style='color: Red'>Неверное имя или пароль!</h2>";
form1.Controls.Add(message);
}
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Untitled Page</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>
nbsp;nbsp;nbsp;
</td>
<td align="right" height="43" style="width: 167px">
Имяnbsp;пользователя:</td>
<td>
nbsp;<asp:TextBox ID="UsernameText" runat="server" />
</td>
<td>
<asp:RequiredFieldValidator ID="UsernameRequiredValidator"
runat="server" ControlToValidate="UsernameText"
Display="Dynamic"
ErrorMessage='Не заполнено поле "Имя пользователя"'
ToolTip="Пустое поле ввода">*
</asp:RequiredFieldValidator>
<asp:RegularExpressionValidator ID="UsernameValidator"
runat="server" ControlToValidate="UsernameText"
Display="Dynamic" ErrorMessage="Неверное имя пользователя"
ToolTip="Допустимы буквы, цифры, пробелы и подчеркивания"
ValidationExpression="[а-яА-Я\w| ]*">*
</asp:RegularExpressionValidator>
</td>
</tr>
<tr>
<td>
nbsp;nbsp;nbsp;
</td>
<td align="right" height="43" style="width: 167px">
nbsp;Пароль:</td>
<td>
nbsp;<asp:TextBox ID="PasswordText" runat="server"
TextMode="Password" />
</td>
<td>
<asp:RequiredFieldValidator ID="PwdRequiredValidator"
runat="server" ControlToValidate="PasswordText"
Display="Dynamic" ErrorMessage='Не заполнено поле "Пароль"'
ToolTip="Пустое поле ввода">*
</asp:RequiredFieldValidator>
<asp:RegularExpressionValidator ID="PwdValidator" runat="server"
ControlToValidate="PasswordText"
Display="Dynamic" ErrorMessage="Неверный пароль"
ToolTip="Используются недопустимые символы"
ValidationExpression='[а-яА-Я\w| !"$amp;/()=\-?\*]*'>*
</asp:RegularExpressionValidator>
</td>
</tr>
</table>
<asp:Button ID="Button1" runat="server" Text="Отправить"
OnClick="LoginAction_Click" />
</asp:Panel>
<asp:Label ID="lblResult" runat="server" />
</div>
<asp:ValidationSummary ID="ValidationSummary1" runat="server" />
</form>
</body>
</html>
При такой инфраструктуре аутентификации любой пользователь, открывший сеанс с приложением, какую бы страницу он не запросил, будет направляться на страницу регистрации до тех пор, пока не введет свои данные, хранящиеся в удостоверении
В нашем файле Web.config до настоящего момента пароли хранились в виде
В секции <credentials> имеется параметр passwordFormat. Он предназначен для указания ASP.NET, в каком формате хранятся значения паролей и какой алгоритм
Параметр passwordFormat может принимать одно из трех следующих значений:
Clear - пароль не MD5 - пароль SHA1 - для Для предварительного
string hashedPwd = FormsAuthentication.HashPasswordForStoringInConfigFile(clearTextPassword, "MD5");
Добавьте к проекту страницу HashPasswordPage.aspx и наполните ее следующим кодом(рис ) Код страницы HashPasswordPage.aspx хеширования паролей в Web.config <%@ Page Language="C#" %>
<script runat="server">
protected void btnHashedPwd_Click(object sender, EventArgs e)
{
// Загрузить содержимое корневого Web.config
Configuration myConfig = System.Web.Configuration.
WebConfigurationManager.OpenWebConfiguration("~/");
// Найти содержимое секции system.web
ConfigurationSectionGroup systemWeb = myConfig.SectionGroups["system.web"];
// Найти содержимое секции authentication
System.Web.Configuration.AuthenticationSection authSec =
(System.Web.Configuration.AuthenticationSection)
systemWeb.Sections["authentication"];
// Установить параметр passwordFormat, сообщающий, что было хеширование по MD5
authSec.Forms.Credentials.PasswordFormat = System.Web.Configuration.FormsAuthPasswordFormat.MD5;
// Извлекаем из коллекции Users старые имена и пароли
int count = authSec.Forms.Credentials.Users.Count;
string[] name = new string[count];
string[] clearTextPwd = new string[count];
int i = 0;
foreach (System.Web.Configuration.FormsAuthenticationUser user in authSec.Forms.Credentials.Users)
{
name[i] = user.Name;
clearTextPwd[i] = user.Password;
i++;
}
// Очищаем коллекцию Users
authSec.Forms.Credentials.Users.Clear();
// Добавляем старые имена и новые хешированные пароли
for (i = 0; i < count; i++)
{
// Хешируем исходный пароль
string hashedPwd = FormsAuthentication.HashPasswordForStoringInConfigFile(clearTextPwd[i], "MD5");
// Добавляем в коллекцию Users
authSec.Forms.Credentials.Users.Add(
new System.Web.Configuration.FormsAuthenticationUser(name[i], hashedPwd));
}
// Обновляем файл Web.config
myConfig.Save();
// Отсылаем сообщение
lblHashResult.Text = "Хеширование завершено.<br />"
+ "Повторно не выполнять - будет хеш на хеш!!!";
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div style="text-align: center">
<h1>Административная страница хеширования паролей в Web.config</h1>
<p>
<asp:Button ID="btnHashedPwd" runat="server" OnClick="btnHashedPwd_Click" Text="Хешировать" /></p>
<p>
<asp:Label ID="lblHashResult" runat="server"></asp:Label></p>
</div>
</form>
</body>
</html>
Выполните страницу HashPasswordPage.aspx, но только один раз, чтобы повторно не хешировать уже В результате мы получим вариант
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<compilation debug="true" />
<authentication mode="Forms">
<forms
name="MyCookieName"
loginUrl="MyLogin.aspx"
defaultUrl="MyDefault.aspx"
protection="All"
timeout="20"
path="/"
requireSSL="false"
slidingExpiration="true"
cookieless="AutoDetect"
domain=""
enableCrossAppRedirects="false"
>
<credentials passwordFormat="MD5">
<user name="admin" password="FA03EB688AD8AA1DB593D33DABD89BAD" />
<user name="петя" password="B63974E3EE7B0920FE24DFB8E82FAE81" />
<user name="вася" password="44D4B2D42E830BE0DD43E6830D957C5D" />
<user name="user1" password="7C6A180B36896A0A8C02787EEAFB0E4C" />
<user name="user2" password="6CB75F652A9B52798EB6CF2201057C73" />
<user name="user3" password="819B0643D6B89DC9B579FDFC9094F28E" />
</credentials>
</forms>
</authentication>
<authorization>
<deny users="?"/>
</authorization>
</system.web>
</configuration>
Исходные пароли, вводимые пользователями при регистрации, остались прежними. Но в
До сих пор мы использовали временные
Постоянные
true (вместо false ) в методеFormsAuthentication.RedirectFromLoginPage(строка, true);
FormsAuthentication.SetAuthCookie(строка, true);
HttpCookie authCookie = FormsAuthentication.GetAuthCookie(строка, true); this.Response.Cookies.Add(authCookie);
Установленный таким способом
FormsAuthentication.SignOut();
Можно также изменить временной статус постоянного
Добавьте к проекту страницу ModifyPersistentCookieAuth.aspx без файла отделенного кода и заполните ее так(рис ) Страница создания на браузере постоянного cookie-набора аутентификации<%@ Page Language="C#" EnableViewState="false" %>
<script runat="server">
Label message;
protected void Page_Load(object sender, EventArgs e)
{
// Дескриптор центрирования
HtmlGenericControl center = new HtmlGenericControl("center");
form1.Controls.Add(center);
// Текстовая метка с заголовком
Label label = new Label();
center.Controls.Add(label);
label.Text = "<h2>Закрепить аутентификацию за браузером</h2>";
// Кнопки
Button createPersistentCookie = new Button();
center.Controls.Add(createPersistentCookie);
createPersistentCookie.Text = "Создать бессрочный AuthCookie";
createPersistentCookie.Click += new EventHandler(createPersistentCookie_Click);
center.Controls.Add(new HtmlGenericControl("br"));
Button createTemporaryCookie = new Button();
center.Controls.Add(createTemporaryCookie);
createTemporaryCookie.Text = "Создать срочный AuthCookie";
createTemporaryCookie.Click += new EventHandler(createTemporaryCookie_Click);
center.Controls.Add(new HtmlGenericControl("br"));
Button deleteCookie = new Button();
center.Controls.Add(deleteCookie);
deleteCookie.Text = "Удалить AuthCookie";
deleteCookie.Click += new EventHandler(deleteCookie_Click);
center.Controls.Add(new HtmlGenericControl("br"));
// Текстовая метка с сообщением
message = new Label();
center.Controls.Add(message);
message.Text = String.Empty;
}
void createPersistentCookie_Click(object sender, EventArgs e)
{
// Создать бессрочный cookie
HttpCookie authCookie = FormsAuthentication.GetAuthCookie("xx", true);
// Отослать на браузер
this.Response.Cookies.Add(authCookie);
// Сообщить пользователю
message.Text = "Бессрочный AuthCookie создан!";
}
void createTemporaryCookie_Click(object sender, EventArgs e)
{
// Создать бессрочный cookie
HttpCookie authCookie = FormsAuthentication.GetAuthCookie("xx", true);
// Настроить его как временный сроком на 10 дней
authCookie.Expires = DateTime.Now.AddDays(10);
// Отослать на браузер
this.Response.Cookies.Add(authCookie);
// Сообщить пользователю
message.Text = "Срочный AuthCookie создан!";
}
void deleteCookie_Click(object sender, EventArgs e)
{
// Удалить cookie-набор регистрации
FormsAuthentication.SignOut();
// Сообщить пользователю
message.Text = "AuthCookie удален!";
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
</form>
</body>
</html>
Интерфейс страницы в режиме выполнения будет таким
При закреплении

API Membership является готовой инфраструктурой в ASP.NET, предназначенной для организации управления Membership.
Чаще всего к корневому каталогу сайта допускаются все ананимные пользователи без регистрации, а защищенные ресурсы, требующие аутентификацию, размещаются в
Для использования API Membership нужно выполнитиь следующие шаги:
SQL Server 2005 создает базы данных и работает с ними как с отдельными файлами с расширением .mdf. По умолчанию эти файла размещаются в каталоге
C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data
Мы сами можем вручную создать файл базы данных для хранения удостоверений и добавить в нее таблицы с необходимыми полями. Но это может не стыковаться с API Membership, поскольку он ожидает базу данных определенной структуры. К тому же нужно будет прописывать в
Создайте новый пустой проект командой
Откройте окно копирования проектов командой Тестовые страницы Default.aspx и MyDefault.aspx из предыдущего проекта, сконфигурированные для проверки аутентификации, будут следующими
<%@ Page Language="C#" %>
<script runat="server">
protected void SignOutAction_Click(object sender, EventArgs e)
{
// Уничтожить cookie-набор
FormsAuthentication.SignOut();
// Направить на страницу регистрации
//FormsAuthentication.RedirectToLoginPage();
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h1>
Страница с ограниченным доступом Default.aspx</h1>
<p>
<asp:Button ID="SignOutAction" runat="server"
Text="Отменить регистрацию" OnClick="SignOutAction_Click" />
<asp:HyperLink ID="HyperLink1" runat="server"
NavigateUrl="~/MyDefault.aspx">На страницу MyDefault.aspx...
</asp:HyperLink></p>
</div>
</form>
</body>
</html>
<%@ Page Language="C#" %>
<script runat="server">
protected void SignOutAction_Click(object sender, EventArgs e)
{
// Уничтожить cookie-набор
FormsAuthentication.SignOut();
// Направить на страницу регистрации
//FormsAuthentication.RedirectToLoginPage();
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h1>
Страница с ограниченным доступом MyDefault.aspx</h1>
<p>
<asp:Button ID="SignOutAction" runat="server"
OnClick="SignOutAction_Click" Text="Отменить регистрацию" />
<asp:HyperLink ID="HyperLink1" runat="server"
NavigateUrl="~/Default.aspx">На страницу Default.aspx...
</asp:HyperLink></p>
</div>
</form>
</body>
</html>
Код страницы регистрации MyLogin.aspx мы рассмотрим чуть позже, вместе с введенными изменениями.
Откройте в новом проекте скопированный файл web.config и удалите из него секцию В результате
<?xml version="1.0" encoding="utf-8"?> <configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0"> <system.web> <compilation debug="true" /> <authentication mode="Forms"> <forms name="MyCookieName" loginUrl="MyLogin.aspx" defaultUrl="MyDefault.aspx" protection="All" timeout="20" path="/" requireSSL="false" slidingExpiration="true" cookieless="AutoDetect" domain="" enableCrossAppRedirects="false"> </forms> </authentication> <!-- Временно закомментировали, чтобы не требовал регистрации <authorization> <deny users="?"/> </authorization> --> </system.web> </configuration>
Запустите утилиту WAT командой Website/ASP.NET Configuration и обратите внимание, как долго она запускаетсяЗамечание. Эта утилита может не запускаться, если абсолютный путь к созданному проекту имеет пробелы или кириллицу. В этом случае переместите проект в другое место файловой системы компьютера.
В панели Solution Explorer щелкните на кнопке RefreshМы видим, что утилита WAT так долго запускалась потому, что добавила к проекту каталог App_Data (если до этого его еще не было) и создала в нем базу данных ASPNETDB.MDF, готовую для хранения удостоверений и согласованную с API Membership

В панели Такой способ хранения удостоверений пользователей в локальной базе данных вместе с приложением очень удобен, поскольку позволяет перемещать сайт в любое место сервера или разворачивать на любом сервере без дополнительных настроек подключения SQL Server. Да и Membership будут согласованы с хранилищем удостоверений.
Утилита WAT автоматически создает хранилище удостоверений только в том случае, если обнаружит в корневом
<authentication mode="Forms">
Если на момент запуска утилиты WAT файл конфигурации в
Для того, чтобы проверить работоспособность созданной локальной базы данных, выполните следующее:
Запустите утилиту WAT командой Website/ASP.NET Configuration
На вкладке Home щелкните на
На вкладке Provider щелкните на
В сгенерированном страницей ManageConsolidatedProviders.aspx отклике щелкните на 
В результате страница пришлет ответ, что созданная нами локальная база данных функционирует нормально.
Важно отметить, что хоть утилита WAT автоматически создала базу данных для поддержки
На данном этапе мы рассмотрим интерактивный способ добавления пользователей с применением утилиты WAT. В дальнейшем можно будет создать свои административные страницы для программного добавления пользователей в это хранилище, используя классы Membership. При этом нужно помнить, что хранилище удостоверений будет размещаться на удаленном сервере и поддерживать его мы будем как удаленные пользователи либо через WAT, либо через собственные административные страницы, также хранящиеся на сервере.
Для создания новых аутентифицированных пользователей через утилиту WAT выполните следующее:
В панели Solution Explorer щелкните на пиктограмме ASP.NET Configuration, чтобы запустить утилиту WAT
Перейдите на вкладку Security и щелкните на Появится следующий отклик утилиты WAT

Сообщение на странице предлагает ввести
В утилите за
Заполните поля страницы для добавления в хранилище одного пользователя со следующими характеристиками| User Name: | |
| Password: | RootRoot |
| Confirm Password: | RootRoot |
| E-mail: | |
| Security Question: | У Вас продается славянский шкаф ? |
| Security Answer: | Шкаф уже продан, осталась только тумбочка ! |
После этого действия новый пользователь будет создан в базе данных.
В появившемся отклике щелкните на кнопке Continue, чтобы вернутся к интерфейсу добавления следующего пользователя, либо закройте WATНа данном этапе для проверки аутентификации с использованием API Membership и хранилища
Модифицируйте страницу регистрации MyLogin.aspx, чтобы код стал таким(рис ) Код страницы регистрации MyLogin.aspx<%@ Page Language="C#" EnableViewState="false" %>
<script runat="server">
protected void LoginAction_Click(object sender, EventArgs e)
{
this.Validate();// Исполнить валидаторы на сервере
if (!this.IsValid)// Оценить флаг достоверности
return;// Отправить назад как есть
// Извлечь из базы данных и сравнить с введенным
if (Membership.ValidateUser(UsernameText.Text, PasswordText.Text))
{
// Создать временный cookie-набор (второй параметр false),
// записать в него метку аутентификации и перенаправить
// на исходную запрошенную страницу или MyDefault.aspx
// с созданием coockie-набора только на период сеанса
FormsAuthentication.RedirectFromLoginPage(UsernameText.Text, false);
}
else
{
HtmlGenericControl message = new HtmlGenericControl();
message.InnerHtml = "<h2 style='color: Red'>Неверное имя или пароль!</h2>";
form1.Controls.Add(message);
}
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Untitled Page</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>
nbsp;nbsp;nbsp;
</td>
<td align="right" height="43" style="width: 167px">
Имяnbsp;пользователя:</td>
<td>
nbsp;<asp:TextBox ID="UsernameText" runat="server" />
</td>
<td>
<asp:RequiredFieldValidator ID="UsernameRequiredValidator"
runat="server" ControlToValidate="UsernameText"
Display="Dynamic"
ErrorMessage='Не заполнено поле "Имя пользователя"'
ToolTip="Пустое поле ввода">*
</asp:RequiredFieldValidator>
<asp:RegularExpressionValidator ID="UsernameValidator"
runat="server" ControlToValidate="UsernameText"
Display="Dynamic" ErrorMessage="Неверное имя пользователя"
ToolTip="Допустимы буквы, цифры, пробелы и подчеркивания"
ValidationExpression="[а-яА-Я\w| ]*">*
</asp:RegularExpressionValidator>
</td>
</tr>
<tr>
<td>
nbsp;nbsp;nbsp;
</td>
<td align="right" height="43" style="width: 167px">
nbsp;Пароль:</td>
<td>
nbsp;<asp:TextBox ID="PasswordText" runat="server"
TextMode="Password" />
</td>
<td>
<asp:RequiredFieldValidator ID="PwdRequiredValidator"
runat="server" ControlToValidate="PasswordText"
Display="Dynamic" ErrorMessage='Не заполнено поле "Пароль"'
ToolTip="Пустое поле ввода">*
</asp:RequiredFieldValidator>
<asp:RegularExpressionValidator ID="PwdValidator" runat="server"
ControlToValidate="PasswordText"
Display="Dynamic" ErrorMessage="Неверный пароль"
ToolTip="Используются недопустимые символы"
ValidationExpression='[а-яА-Я\w| !"$amp;/()=\-?\*]*'>*
</asp:RegularExpressionValidator>
</td>
</tr>
</table>
<asp:Button ID="Button1" runat="server" Text="Отправить"
OnClick="LoginAction_Click" />
</asp:Panel>
<asp:Label ID="lblResult" runat="server" />
</div>
<asp:ValidationSummary ID="ValidationSummary1" runat="server" />
</form>
</body>
</html>
Запустите приложение с любой страницы и введите | User Name: | |
| Password: | RootRoot |
С помощью утилиты WAT добавьте в хранилище еще несколько пользователей и убедитесь, что аутентификация на основе Membership и хранилища удостоверений в При добавлении новых пользователей следует иметь ввиду, что реляционной таблицы aspnet_Users и является основой для формирования поля как
В панели Server Explorer установите ASPNETDB
Для таблиц aspnet_Users и aspnet_Membership выполните команду Show Table Data контекстного меню
После таких действий откроются таблицы aspnet_Users и aspnet_Membership, в которых можно найти информацию о созданных пользователях. Для того, чтобы увидеть структуру таблиц, следует выполнить для них команду Open Table Definition контекстного меню.
Интерфейс API Membership включает в себя следующие классы пространства имен System.Web.Security:
Membership - статический класс, имеющий ряд полезных методов MembershipCreateUserException - исключение, генерируемое ошибкой MembershipPasswordException - исключение при невозможности извлечения пароляMembershipUser - объект этого класса содержит всю информацию о пользователе и возвращается методом Membership.GetUser()MembershipUserCollection - коллекция пользователей, извлекаемая методом Membership.GetAllUsers()MembershipProvider - MembershipProviderCollection - коллекция доступных для приложения поставщиков на данной машинеSqlMembershipProvider - поставщик для работы с базами данных SQL ServerActiveDirectoryMembershipProvider - поставщик для работы со службой Active DirectoryActiveDirectoryMembershipUser - класс поддержки пользователя, расширенный для работы со службой Active DirectoryИспользуя API Membership, можно программно решать, например, следующие задачи:
Для создания и удаления пользователей следует применить перегруженные CreateUser() и класса Membership. Нужно создать административные страницы, содержащие требуемые поля для ввода информации. Поля можно контролировать
Метод CreateUser() имеет несколько перегрузок, из которых простейшая принимает только имя и пароль. В то же время более полные CreateUser() содержит экземпляр перечисления MembershipCreateStatus в качестве CreateUser(), включающую контрольный вопрос и ответ, чтобы избежать выброса исключения MembershipCreateUserException.
Удаление пользователя выполняется методом Membership., которому передается в качестве параметра
В качестве примера создадим собственную страницу добавления, имеющую аналогичную функциональность с WAT, и отдельно страницу удаления пользователя в
Скопируйте страницу MyLogin.aspx и присвойте копии имя AddUserMembership.aspxCustomValidator. С помощью этого элемента реализуем проверку достоверности на клиенте и на сервере.
Неалфавитно-цифровые символы представим в виде
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | ||||||||||
| 1 | ||||||||||
| 2 | ||||||||||
| 3 | ! | " | # | $ | % | ' | ||||
| 4 | ( | ) | * | + | , | . | / | |||
| 5 | : | ; | ||||||||
| 6 | < | = | > | ? | @ | |||||
| 7 | ||||||||||
| 8 | ||||||||||
| 9 | [ | \ | ] | ^ | _ | |||||
| 10 | ||||||||||
| 11 | ||||||||||
| 12 | { | | | } | ~ |
Строка
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);
Переделайте интерфейсную и кодовую части страницы, чтобы она стала такой(рис ) Административная страница AddUserMembership.aspx добавления пользователей в БД<%@ 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 и убедитесь в работоспособности рассматриваемого механизма добавления пользователей в Теперь рассмотрим вопрос удаления пользователей. Он намного проще, чем создание. Нужно только применить метод 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, которая будет примерно такой(рис ) Административная страница 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>
Испытайте страницу удаления пользователейДля получения списка пользователей применяют метод Membership.GetAllUsers(), а для извлечения конкретного пользователя - метод Membership.GetUser().
Рассмотрим пример, в котором будем использовать элемент для представления пользователей в виде таблицы.
Добавьте к проекту страницу GetUsersMembership.aspx и назначьте ее стартовой
Заполните страницу следующим кодом(рис ) Код страницы GetUsersMembership.aspx для извлечения пользователей<%@ Page Language="C#" EnableViewState="false" %>
<script runat="server">
// Вынесли поле для видимости в обработчиках
MembershipUserCollection myUsers = new MembershipUserCollection();
protected void Page_Load(object sender, EventArgs e)
{
// Скрываем таблицу деталей
tableDetails.Visible = false;
lblUser.Visible = false;
if (checkUser.Checked)
{
// Извлекаем одного пользователя
if (txtUser.Text.Length == 0)
{
lblUsersList.Text = "Введите имя пользователя";
return;
}
try // Попытка
{
string user = Server.HtmlEncode(txtUser.Text);
myUsers = new MembershipUserCollection();
myUsers.Add(Membership.GetUser(user));
}
catch // Откат
{
lblUsersList.Text = "Пользователь не найден";
return;
}
}
else
{
// Извлекаем всех пользователей
myUsers = Membership.GetAllUsers();
}
// Подключаем к сетке извлеченную информации и наполняем элемент
UsersGridView.DataSource = myUsers;
UsersGridView.DataBind();
}
// Обработчик щелчков на ссылки столбца отображения деталей
protected void UsersGridView_SelectedIndexChanged(object sender, EventArgs e)
{
if (UsersGridView.SelectedIndex >= 0)
{
// Заполняем интерфейсные элементы отображаемой информацией,
// адресуясь к конкретному пользователю по ключевому имени,
// заданному параметром DataKeyNames="UserName" элемента GridView
MembershipUser currentUser =
myUsers[(string)UsersGridView.SelectedValue];
lblUserName.Text = currentUser.UserName;
lblEmail.Text = currentUser.Email;
lblPasswordQuestion.Text = currentUser.PasswordQuestion;
lblLastLoginDate.Text = currentUser.LastLoginDate.ToLongDateString();
txtComment.Text = currentUser.Comment;
checkIsApproved.Checked = currentUser.IsApproved;
checkIsLockedOut.Checked = currentUser.IsLockedOut;
// Включаем видимость таблицы деталей
tableDetails.Visible = true;
lblUser.Visible = true;
}
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h2>
<asp:Label ID="lblUsersList" runat="server" Font-Bold="true"
Text="Список зарегистрированных пользователей"></asp:Label>
</h2>
<p>Конкретный пользователь:
<asp:CheckBox ID="checkUser" runat="server" />
<asp:TextBox ID="txtUser" runat="server"></asp:TextBox>
<asp:Button ID="btnUser" runat="server" Text="Получить" /></p>
<asp:GridView ID="UsersGridView" runat="server"
DataKeyNames="UserName"
AutoGenerateColumns="False"
OnSelectedIndexChanged="UsersGridView_SelectedIndexChanged">
<Columns>
<asp:BoundField DataField="UserName" HeaderText="Имя" />
<asp:BoundField DataField="Email" HeaderText="email" />
<asp:BoundField DataField="CreationDate" HeaderText="Создан" />
<asp:CommandField ShowSelectButton="True" HeaderText="Детали"
SelectText="Показать" />
</Columns>
</asp:GridView>
<h2>
<asp:Label ID="lblUser" runat="server"
Text="Подробности для выделенного пользователя"
Visible="False" Font-Bold="true"></asp:Label>
</h2>
<table id="tableDetails" border="1" bordercolor="#0000FF"
width="100%" runat="server">
<tr>
<td width="50%">
Пользователь:</td>
<td>
<asp:Label ID="lblUserName" runat="server"></asp:Label></td>
</tr>
<tr>
<td width="50%">
email:</td>
<td>
<asp:Label ID="lblEmail" runat="server"></asp:Label></td>
</tr>
<tr>
<td width="50%">
Контрольный вопрос:</td>
<td>
<asp:Label ID="lblPasswordQuestion" runat="server"></asp:Label></td>
</tr>
<tr>
<td width="50%">
Дата последней регистрации:</td>
<td>
<asp:Label ID="lblLastLoginDate" runat="server"></asp:Label></td>
</tr>
<tr>
<td valign="top" width="50%">
Комментарии:</td>
<td>
<asp:TextBox ID="txtComment" runat="server" TextMode="MultiLine"
Width="100%"></asp:TextBox></td>
</tr>
<tr>
<td width="50%">
Проверенный:</td>
<td>
<asp:CheckBox ID="checkIsApproved" runat="server" /></td>
</tr>
<tr>
<td width="50%">
Заблокирован:</td>
<td>
<asp:CheckBox ID="checkIsLockedOut" runat="server" /></td>
</tr>
</table>
</div>
</form>
</body>
</html>
Интерфейсная часть страницы представлена элементом и текстовыми метками, спозиционированными в серверной таблице. Значения параметров элемента представляют собой имена полей таблиц aspnet_Users и aspnet_Membership базы данных

Установка в элементе управления свойства DataKeyNames=" позволяет извлекать значения поля через , что очень удобно при получении подробностей о конкретном пользователе из коллекции пользователей.
Метод Membership.GetUser() возвращает объект запрошенного пользователя, свойства которого мы отображаем в текстовых элементах, скомпонованных в таблице. Привязка к свойствам объекта пользователя выполняется в обработчике события SelectedIndexChanged элемента управления .
Результат работы страницы GetUsersMembership.aspx будет примерно таким

Извлечение пароля напрямую через свойство не предусмотрено в классе MembershipUser. Для этого существует метод MembershipUser.GetPassword(), который работает только тогда, когда поставщик SqlMembershipProvider сконфигурирован с параметром enablePasswordRetrieval="true" в
Наша задача - перенастроить поставщик по умолчанию, создав для этого поставщик того же типа, но с другими настройками. Новый поставщик в той же базе данных будет иметь доступ только к своим данным. Включение параметра enablePasswordRetrieval="true" несовместимо с настройкой passwordFormat=", а должно иметь значения " или "
Измените (рис ) Конфигурационный файл с новыми настройками поставщика SqlMembershipProvider<?xml version="1.0" encoding="utf-8"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<system.web>
<compilation debug="true" />
<authentication mode="Forms">
<forms
name="MyCookieName"
loginUrl="MyLogin.aspx"
defaultUrl="MyDefault.aspx"
protection="All"
timeout="20"
path="/"
requireSSL="false"
slidingExpiration="true"
cookieless="AutoDetect"
domain=""
enableCrossAppRedirects="false">
</forms>
</authentication>
<!-- Временно закомментировали, чтобы не требовал регистрации
<authorization>
<deny users="?"/>
</authorization>
-->
<membership defaultProvider="MyMembershipProvider">
<providers>
<add name="MyMembershipProvider" connectionStringName="MyMembershipConnString"
enablePasswordReset="true" requiresQuestionAndAnswer="true"
requiresUniqueEmail="false" enablePasswordRetrieval="true" passwordFormat="Clear"
type="System.Web.Security.SqlMembershipProvider"
/>
</providers>
</membership>
</system.web>
<connectionStrings>
<add name="MyMembershipConnString"
connectionString="Data Source=localhost; Initial Catalog=ASPNETDB; user id=sa; password=;"
/>
</connectionStrings>
</configuration>
Добавьте новых пользователей с помощью нашей административной страницы AddUserMembership.aspx
Получите из страницы GetUsersMembership.aspx копию с именем GetUsersMyMembershipProvider.aspx, назначьте ее стартовой и добавьте в интерфейсную часть текстовую метку lblPassword для отображения пароля
Добавьте в обработчик события SelectedIndexChanged строку заполнения меткиlblPassword.Text = currentUser.GetPassword();
Если у нас есть экземпляр класса MembershipUser, то мы можем обновить его свойства, имеющие аксессор set, а именно:
Comment Email IsApprovedLastActivityDateLastLoginDateДля этого используется Membership.UpdateUser().
Получите из страницы GetUsersMembership.aspx копию с именем UpdateUserMembership.aspx
Скорректируйте страницу UpdateUserMembership.aspx, чтобы обновляемые параметры таблицы деталей размещались в текстовых полях
Закрепите за полем txtEmail элементы проверки достоверности RequiredFieldValidator и RegularExpressionValidatorОкончательный код страницы UpdateUserMembership.aspx будет таким
<%@ Page Language="C#" EnableViewState="false" %>
<%@ Import Namespace="System.Web.Security" %>
<script runat="server">
// Вынесли поле для видимости в обработчиках
MembershipUserCollection myUsers = new MembershipUserCollection();
protected void Page_Load(object sender, EventArgs e)
{
// Скрываем таблицу деталей
tableDetails.Visible = false;
lblUser.Visible = false;
// Извлекаем всех пользователей
myUsers = Membership.GetAllUsers();
// Подключаем к сетке извлеченную информации и наполняем элемент
UsersGridView.DataSource = myUsers;
UsersGridView.DataBind();
}
// Обработчик щелчков на ссылки столбца отображения деталей
protected void UsersGridView_SelectedIndexChanged(object sender, EventArgs e)
{
if (UsersGridView.SelectedIndex >= 0)
{
// Заполняем интерфейсные элементы отображаемой информацией,
// адресуясь к конкретному пользователю по ключевому имени,
// заданному параметром DataKeyNames="UserName" элемента GridView
MembershipUser currentUser =
myUsers[(string)UsersGridView.SelectedValue];
lblUserName.Text = currentUser.UserName;
txtEmail.Text = currentUser.Email;
lblPasswordQuestion.Text = currentUser.PasswordQuestion;
lblLastLoginDate.Text = currentUser.LastLoginDate.ToLongDateString();
txtComment.Text = currentUser.Comment;
checkIsApproved.Checked = currentUser.IsApproved;
checkIsLockedOut.Checked = currentUser.IsLockedOut;
// Включаем видимость таблицы деталей
tableDetails.Visible = true;
lblUser.Visible = true;
}
}
protected void btnUpdate_Click(object sender, EventArgs e)
{
if (UsersGridView.SelectedIndex >= 0)
{
// Адресуемся к выделенному пользователю
MembershipUser currentUser =
myUsers[(string)UsersGridView.SelectedValue];
// Избавляемся от возможных управляющих символов
// в пользовательском вводе
currentUser.Email = Server.HtmlEncode(txtEmail.Text);
currentUser.Comment = Server.HtmlEncode(txtComment.Text);
currentUser.IsApproved = checkIsApproved.Checked;
// Сбрасываем в базу данных
Membership.UpdateUser(currentUser);
// Обновить содержимое GridView из БД, поскольку
// этот обработчик выполнится после Page_Load
myUsers = Membership.GetAllUsers();// Извлекаем пользователей
UsersGridView.DataBind();
}
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h2>
<asp:Label ID="lblUsersList" runat="server" Font-Bold="true"
Text="Список зарегистрированных пользователей"></asp:Label>
</h2>
<asp:GridView ID="UsersGridView" runat="server"
DataKeyNames="UserName"
AutoGenerateColumns="False"
OnSelectedIndexChanged="UsersGridView_SelectedIndexChanged">
<Columns>
<asp:BoundField DataField="UserName" HeaderText="Имя" />
<asp:BoundField DataField="Email" HeaderText="email" />
<asp:BoundField DataField="CreationDate" HeaderText="Создан" />
<asp:CommandField ShowSelectButton="True" HeaderText="Детали"
SelectText="Показать" />
</Columns>
</asp:GridView>
<h2>
<asp:Label ID="lblUser" runat="server"
Text="Подробности для выделенного пользователя"
Visible="False" Font-Bold="true"></asp:Label>
</h2>
<table id="tableDetails" border="1" bordercolor="#0000FF"
width="100%" runat="server">
<tr>
<td width="50%">
Пользователь:</td>
<td>
<asp:Label ID="lblUserName" runat="server"></asp:Label></td>
</tr>
<tr>
<td width="50%">
<font color="#0000FF">email:</font></td>
<td>
<asp:TextBox ID="txtEmail" runat="server" Width="100%">
</asp:TextBox>
<asp:RequiredFieldValidator
ID="RequiredFieldValidator1" runat="server"
ControlToValidate="txtEmail" Display="Dynamic">*
</asp:RequiredFieldValidator>
<asp:RegularExpressionValidator ID="RegularExpressionValidator1"
runat="server" ControlToValidate="txtEmail"
Display="Dynamic"
ValidationExpression="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*">*
</asp:RegularExpressionValidator></td>
</tr>
<tr>
<td width="50%">
Контрольный вопрос:</td>
<td>
<asp:Label ID="lblPasswordQuestion" runat="server"></asp:Label></td>
</tr>
<tr>
<td width="50%">
Дата последней регистрации:</td>
<td>
<asp:Label ID="lblLastLoginDate" runat="server"></asp:Label></td>
</tr>
<tr>
<td valign="top" width="50%">
<font color="#0000FF">Комментарии:</font></td>
<td>
<asp:TextBox ID="txtComment" runat="server" TextMode="MultiLine"
Width="100%"></asp:TextBox></td>
</tr>
<tr>
<td width="50%">
<font color="#0000FF">Проверенный:</font></td>
<td>
<asp:CheckBox ID="checkIsApproved" runat="server" /></td>
</tr>
<tr>
<td width="50%">
Заблокирован:</td>
<td>
<asp:CheckBox ID="checkIsLockedOut" runat="server" /></td>
</tr>
<tr>
<td colspan="2" align="center">
<asp:Button ID="btnUpdate" runat="server" Text="Обновить"
OnClick="btnUpdate_Click" /></td>
</tr>
</table>
</div>
</form>
</body>
</html>
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.