Средства безопасности ASP.NET
Часть 1 – Аутентификация
Автор: Сергей
Бакланов
Источник: RSDN
Magazine #2 2004
Опубликовано: 10.06.2004
Версия текста: 1.0
На сегодняшний день информация в мире имеет очень большое значение, часто
утечка даже самого незначительного её количества может оказаться огромной
потерей. Для избежания подобных инцидентов нужно уметь её защищать. С этой целью
в мире ИТ было создано множество способов, начиная от обычного шифрования
информации методом Цезаря (перемещение каждого символа на 3 вперёд) и
заканчивая внедрением карт доступа и средств биосканирования. Каждое средство
предназначено для своих целей, поэтому нужно чётко представлять, что вы хотите
сделать, чего пытаетесь добиться. Разумеется, самыми надёжным методом является
внедрение отдельных устройств идентификации личности. Это могут быть сканеры
сетчатки глаза, сканеры отпечатков пальцев, отдельные кардридеры и другие
изощрённые способы. Но вышеперечисленные средства стоят очень дорого, и их
поддержка тоже оказывается далеко не самым дешёвым и доступным удовольствием;
подобные технологии, в большинстве случаев, могут себе позволить крупные
компании, у которых есть на это как финансовые возможности, так и явная
необходимость, когда штат включает сотни и тысячи сотрудников. Эти средства
позволяют не только обезопасить систему от несанкционированного доступа, но и
предоставляют полный контроль за перемещением персонала как в реальном
физическом мире, так и в виртуальном, т. е. по сетям компании.
Наряду с такими дорогими и высокотехнологичными системами безопасности
существуют технологии более низкого ранга, но всё же способные обеспечить
безопасность на своём уровне – на уровне программном. Давайте познакомимся с
ними поближе, а точнее со средствами, которые наиболее распространены в среде
ASP.NET и .NET Framework. Мы уделим основное внимание таким аспектам
безопасности ASP.NET как аутентификация, авторизация и криптография.
Для начала, следует провести чёткую грань между понятиями аутентификации и
авторизации. Аутентификация – это процесс ввода имени
пользователя или его e-mail и какой-либо секретной информации, которая могла бы
быть доступна только ему – в большинстве случаев это пароль. Наглядным примером
аутентификации может послужить вход в Windows. Авторизация –
это проверка прав доступа к определённому ресурсу или проверка привилегий на
выполнение определённых действий, например, авторизация в Windows проходит
каждый раз, когда вы пытаетесь изменить настройки системы, добавить или удалить
пользователей, и если у вас не окажется соответствующих прав для выполнения
подобных действий, то ОС выдаст вам соответствующую ошибку.
Давайте теперь перейдём к описанию процесса аутентификации непосредственно в
рамках среды ASP.NET, где для вашего выбора предоставлены 3 вида
аутентификации:
- Аутентификация Windows
- Формой
- Паспортом
Аутентификация Windows:
Как и следует из названия, этот метод основывается на использовании учётных
записей Windows. Такой метод уместен, если вы создаёте приложение для локальной
сети, и все действующие учётные записи и группы хранятся на заранее определённом
домене. При этом нужно быть очень осторожными, назначая права доступа
пользователям, поскольку вы одновременно задаёте и права для работы в Windows.
Для того, чтобы настроить ASP.NET на работу в режиме Windows аутентификации
необходимо изменить файл настройки Web-проекта Web.config или при необходимости
конфигурационный файл всего сервера, расположенный по адресу
WINDOWS_FOLDER\Microsoft.NET\
Framework\.NET version\CONFIG\Machine.config. В нашем примере мы будем
работать исключительно с файлом проекта – Web.config, в котором вам нужно найти
раздел authentication и присвоить его атрибуту mode значение
Windows:
Теперь можно приступить непосредственно к программированию и реализации
аутентификации на основе Windows. В помощь вам класс WindowsIdentity, который
служит специально для работы с аутентификацией Windows. Вообще, для
аутентификации, базирующейся на Windows, существуют два основных класса,
предоставляемых .NET Framework:
- GenericIdentity – только реализует интерфейс IIdentity и не относится к
какому-то определённому типу аутентификации
- WindowsIdentity – также является реализацией интерфейса IIdentity, но плюс
ещё и включает методы, характерные только для аутентификации на основе Windows
Имя пользователя и группы хранятся в объекте WindowsIdentity в следующем
формате: DOMAIN\UserName и DOMAIN\Group соответственно. Исключение составляют
лишь встроенные группы, например группа Administrators, для обращения к ней
можно использовать строку подключения через WindowsIdentity:
BUILTIN\Administrators. Или же можно задать встроенную группу из перечисления
System.Security.Principal.WindowsBuiltInRole.
Из рис. 1 видно, что объект WindowsIdentity позволяет получить имя
пользователя; определить тип аутентификации; установить, была ли аутентификация
проведена анонимно; также можно узнать, прошёл пользователь аутентификацию или
нет, гость он или системный пользователь.
Рис. 1 – Объект WindowsIdentity
Поскольку в приложениях ASP.NET для обращения к объекту WindowsIdentity нужно
будет выстроить следующую цепочку:
HttpContext.Current.User.Identity, то вы сможете также определить, к какой
роли принадлежит текущий пользователь. Это можно достичь благодаря тому, что
свойство User в этой цепочке реализует интерфейс Iprincipal, который позволяет
определить принадлежность пользователя к определённой роли путём вызова функции
IsInRole, имеющей следующий синтаксис:
Public Overridable Function
IsInRole(ByVal role As String) As Boolean
Member of: System.Security.Principal.Iprincipal
|
Но давайте ненадолго отойдём от голой теории и попробуем реализовать
практический пример. Для этого создайте новый проект ASP.NET Web Application и
введите следующий код:
Default.aspx:
<%@ Page Language="vb" AutoEventWireup="false"
Codebehind="default.aspx.vb" Inherits="AuthSample.WebForm1"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Authentication Sample</title>
<meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1">
<meta name="CODE_LANGUAGE" content="Visual Basic .NET 7.1">
<meta name=vs_defaultClientScript content="JavaScript">
<meta name=vs_targetSchema content="http://schemas.microsoft.com/intellisense/ie5">
</head>
<body MS_POSITIONING="GridLayout">
<form id="Form1" method="post" runat="server">
</form>
</body>
</html>
|
Default.aspx.vb:
Public Class WebForm1
Inherits System.Web.UI.Page
#Region “ Web Form Designer Generated Code “
‘This call is required by the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
End Sub
‘NOTE: The following placeholder declaration is required by the Web Form Designer.
‘Do not delete or move it.
Private designerPlaceholderDeclaration As System.Object
Private Sub Page_Init (ByVal sender
As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Init
‘CODEGEN: This method call is required by the Web Form Designer
‘Do not modify it using the code editor.
InitializeComponent()
End Sub
#End Region
Private Sub Page_Load (ByVal sender
As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
Dim s As String
s = “<p><b>Name:</b> “ & HttpContext.Current.User.Identity.Name & “</p>” & _
“<p><b>Authentication type:</b> “ & _
HttpContext.Current.User.Identity.AuthenticationType.ToString & “</p>” & _
“<p><b>Is authenticated:</b> “ & _
HttpContext.Current.User.Identity.IsAuthenticated.ToString & “</p>” & _
“<p><b>Is admin:</b> “ & _
HttpContext.Current.User.IsInRole(“Administrator”).ToString & “</p>”
Response.Write(s)
End Sub
End Class
|
Если был выбран режим аутентификации Windows и настройки IIS не вызвали
никаких конфликтных ситуаций, то вы получите соответствующую информацию о своём
текущем пользователе. Если же поле имени пользователя и типа аутентификации
оказались пустыми, то вам нужно просто настроить IIS, для этого выполните
следующие действия:
- Откройте IIS и найдите виртуальный каталог с этим приложением
- Откройте окно свойств для этого каталога и перейдите во вкладку
Безопасность каталога. В рамке Анонимный доступ и проверка
подлинности нажмите кнопку Изменить…
- В появившемся окне (рис. 2) снимите флажок Анонимный доступ
Рис. 2 – Настройка IIS
На этом мы закончим рассмотрение аутентификации на основе Windows и перейдём
к аутентификации формой.
Аутентификация формой:
Аутентификация формой или, как её ещё называют аутентификация на основе
Cookie-файлов, имеет ряд преимуществ над аутентификацией Windows.
- Во-первых, вы имеете возможность самому определить на свой вкус и цвет или
на вкус и цвет пользователя внешний вид формы регистрации вместо однотипного
окна регистрации Windows.
- Во-вторых, вы полностью контролируете вводимую информацию
- Сведения о пользователях теперь может храниться не только в SAM или Active
Directory, но и в любом другом хранилище, в частности: база данных, каталог
LDAP, XML-файлы или же обычный текстовый файл.
- Отпадает необходимость связывать политику безопасности сервера с политикой
Web-приложения, поскольку, как уже было ранее сказано, все сведения о
пользователях можно вынести в отдельное хранилище данных без каких-либо
пересечений с учётными записями ОС.
Но, не смотря на такое изобилие возможностей аутентификации на основе формы,
существует и одно весомое ограничение – пользователь должен разрешить применение
cookie-файлов. Если его не будет, то аутентификация формой с применением средств
ASP.NET работать не будет. Обратите внимание на слова “…с применением средств
ASP.NET…”. Это означает, что не будет работать механизм, освобождающий
разработчика от рутинных операций бесконечных проверок, иными словами, все
запросы, поступившие от пользователя, ещё не прошедшего аутентификацию,
переадресовываются на страницу регистрации, где он вводит необходимую информацию
(чаще всего имя пользователя и пароль). Полученные сведения передаются среде
ASP.NET, где происходит их верификация. В случае успеха пользователю передаётся
cookie-файл, в котором содержится удостоверение об авторизации
(Authorization ticket), имя пользователя и ключ для последующего получения
идентификатора. В результате все последующие обращения броузера будут содержать
в заголовках сведения об авторизации, направляемые на проверку в среду ASP.NET.
Поэтому, если пользователь не поддерживает cookie, то все проверки о том, прошёл
ли он аутентификацию, нужно будет осуществлять вручную, например, в предыдущих
версиях ASP для этого применяли объект Session, примерно, в следующей форме:
If Not Session(“Registered”) = “1” Then
Response.Redirect(“login.asp”)
End If
|
Для использования аутентификации формой сперва нужно настроить конфигурацию
Web-проекта. Для этого измените содержимое тэга <authentication> файла
Web.config следующим образом:
<authentication mode=”Forms”>
<forms name=”ASP_XML_Form” loginUrl=”login.aspx”
protection=”All” timeout=”30” path=”/” requireSSL=”false”
slidingExpiration=”true” />
</authentication>
|
Давайте подробнее рассмотрим вышеприведённый код. Атрибут mode тэга
<authentication> определяет способ аутентификации. В предыдущих примерах
мы использовали значение Windows, которое настраивало аутентификацию в
режим аутентификации средствами Windows, теперь для работы на основе форм мы
применяем режим Forms. Кроме этих двух констант существуют ещё 2:
Passport и None – первая из них определяет аутентификацию на
основе паспорта, о которой речь пойдёт позже, вторая отключает её вообще.
Следующий тэг (<forms>) присущ только аутентификации на основе формы и
включает в себя следующие сведения:
- name – имя cookie-файла, в который будут внесены данные
об успешном прохождении аутентификации
- loginUrl – определяет адрес страницы, на которую будет
переадресован пользователь для прохождения регистрации
- protection – принимает значения
All|None|Encryption|Validation и определяет способ защиты данных в
cookie-файлах. Из допустимых значений видно, что можно ничего не делать с
полученными данными и принимать их такими, какие они есть; можно сверять их;
можно шифровать; а также есть возможность объединить верификацию с
криптографией – такое значение используется по умолчанию.
- timeout – определяет промежуток времени в секундах, в
течение которого cookie будет доступен
- path – этот атрибут задаёт полный путь к cookie-файлу. По
умолчанию он содержит косую черту (/), которая раскрывает все пути. Менять
этот параметр не рекомендуется, потому что некоторые броузеры чувствительны к
регистру в пути, потому в результате изменений этого параметра вы можете
отрезать некоторых пользователей от возможности проходить аутентификацию.
- requireSSL – этот атрибут принимает значения True или
False (по умолчанию) и устанавливает необходимость применения протокола
защищённых сокетов (SSL – Secured Sockets Layer)
- slidingExpiration – указывает, нужно ли пересоздавать
cookie и удостоверение об авторизации, если истекает таймаут. Принимает
значения true (по умолчанию) или false.
Выше были описаны все возможные атрибуты раздела forms,но для корректной
работы приложения достаточно использовать лишь 3 из них, как это показано в
следующем листинге:
<forms name=”ASP_XML_Form” loginUrl=”login.aspx” protection=”All” />
|
Аутентификация формой с использованием отдельных XML-файлов:
Давайте теперь создадим простую страницу регистрации пользователей, которая
сверяет введённые имя и пароль с данными из XML-файла. Для этого сперва создайте
XML-файл с именем users.xml следующего образца:
users.xml:
<?xml version=”1.0” encoding=”utf-8” ?>
<users>
<user>
<name>John</name>
<password>one</password>
</user>
<user>
<name>Mike</name>
<password>two</password>
</user>
<user>
<name>Bill</name>
<password>three</password>
</user>
</users>
|
База пользователей готова – теперь можно приступить к созданию пробного
проекта регистрации пользователей. Весь необходимый код приведён ниже:
Default.aspx:
<%@ Page Language=”vb” AutoEventWireup=”false”
Codebehind=”default.aspx.vb” Inherits=”FormAuth._default”%>
<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.0 Transitional//EN”>
<html>
<head>
<title>default</title>
<meta name=”GENERATOR” content=”Microsoft Visual Studio .NET 7.1”>
<meta name=”CODE_LANGUAGE” content=”Visual Basic .NET 7.1”>
<meta name=vs_defaultClientScript content=”JavaScript”>
<meta name=vs_targetSchema content=”http://schemas.microsoft.com/intellisense/ie5”>
</head>
<body MS_POSITIONING=”GridLayout”>
<form id=”Form1” method=”post” runat=”server”>
</form>
</body>
</html>
|
Default.aspx.vb:
Imports System.Web.Security
Public Class _default
Inherits System.Web.UI.Page
#Region “ Web Form Designer Generated Code “
‘This call is required by the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
End Sub
‘NOTE: The following placeholder declaration is required by the Web Form Designer.
‘Do not delete or move it.
Private designerPlaceholderDeclaration As System.Object
Private Sub Page_Init(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Init
‘CODEGEN: This method call is required by the Web Form Designer
‘Do not modify it using the code editor.
InitializeComponent()
End Sub
#End Region
Private Sub Page_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
‘Put user code to initialize the page here
If context.Current.User.Identity.Name = “” Then
Response.Redirect(“login.aspx”)
Else
Response.Write(“<h2><I>Hello “ & _
context.Current.User.Identity.Name & “</I></h2>”)
End If
End Sub
End Class
|
login.aspx:
<%@ Page Language=”vb” AutoEventWireup=”false”
Codebehind=”login.aspx.vb” Inherits=”FormAuth.WebForm1”%>
<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.0 Transitional//EN”>
<HTML>
<HEAD>
<title>Registration</title>
<meta name=”GENERATOR” content=”Microsoft Visual Studio .NET 7.1”>
<meta name=”CODE_LANGUAGE” content=”Visual Basic .NET 7.1”>
<meta name=”vs_defaultClientScript” content=”JavaScript”>
<meta name=”vs_targetSchema” content=”http://schemas.microsoft.com/intellisense/ie5”>
</HEAD>
<body MS_POSITIONING=”GridLayout”>
<form id=”Form1” method=”post” runat=”server”>
<table border>
<tr>
<td>Name</td>
<td><asp:TextBox ID=”txtName” Runat=server></asp:TextBox></td>
</tr>
<tr>
<td>Password</td>
<td><asp:TextBox ID=”txtPassword”
Runat=server TextMode=Password>
</asp:TextBox></td>
</tr>
<tr>
<td colspan=2 align=right><asp:Button ID=”btnLogin” Text=”Login”
Runat=server></asp:Button></td>
</tr>
</table>
<p><asp:Label ID=”lbl” Runat=server
Visible=False ForeColor=Maroon Font-Bold=True>
Authentication failed</asp:Label></p>
</form>
</body>
</HTML>
|
login.aspx.vb:
Imports System.Xml
Imports System.Web.Security
Public Class WebForm1
Inherits System.Web.UI.Page
Protected WithEvents txtName As
System.Web.UI.WebControls.TextBox
Protected WithEvents txtPassword As
System.Web.UI.WebControls.TextBox
Protected WithEvents lbl As
System.Web.UI.WebControls.Label
Protected WithEvents btnLogin As
System.Web.UI.WebControls.Button
#Region “ Web Form Designer Generated Code “
‘This call is required by the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
End Sub
‘NOTE: The following placeholder declaration is required by the Web Form Designer.
‘Do not delete or move it.
Private designerPlaceholderDeclaration As System.Object
Private Sub Page_Init(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Init
‘CODEGEN: This method call is required by the Web Form Designer
‘Do not modify it using the code editor.
InitializeComponent()
End Sub
#End Region
Private Sub btnLogin_Click(ByVal sender
As Object, _
ByVal e As EventArgs) Handles btnLogin.Click
Dim xd As New XmlDocument, xr As XmlNodeReader
Dim sName As String, sPass As String
xd.Load(Server.MapPath(“users.xml”))
‘ Активируем XmlNodeReader
xr = New XmlNodeReader(xd.Item(“users”))
While xr.Read
If xr.Name = “name” And xr.NodeType = XmlNodeType.Element
Then
sName = xr.ReadString
If sName <> txtName.Text Then xr.Skip()
ElseIf xr.Name = “password” And xr.NodeType =
XmlNodeType.Element Then
If xr.ReadString() = txtPassword.Text Then
FormsAuthentication.RedirectFromLoginPage(txtName.Text, True)
Else
xr.Skip()
End If
End If
End While
lbl.Visible = True
End Sub
End Class
|
Давайте теперь проведём “разбор полётов”: вышеприведённый код содержит в себе
2 страницы. Все действия начинаются на странице default.aspx, в которой
происходит проверка, есть ли у текущего пользователя имя:
If context.Current.User.Identity.Name = “” Then
Response.Redirect(“login.aspx”)
Else
Response.Write(“<h2><I>Hello “ & context.Current.User.Identity.Name & “</I></h2>”)
End If
|
Если оно есть, то на экран будет выведено приветствие, в противном случае –
пользователь будет переадресован на страницу регистрации login.aspx, где ему
будет предложено ввести своё имя и пароль. Введённые сведения сверяются с
данными из XML файла. Если пользователь не будет найден, появится сообщение об
ошибке (рис. 3), в ином случае он будет благополучно переадресован на исходную
страницу default.aspx, которая, обнаружив, что у текущего пользователя имя
определено, поприветствует его.
Рис. 3 – Неверные данные при регистрации
Если вы успешно прошли аутентификацию и увидели приветствие, то закройте окно
броузера и попробуйте заново запустить страницу default.aspx. Вы сразу увидите
перед собой приветствие для того пользователя, чьё имя вы вводили в последний
раз. Дело в том, что при регистрации мы сохранили на машине клиента cookie-файл.
Это произошло в тот момент, когда мы в коде вызывали функцию
RedirectFromLoginPage, передав её параметру CreatePersistentCookie значение
True:
FormsAuthentication.RedirectFromLoginPage(txtName.Text, True)
|
Для того чтобы исключить передачу cookie файла достаточно вызвать эту функцию
со значением False параметра CreatePersistentCookie. Или есть другой способ – в
странице default.aspx добавьте обработчик события выгрузки страницы со следующим
кодом:
Private Sub Page_Unload(ByVal
sender As Object, _
ByVal e As System.EventArgs) Handles MyBase.Unload
FormsAuthentication.SignOut()
End Sub
|
В результате, после выгрузки главной страницы пользователь будет
регистрироваться о выходе.
Аутентификация формой с использованием файла конфигурации:
В предыдущем примере мы хранили все данные о пользователях в отдельном
XML-файле, но оказывается ASP.NET предоставляет возможность хранить сведения об
аккаунтах прямо в файле конфигурации Web-проекта. Преимуществом этого метода
является то, что для его реализации требуется значительно меньше программного
кода, поскольку в данном случае программисту не нужно вручную просматривать
XML-файл в поисках соответствующих совпадений – он лишь вызывает одну
единственную функцию, которая и решает всё дело. Для того чтобы понять принцип
работы этого механизма, давайте ещё раз обратимся к файлу конфигурации, а точнее
к тэгу forms. Этот тэг помимо уже описанных ранее атрибутов может также включать
раздел <credentials> - сертификаты:
Web.config:
<authentication mode=”Forms”>
<forms name=”ASP_XML_Form” loginUrl=”login.aspx”
protection=”All” timeout=”30” path=”/”
requireSSL=”false” slidingExpiration=”true”>
<credentials passwordFormat=”Clear”>
<user name=”John” password=”one”/>
<user name=”Mike” password=”two”/>
<user name=”Bill” password=”three”/>
</credentials>
</forms>
</authentication>
|
Как видно из вышеприведённого листинга, тэг credentials содержит один
единственный атрибут – passwordFormat. Этот параметр определяет способ хранения
пароля и принимает следующие значения:
- Clear – пароль сохраняется без каких-либо изменений
- SHA1 – пароль хэшируется методом SHA1 (Secure Hash
Algorithm версии 1)
- MD5 – пароль хэшируется методом MD5 (Message Digest
версии 5)
Если вы выберите какой-нибудь из алгоритмов хэширования, то пароль уже нельзя
будет хранить в исходной форме в файле конфигурации – его нужно будет сперва
хэшировать и лишь потом присвоить полученный результат атрибуту password. В
противном случае, когда ASP.NET будет проводить аутентификацию, пароли просто не
совпадут.
Теперь, когда мы имеем свежеиспечённую базу учётных записей, давайте вернёмся
к предыдущему приложению и изменим код обработчика события нажатия кнопки
регистрации в странице login.aspx:
login.aspx.vb:
Private Sub btnLogin_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles btnLogin.Click
If FormsAuthentication.Authenticate(txtName.Text, txtPassword.Text) Then
‘ успешно
FormsAuthentication.RedirectFromLoginPage(txtName.Text, False)
Else
lbl.Visible = True
End If
End Sub
|
Теперь сравните этот код с тем, который использовался в предыдущем примере.
Как видите, он сократился от множества условий и переборов до всего одного
запроса, возвращающего True или False.
Мы специально сейчас не станем рассматривать пример кода, работающего с
хэшированными паролями, чтобы не торопить события. Дело в том, что в 3-й части
этой статьи, которая будет посвящена криптографии, вы узнаете обо всех тонкостях
хэширования и шифрования данных и сможете сами применить эти методы на практике.
Аутентификация формой с использованием базы данных:
Давайте теперь рассмотрим пример работы с ещё одним хранилищем данных о
пользователях – с базой данных MS SQL Server. Большинство динамических сайтов
используют базы данных для хранения содержимого сайта. Сведения о пользователях
также не являются исключением и вполне могут занять своё место в общем пуле
данных. Для того, чтобы своими глазами увидеть, как всё это происходит, давайте
создадим тестовое приложение, которое вновь будет основано на уже известной нам
странице регистрации, применяемой в предыдущих примерах. Прежде всего,
необходимо приготовить базу данных, для этого откройте утилиту SQL Query
Analyzer и выполните в ней следующий код, написанный на языке tSQL:
FormAuthUsers.sql:
CREATE DATABASE FormAuthUsers
GO
USE FormAuthUsers
GO
CREATE TABLE [Users] (
[ID] [int] IDENTITY (1, 1) NOT NULL,
[UserName] [nvarchar] (50),
[Password] [nvarchar] (50),
CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED
([ID]) ON [PRIMARY]
) ON [PRIMARY]
GO
INSERT INTO Users (UserName, Password)
VALUES(‘John’, ‘one’)
GO
INSERT INTO Users (UserName, Password)
VALUES(‘Mike’, ‘two’)
GO
INSERT INTO Users (UserName, Password)
VALUES(‘Bill’, ‘three’)
GO
CREATE PROCEDURE FindUser
@Name nvarchar(50),
@Password nvarchar(50)
AS
SELECT COUNT(ID) FROM Users
WHERE UserName = @Name AND Password = @Password
GO
|
В результате выполнения этого кода на вашем SQL Server должна создаться база
данных с именем “FormAuthUsers”, в которой вы сможете найти таблицу
Users с тремя записями и хранимую процедуру FindUser. Эта
процедура возвращает количество пользователей, удовлетворяющих запросу, который
формируется из параметров, передаваемых этой процедуре.
Теперь, когда у нас готова база данных, мы можем приступить к созданию
страницы, которая будет с ней работать. Для этого вновь возьмите за основу
предыдущие примеры и замените обработчик события нажатия кнопки на странице
login.aspx:
login.aspx.vb:
Imports System.Data.SqlClient
Imports System.Web.Security
Public Class WebForm1
Inherits System.Web.UI.Page
Protected WithEvents txtName As
System.Web.UI.WebControls.TextBox
Protected WithEvents txtPassword As
System.Web.UI.WebControls.TextBox
Protected WithEvents lbl As
System.Web.UI.WebControls.Label
Protected WithEvents btnLogin As
System.Web.UI.WebControls.Button
#Region “ Web Form Designer Generated Code “
‘This call is required by the Web Form Designer.
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
End Sub
‘NOTE: The following placeholder declaration is required by the Web Form Designer.
‘Do not delete or move it.
Private designerPlaceholderDeclaration As System.Object
Private Sub Page_Init(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Init
‘CODEGEN: This method call is required by the Web Form Designer
‘Do not modify it using the code editor.
InitializeComponent()
End Sub
#End Region
Private Sub btnLogin_Click(ByVal sender
As Object, _
ByVal e As EventArgs) Handles btnLogin.Click
Dim cn As New _
SqlConnection(“server=localhost;database=FormAuthUsers;uid=sa;pwd=;”)
Dim cm As New SqlCommand(“FindUser”,
cn)
Dim n As Integer
Try
cn.Open()
Catch ex As SqlException
Response.Write(ex.Message)
Exit Sub
End Try
cm.CommandType = CommandType.StoredProcedure
Dim prmName = New SqlParameter(“@Name”, SqlDbType.NvarChar, 50)
prmName.Value = txtName.Text
cm.Parameters.Add(prmName)
Dim prmPass = New SqlParameter(“@Password”, SqlDbType.NvarChar,
50)
prmPass.Value = txtPassword.Text
cm.Parameters.Add(prmPass)
n = cm.ExecuteScalar
If n > 0 Then
FormsAuthentication.RedirectFromLoginPage(txtName.Text, False)
Else
lbl.Visible = True
End If
cn.Close()
End Sub
End Class
|
Для корректной работы этой страницы убедитесь, что строка подключения
подходит под вашу конфигурацию. Давайте разберёмся в том, что тут происходит.
Во-первых, создаётся объект соединения SqlConnection, в качестве параметра
которому передаётся строка подключения к базе данных:
Dim cn As New _
SqlConnection(“server=localhost;database=FormAuthUsers;uid=sa;pwd=;”)
|
После этого создаётся экземпляр объекта SqlCommand, который служит для
выполнения команд работы с данными. Следующие строки кода открывают соединение,
но при этом учитывается возможность исключений, которые вылавливаются
обработчиком исключений try:
Try
cn.Open()
Catch ex As SqlException
Response.Write(ex.Message)
Exit Sub
End Try
|
Если при открытии соединения возникают какие-либо сбои, то пользователь
получает соответствующее сообщение, и операция прерывается.
После этого объект SqlCommand настраивается на выполнение хранимой процедуры,
и подготавливаются параметры для её запуска. Для этих 7 строк кода, конечно же,
существует альтернатива, состоящие из 1 строки кода:
cm.CommandText = "exec FindUser '" & txtName.Text & "',
'" & txtPassword.Text & "'"
|
Но, не смотря на то, что этот код короче, время работы будет больше. Почему?
Дело в том, что с этой строкой вы осуществляете оперативный запрос, т. е. Вы
пишите непосредственно SQL-команду, которая вызывает хранимую процедуру. В
результате вы передаёте по сети дополнительные данные в виде команды “exec”,
которая в свою очередь занимает место в сетевом трафике; как только этот запрос
достигнет сервера, то сначала выполнится команда “exec”, и лишь потом запустится
нужная нам хранимая процедура FindUser. Кроме этого существует ещё более
тяжёлый способ, который заключается в отказе от хранимых процедур и вставке
всего необходимого кода запроса непосредственно в объект SqlCommand, в
результате чего ещё больше дополнительной информации отправляется по сетевому
трафику. Казалось бы, что это такой плюс-минус пара десятков байт, но, а если
вам придётся работать с огромными запросами, код которых значительно больше, чем
у нашей процедуры? Поэтому самым лучшим способом является использование хранимых
процедур, поскольку в этом случае вы получаете чёткое разделение обязанностей,
при котором клиентская страница отвечает только за ввод-вывод данных в доступной
пользователю форме; SQL Server выполняет все операции с данными; а IIS выступает
в роли посредника между клиентом и сервером – вот вам и трёхуровневая
архитектура. Не загружайте “нежные” клиентские машины лишней работой – лучше
доверьте её тяжёлой артиллерии, т. е. серверу.
Но вернёмся к нашему коду и продолжим его разбор: после определения типа
команды и подготовки всех параметров мы благополучно выполняем эту команду, при
чём, обратите внимание, что для выполнения используется функция ExecuteScalar.
Её следует применять, когда в качестве результата вы получаете скалярную
величину, т. е. число, что собственно и происходит в нашей процедуре FindUser –
она возвращает количество записей, удовлетворяющих заданному условию:
SELECT COUNT(ID) FROM Users
WHERE UserName = @Name AND Password = @Password
|
В конце кода, получив количество найденных записей, мы просто анализируем это
значение и выполняем соответствующие операции.
Аутентификация формой с использованием Web-служб:
Предположим, вы работаете в организации XYZ. Вам было поручено создать
приложение, управляющее информацией о персонале вашей организации. Вы работаете
над этим проектом уже 7 месяцев, и вдруг по соображениям безопасности вам было
поручено разместить информацию о пользователях на совсем другом сервере, с
которым активно работает другой отдел организации XYZ. Непосредственный доступ к
серверу вам не обеспечили, поэтому ваш проект не может напрямую обращаться к
базе данных с пользователями, расположенной на этом сервере. Для решения этой
проблемы было решено дать вам возможность разработать Web-службу, через которую
вы могли бы осуществлять контроль над аутентификацией пользователей.
Эта выдуманная история раскрывает ещё один способ, позволяющий проводить
аутентификацию – использование Web-служб. Web-службы становятся особенно
актуальными, когда у вас или у ваших клиентов нет полноценного доступа к
серверу. Кроме того, Web-службы применимы не только к Web-приложениям, но они
могут также быть использованы и программными продуктами, работающими на самых
разнообразных платформах. Это стало возможно благодаря применению технологии
SOAP (Simple Object Access Protocol), которая использует стандартные порты
TCP/IP и протокол HTTP.
Для работы с Web-службой её, прежде всего, нужно создать. Для этого начните
новый проект типа ASP.NET Web Service (рис. 4).
Рис. 4 – Создание Web-службы
Теперь, используя код обработчика события нажатия кнопки регистрации из
предыдущего примера, вставьте его в исходный код Web-службы, немного видоизменив
до следующей формы:
AuthSrvc.asmx:
Imports System.Web.Services
Imports System.Data.SqlClient
<System.Web.Services.WebService(Namespace := "http://tempuri.org/AuthSrvc/Service1")> _
Public Class Service1
Inherits System.Web.Services.WebService
#Region " Web Services Designer Generated Code "
Public Sub New()
MyBase.New()
InitializeComponent()
End Sub
Private components As System.ComponentModel.IContainer
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
components = New System.ComponentModel.Container()
End Sub
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
#End Region
<WebMethod()> Public Function Authenticate(ByVal UserName As String, _
ByVal Password As String, ByRef ErrMessage As String) As Boolean
Dim cn As New _
SqlConnection("server=localhost;database=FormAuthUsers;uid=sa;pwd=;")
Dim cm As New SqlCommand("FindUser", cn)
Dim n As Integer
Try
cn.Open()
Catch ex As SqlException
ErrMessage = ex.Message
Exit Function
End Try
cm.CommandType = CommandType.StoredProcedure
Dim prmName = New SqlParameter("@Name", SqlDbType.NVarChar, 50)
prmName.Value = UserName
cm.Parameters.Add(prmName)
Dim prmPass = New SqlParameter("@Password", SqlDbType.NVarChar, 50)
prmPass.Value = Password
cm.Parameters.Add(prmPass)
n = cm.ExecuteScalar
cn.Close()
If n > 0 Then
Return True
Else
Return False
End If
End Function
End Class
|
Вы можете проверить работоспособность службы, не отходя от кассы, для этого
просто запустите её на выполнение в среде Visual Studio .NET. Если в службе не
было ошибок, то увидите перед собой экран, на котором будут 2 гиперссылки. Одна
из них ведёт к описанию Web-службы средствами языка WSDL (Web Service
Description Language), а другая (Authenticate) позволяет протестировать
службу. Нажмите на вторую гиперссылку и заполните таблицу параметров, в
появившейся странице (рис. 5). Если вы введёте в поле UserName строку “John”, а
в качестве пароля подставите “one”, то функция вернёт значение True:
http://localhost/AuthSrvc/AuthSrvc.asmx/Authenticate:
<?xml version="1.0" encoding="utf-8" ?>
<boolean xmlns="http://tempuri.org/AuthSrvc/Service1">true</boolean>
|
Если изменить значение любого из этих полей на недействительное, т. е. на то,
которого нет в базе данных, то результат соответственно будет противоположным –
False.
Думаю, нет смысла детально разбирать код этой функции, потому что во многом
она похожа на свою предшественницу из предыдущего примера. Но, тем не менее,
следует обратить особое внимание на обработчик исключений. Если в листинге с
базой данных он при возникновении каких-либо исключений просто выводил
соответствующее сообщение на экран, то в Web-службе мы передаём сообщение об
ошибке параметру ErrMessage функции Authenticate, который был объявлен по
ссылке:.
Try
cn.Open()
Catch ex As SqlException
ErrMessage = ex.Message
Exit Function
End Try
|
В приложениях, которые будут использовать эту службу, мы встроим проверку на
наличие каких-либо исключений, и при их обнаружении будем выводить
соответствующее сообщение.
Рис. 5 – Проверка работоспособности Web-службы
Теперь давайте создадим приложение, которое будет использовать эту
Web-службу, но только на этот раз мы немного отойдём от темы и для разнообразия
создадим приложение Windows:
- Создайте новый проект типа Windows Application
- Измените форму так, чтобы она была похожа на форму, изображённую на рис.
6, или можете просто подставить код в конструктор из следующего листинга.
- В окне SolutionExplorer щёлкните правой кнопкой мыши по папке
References и выберите в появившемся контекстном меню команду Add Web
Reference…
- Перед вами появится диалог установки ссылок к Web-сервисам. Введите в поле
URL полный адрес к файлу .asmx и запустите поиск. В результате вы должны
увидеть нечто подобное рисунку 7.
- Нажмите на кнопку Add Reference, и в вашем проекте появится ссылка
на указанную Web-службу.
-
Рис. 6 – Примерный вид тестового приложения
Рис. 7 – Результаты поиска Web-службы
Теперь можно приступить к написанию программного кода, реализующего этот
Web-сервис. Весь необходимый код приведён ниже:
AuthSrvcRelease.vb:
Public Class Form1
Inherits System.Windows.Forms.Form
#Region " Windows Form Designer generated code "
Public Sub New()
MyBase.New()
InitializeComponent()
End Sub
Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If Not (components Is Nothing) Then
components.Dispose()
End If
End If
MyBase.Dispose(disposing)
End Sub
Private components As System.ComponentModel.IContainer
Friend WithEvents Label1 As
System.Windows.Forms.Label
Friend WithEvents Label2 As
System.Windows.Forms.Label
Friend WithEvents txtName As
System.Windows.Forms.TextBox
Friend WithEvents txtPassword As
System.Windows.Forms.TextBox
Friend WithEvents cmdExit As
System.Windows.Forms.Button
Friend WithEvents cmdLogin As
System.Windows.Forms.Button
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
Me.Label1 = New System.Windows.Forms.Label
Me.Label2 = New System.Windows.Forms.Label
Me.txtName = New System.Windows.Forms.TextBox
Me.txtPassword = New System.Windows.Forms.TextBox
Me.cmdExit = New System.Windows.Forms.Button
Me.cmdLogin = New System.Windows.Forms.Button
Me.SuspendLayout()
Me.Label1.Location = New System.Drawing.Point(8, 8)
Me.Label1.Name = "Label1"
Me.Label1.Size = New System.Drawing.Size(40, 16)
Me.Label1.TabIndex = 0
Me.Label1.Text = "Name:"
Me.Label2.Location = New System.Drawing.Point(8, 40)
Me.Label2.Name = "Label2"
Me.Label2.Size = New System.Drawing.Size(64, 16)
Me.Label2.TabIndex = 1
Me.Label2.Text = "Password:"
Me.txtName.Location = New System.Drawing.Point(80, 5)
Me.txtName.Name = "txtName"
Me.txtName.Size = New System.Drawing.Size(216, 20)
Me.txtName.TabIndex = 2
Me.txtName.Text = ""
Me.txtPassword.Location = New System.Drawing.Point(80, 37)
Me.txtPassword.Name = "txtPassword"
Me.txtPassword.PasswordChar = Microsoft.VisualBasic.ChrW(42)
Me.txtPassword.Size = New System.Drawing.Size(216, 20)
Me.txtPassword.TabIndex = 3
Me.txtPassword.Text = ""
Me.cmdExit.DialogResult = System.Windows.Forms.DialogResult.Cancel
Me.cmdExit.Location = New System.Drawing.Point(216, 72)
Me.cmdExit.Name = "cmdExit"
Me.cmdExit.Size = New System.Drawing.Size(80, 24)
Me.cmdExit.TabIndex = 4
Me.cmdExit.Text = "Exit"
Me.cmdLogin.Location = New System.Drawing.Point(128, 72)
Me.cmdLogin.Name = "cmdLogin"
Me.cmdLogin.Size = New System.Drawing.Size(80, 24)
Me.cmdLogin.TabIndex = 5
Me.cmdLogin.Text = "Login"
Me.AcceptButton = Me.cmdLogin
Me.AutoScaleBaseSize = New System.Drawing.Size(5, 13)
Me.CancelButton = Me.cmdExit
Me.ClientSize = New System.Drawing.Size(304, 103)
Me.Controls.Add(Me.cmdLogin)
Me.Controls.Add(Me.cmdExit)
Me.Controls.Add(Me.txtPassword)
Me.Controls.Add(Me.txtName)
Me.Controls.Add(Me.Label2)
Me.Controls.Add(Me.Label1)
Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog
Me.MaximizeBox = False
Me.MinimizeBox = False
Me.Name = "Form1"
Me.Text = "AuthSrvc Test application"
Me.ResumeLayout(False)
End Sub
#End Region
Private Sub cmdLogin_Click(ByVal sender
As System.Object, _
ByVal e As System.EventArgs) Handles
cmdLogin.Click
Dim au As New localhost.Service1
Dim sErr As String, bln As Boolean
Cursor = Cursors.WaitCursor
bln = au.Authenticate(txtName.Text, txtPassword.Text, sErr)
Cursor = Cursors.Default
If sErr <> "" Then
MsgBox(sErr)
Exit Sub
End If
If bln = True Then
MsgBox("Hello " & txtName.Text, MsgBoxStyle.Information)
Else
MsgBox("Wrong data!", MsgBoxStyle.Exclamation)
End If
End Sub
Private Sub cmdExit_Click(ByVal sender
As System.Object, _
ByVal e As System.EventArgs) Handles
cmdExit.Click
End
End Sub
End Class
|
В этом примере можно увидеть очень простой код, который заключается в обычном
вызове функции, которая выполняет все необходимые операции.
Как уже было ранее сказано, Web-службы основаны на технологии SOAP и потому
могут быть использованы приложениями, работающими совсем на другой платформе. Мы
не будем уходить далеко, отрекаясь от Windows, но попробуем вызвать эту же самую
Web-службу без применения технологий .NET, т. е. непосредственно через SOAP. Для
этого создайте следующий файл сценария на языке Visual Basic Script Edition
(VBScript) и запустите его на выполнение:
SOAP.vbs:
Set sc = CreateObject("MSSOAP.SoapClient")
sc.mssoapinit "http://localhost/AuthSrvc/AuthSrvc.asmx?WSDL"
If sc.Authenticate ("John", "one", s) = True Then
MsgBox "Hello John", 64
Else
MsgBox "Wrong data!!", 48
End If
Set sc = Nothing
|
Как видите, применяя объектную модель SOAP, вы можете обращаться к
Web-службам, используя самые разнообразные языки программирования (даже
скрипты!) и платформы.
Но не всё так идеально, как кажется. Под красивой обёрткой Web-сервисов
скрываются подводные камни, в первую очередь – это их собственная безопасность.
Web-службы имеют беззащитную XML-структуру, перехватив которую, можно легко
понять и получить передаваемые данные. Чтобы исключить, а точнее уменьшить
вероятность подобной утечки информации, необходимо обезопасить веб-службы. Для
этих целей существует ряд технологий, но наиболее распространённые только три из
них: правила Firewall’а, Secure Sockets Layer (SSL) и Virtual Private Network
(VPN).
Если вы точно знаете, какие компьютеры будут обращаться к вашему Web-сервису,
то в этом случае вам подойдёт вариант с применением правил Firewall’а, где вы
можете задать ограничения и права для конкретных IP-адресов, поэтому данный
метод больше применим для локальных сетей, где вам не приходится особо
беспокоиться о конфиденциальности передаваемых сведений. Очень удобным средством
для этого является Microsoft Security and Acceleration (ISA) Server. Он
предлагает расширенные правила политики, позволяющие ограничить или, наоборот,
открыть доступ к информации для конкретных клиентов.
SSL наибольшим образом подходит для сетей Internet. При его использовании
данные шифруются и передаются между сервером и клиентом; поступившие данные
после этого проходят аутентификацию, проверяя тем самым, от того ли источника
пришли эти данные. Это происходит с применением сертификатов, которые должны
находиться как у сервера, так и у клиента, поэтому с одной стороны использование
сертификатов позволяет удостовериться, что данные попадают в нужные руки, но с
другой стороны – нужно быть уверенным, что у получателя есть соответствующий
сертификат. Таким образом, для применения SSL вам нужно:
- Получить сертификаты: сертификаты бывают коммерческие и
триальные. Разница между ними заключается в том, что коммерческий будет
официально оформлен на покупателя и, соответственно, будет стоить денег, а
триальный можно получить бесплатно, но при этом без официального оформления.
Сертификат можно получить по следующему адресу: http://www.verisign.com/. Но какой бы тип
сертификата вы не заказывали, загрузить вам всё равно нужно будет 2: один для
сервера, а другой – для клиентов (его ещё называют Certificate Authority
(CA)).
- Настроить сервер и установить сертификаты на клиентских
броузерах: далее для успешного прохождения аутентификации запросов
SSL необходимо добавить сертификаты, как на сервере, так и на клиентских
машинах. Более того, клиентские сертификаты предназначены не для компьютера, а
для броузера, т. е., если пользователь использует и Internet Explorer, и
Netscape, желательно выдать ему сертификаты для обоих обозревателей. Впрочем,
и серверные сертификаты тоже предназначены для разных типов серверов (На
Verisign вы сможете найти сертификаты для более чем 50 видов серверов), но всё
отличие в том, что их, как правило, не меняют, разве только новую версию
устанавливают.
ПРИМЕЧАНИЕ
Но, не смотря на отсутствие официальной регистрации, триальный
сертификат является легальным. |
VPN – это расширение локальной сети, основанное на применении глобальной, в
частности, Internet’а. Например, пользователь, работающий на удалённой машине,
может соединиться с локальной сетью по средствам VPN, используя при этом
Internet. С помощью этой технологии вы можете отправлять данные между
компьютерами через защищённое соединение, поскольку VPN обладает теми же
средствами безопасности, что и локальная сеть. Одним из недостатков VPN
необходимость в долговременном соединении для эффективной работы. Для обмена
данными VPN работает со следующими протоколами: Microsoft Point-to-Point
Tunneling Protocol (PPTP), поставляемый с Windows NT 4.0 и Windows 2000, или
Layer Two Tunneling Protocol (L2TP), доступный в Windows 2000.
ПРИМЕЧАНИЕ
В списке соответствующих операционных систем приведены лишь те, начиная
с версий которых, данные протоколы стали доступными, т. е. в число этих ОС
должны войти и более поздние версии, например, Windows XP, Windows 2003
Server. |
Web-службы и средства их безопасности – это очень интересные и актуальные
темы, учитывая то, что рост популярности Web-сервисов пошёл резко вверх с
появлением .NET Framework и VS.NET. Но мы не станем дальше углубляться в
подробности, а вернёмся в русло этой статьи. Вы можете с лёгкостью сами освоить
все эти технологии. Для этого вам нужно лишь немного желания, терпения и
свободного времени. Я могу вам дать только путеводительные метки, которые смогут
вас направить по нужному курсу:
Аутентификация паспортом:
Паспорт – это единая система регистрации, созданная Microsoft, им можно
воспользоваться на любом Web-сайте, являющемся членом этой акции. Одним важным
плюсом данной технологии является то, что пользователю не нужно помнить
регистрационные данные для каждого сайта в отдельности, что часто случается,
когда привычный для вас аккуант уже занят на определённом web-узле. Паспорт
позволяет решить эту проблему благодаря тому, что он использует общую базу о
пользователях, поэтому на сайтах, поддерживающих .NET паспорт вы будете вводить
всегда одни и те же регистрационные данные: ваш e-mail и пароль.
Метод аутентификации на основе паспорта использует стандартные технологии Web
для удобства использования и сохранения конфиденциальности:
- защищённый протокол SSL
- cookie-файлы
- JavaScript 1.2
- шифрование методом 3DES
Для того чтобы реализовать всю мощь возможностей паспорта, вам нужно
выполнить следующие действия:
1. Загрузите .NET passport SDK по следующему адресу:http://msdn.microsoft.com/library/def
ault.asp?url=/downloads/list/websrvpass.asp
2. После этого вам следует зарегистрировать свой сайт в службе .NET паспорта:
http://go.microsoft.com/fwlink/?LinkID=9732.
Если вы не выполните регистрацию, то ваши возможности будут крайне ограничены, и
вы не сможете в полной мере получить ожидаемый результат, например, для выхода
из системы (т. е. logout) вам придётся закрыть все окна броузера и после этого
удалить все cookie-файлы с паспортными данными
Также как и при использовании других типов аутентификации, сначала нужно
настроить файл конфигурации проекта. Следующий листинг демонстрирует базовое
содержание раздела authentication файла настройки:
<authentication mode="Passport">
<passport redirectUrl="login.aspx" />
</authentication>
|
В этом коде мы задаём тип аутентификации паспортом, после чего задаём один
единственный параметр, настраивающий аутентификацию паспортом – адрес страницы,
на которую будет переадресован пользователь, при возникновении необходимости
пройти регистрацию: <passport redirectUrl="login.aspx" />
Ещё одна черта, объединяющая все виды аутентификации, - это интерфейс
IIdendity, на основе которого были созданы все классы сведений о пользователе
для различных видов аутентификации. Аутентификация паспортом тоже не является
исключением из этого списка, и средством, реализующим все основные свойства,
стал объект System.Web.Security.PassportIdentity инфраструктуры .NET
Framework.
Для обозначения ссылки к регистрационной странице принято использовать
специализированный логотип, подгружаемый через Интернет. Из-за того, что этот
логотип обычно приходится использовать довольно часто, лучше всего создать
отдельный элемент управления, реализующий компонент аутентификации. Для этого
выполните следующие действия:
- Cоздайте в VS.NET новый проект типа ASP.NET Web Application
- Добавьте в него пользовательский элемент управления Web User Control и
задаёте ему имя passport.ascx
- Замените его исходный код на следующий:
passport.ascx.vb:
Imports System.Web.Security
Public Class passport
Inherits System.Web.UI.UserControl
#Region " Web Form Designer Generated Code "
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
End Sub
Private designerPlaceholderDeclaration As System.Object
Private Sub Page_Init(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Init
InitializeComponent()
End Sub
#End Region
Private Sub Page_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
Dim id As PassportIdentity
id = CType(context.User.Identity, PassportIdentity)
Response.Write(id.LogoTag())
End Sub
End Class
|
- После этого измените имя страницы Web-проекта на login.aspx и
введите следующий код структуры страницы:
login.aspx:
<%@ Page Language="vb" AutoEventWireup="false" Codebehind="login.aspx.vb"
Inherits="PassAuth.WebForm1"%>
<%@ Register TagName="passport" TagPrefix="ctl" src="passport.ascx"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>LogIn</title>
<meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1">
<meta name="CODE_LANGUAGE" content="Visual Basic .NET 7.1">
<meta name="vs_defaultClientScript" content="JavaScript">
<meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
</head>
<body MS_POSITIONING="GridLayout">
<form id="Form1" method="post" runat="server">
<ctl:passport id="pas" runat=server></ctl:passport>
</form>
</body>
</html>
|
Все основные действия по аутентификации пользователя берёт на себя объект
PassportIdentity, а точнее служба Microsoft Passport, на которую .NET Framework
выходит с помощью объекта PassportIdentity. Именно поэтому, вам остаётся только
пожинать плоды, но для того, чтобы знать, что конкретно можно и нужно пожинать,
обратитесь к таблице 1, в которой разъясняются все возможные атрибуты,
описывающие зарегистрировавшегося пользователя.
Имя атрибута |
Описание |
Accessibility |
Определяет, следует ли допустить опции доступности для данного
пользователя на всех узлах, являющимися членами Microsoft Passport |
BDay_precision |
Определяет точность атрибута Birthdate |
Birthdate |
Содержит дату или год рождения пользователя, в зависимости от значения
атрибута BDay_precision |
City |
Идентификатор GeoID, хранящий информацию о местоположении
пользователя |
Country |
Код страны пользователя по стандарту ISO 3166 |
Directory |
Пока не используется |
Firstname |
Имя пользователя |
Flags |
Содержит опции пользовательского профиля |
Gender |
Определяет пол пользователя |
Lang_Preference |
Идентификатор LCID национального языка пользователя |
Lastname |
Фамилия пользователя |
MemberIDHigh |
Уникальный идентификатор пользователя PUID высокого уровня |
MemberIDLow |
Уникальный идентификатор пользователя PUID низкого уровня |
MemberName |
Содержит имя пользователя и имя домена, разделённые знаком “@” |
Nickname |
Дружелюбное обращение к пользователю |
Occupation |
Содержит некоторую дополнительную информацию о пользователе, в
частности, род деятельности |
PostalCode |
Почтовый индекс пользователя в США или в другой стране |
PreferredEmail |
Адрес электронной почты пользователя |
ProfileVersion |
Версия профиля пользователя |
Region |
Идентификатор GeoID, обозначающий место проживания пользователя в
стране |
TimeZone |
Определяет часовой пояс, в котором проживает пользователь |
Wallet |
Определяет, хранит ли пользователь паспорт в
бумажнике |
Табл. 1 – Опции профиля пользователя
Для получения доступа ко всем этим атрибутам есть два способа: методом
GetProfileObject объекта PassportIdentity и через свойство Item того же объекта.
Следующий листинг, написанный на языке C#, демонстрирует оба эти способа в
действии:
default.aspx.cs:
using System.Web.Security;
…
private void Page_Load(object sender,
System.EventArgs e)
{
PassportIdentity id;
id = (PassportIdentity)User.Identity;
Response.Write(id["Firstname"] + "<br>");
Response.Write(id.GetProfileObject("Lastname") + "<br>");
}
|
Теперь давайте вернёмся к нашему проекту с элементом управления passport.ascx
и доведём страницу регистрации до ума. Для этого измените файлы login.aspx и
login.aspx.vb следующим образом:
login.aspx:
<%@ Page Language="vb" AutoEventWireup="false"
Codebehind="login.aspx.vb" Inherits="PassAuth.WebForm1"%>
<%@ Register TagName="passport" TagPrefix="ctl" src="passport.ascx"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>LogIn</title>
<meta name="GENERATOR" content="Microsoft Visual Studio .NET 7.1">
<meta name="CODE_LANGUAGE" content="Visual Basic .NET 7.1">
<meta name="vs_defaultClientScript" content="JavaScript">
<meta name="vs_targetSchema" content="http://schemas.microsoft.com/intellisense/ie5">
</head>
<body MS_POSITIONING="GridLayout">
<form id="Form1" method="post" runat="server">
<p><asp:Label ID="lblLogin" Runat=server>Please login...</asp:Label>
<ctl:passport id="pas" runat=server/></p>
<asp:Label ID="lbl" Runat=server Visible=False>
<table border>
<tr>
<th>PUID:</th>
<td><asp:Label ID="lblPUID" Runat=server/></td>
</tr>
<tr>
<th>Firstname:</th>
<td><asp:Label ID="lblFName" Runat=server/></td>
</tr>
<tr>
<th>Lastname:</th>
<td><asp:Label ID="lblLName" Runat=server/></td>
</tr>
<tr>
<th>E-mail:</th>
<td><asp:Label ID="lblEmail" Runat=server/></td>
</tr>
</table>
</asp:Label>
</form>
</body>
</html>
|
login.aspx.vb:
Imports System.Web.Security
Public Class WebForm1
Inherits System.Web.UI.Page
Protected WithEvents lbl As
System.Web.UI.WebControls.Label
Protected WithEvents lblLogin As
System.Web.UI.WebControls.Label
Protected WithEvents lblPUID As
System.Web.UI.WebControls.Label
Protected WithEvents lblFName As
System.Web.UI.WebControls.Label
Protected WithEvents lblLName As
System.Web.UI.WebControls.Label
Protected WithEvents lblEmail As
System.Web.UI.WebControls.Label
#Region " Web Form Designer Generated Code "
<System.Diagnostics.DebuggerStepThrough()> Private Sub
InitializeComponent()
End Sub
Private designerPlaceholderDeclaration As System.Object
Private Sub Page_Init(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Init
InitializeComponent()
End Sub
#End Region
Private Sub Page_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
If User.Identity.IsAuthenticated Then
Dim id As PassportIdentity = CType(User.Identity, PassportIdentity)
lbl.Visible = True
lblPUID.Text = User.Identity.Name
lblFName.Text = id("Firstname")
lblLName.Text = id("Lastname")
lblEmail.Text = id("PreferredEmail")
lblLogin.Visible = False
Else
lblLogin.Visible = True
lbl.Visible = False
End If
End Sub
End Class
|
Обратите внимание, что в предыдущем примере одним из полей таблицы было поле
PUID, и данные в него мы загружали из свойства User.Identity.Name. Это свойство
хранит в себе уникальный идентификатор Passport User ID конкретного
пользователя, и, если вам нужно будет получить данные на определённого
пользователя, то для его нахождения и обозначения нужно использовать именно это
свойство, а не, скажем, атрибут профиля пользователя MemberName. Не смотря на
то, что данное свойство Name находится в объекте User.Identity, а не в
PassportIdentity, оно всё равно содержит в себе нужный вам PUID, поскольку
объект User.Identity содержит в себе информацию о текущем зарегистрированном
пользователе и соответственно значение его свойства Name определяется способом
аутентификации.
На этом мы завершаем обзор средств аутентификации в среде ASP.NET. Чтобы на
пути освоения новых технологий вы всегда могли чувствовать поддержку за плечами,
то в помощь вам необъятные ресурсы глобальной сети Интернет, и материалы
библиотеки MSDN. В следующей части статьи мы взглянем на мир информационной
безопасности с ещё одной стороны – со стороны авторизации.
Скачать примеры
Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен
в какой бы то ни было форме и какими бы то ни было средствами без письменного
разрешения владельцев авторских прав.