Сообщений 4    Оценка 15        Оценить  
Система Orphus

Средства безопасности ASP.NET

Часть 1 – Аутентификация

Автор: Сергей Бакланов
Источник: RSDN Magazine #2-2004
Опубликовано: 10.10.2004
Исправлено: 10.12.2016
Версия текста: 1.0
Windows-аутентификация
Аутентификация формой
Аутентификация формой с хранением аутентификационной информации в XML-файлах
Аутентификация формой с хранением информации в файле конфигурации
Аутентификация формой с использованием базы данных
Аутентификация формой с использованием Web-служб
Аутентификация с помощью Microsoft Passport

Исходные тексты примеров

На сегодняшний день информация имеет очень большое значение, часто утечка даже самого незначительного её количества может оказаться огромной потерей. Во избежание подобных инцидентов нужно уметь её защищать. Для этого есть множество способов и средств, начиная от обычного шифрования информации методом Цезаря(перемещение каждого символа на 3 вперёд) и заканчивая внедрением карт доступа и средств биосканирования. Каждое средство предназначено для своих целей, поэтому нужно чётко представлять, что вы хотите сделать, чего пытаетесь добиться. Разумеется, самыми надёжным методом является внедрение отдельных устройств идентификации личности. Это могут быть сканеры сетчатки глаза, сканеры отпечатков пальцев, отдельные кардридеры и другие изощрённые способы. Но такие средства стоят очень дорого, и их поддержка тоже оказывается далеко не самым дешёвым и доступным удовольствием. Применение подобных технологий могут себе позволить только крупные компании и государственные учреждения, имеющие как финансовые возможности, так и ярко выраженные потребности в этом. Технические средства позволяют не только обезопасить систему от несанкционированного доступа, но и предоставляют полный контроль за перемещением персонала как в реальном физическом мире, так и в виртуальном, т. е. по сетям компании.

Наряду с дорогими и высокотехнологичными системами безопасности существуют технологии более низкого ранга, но всё же способные обеспечить безопасность на своём уровне – на уровне программном. Давайте познакомимся с ними поближе, а точнее, со средствами, которые наиболее распространены в среде ASP.NET и .NET Framework. Здесь основное внимание будет уделено таким аспектам безопасности ASP.NET, как аутентификация, авторизация и криптография.

Для начала следует провести чёткую грань между понятиями аутентификации и авторизации. Аутентификация – процесс выяснения и проверки личности пользователя с помощью получения от него пары логин/пароль и сравнения их с каким-либо заслуживающим доверия источником. Наглядным примером аутентификации может служить вход в Windows. Авторизация – это проверка прав доступа к определённому ресурсу или проверка привилегий на выполнение определённых действий. Например, авторизация в Windows проходит каждый раз, когда вы пытаетесь изменить настройки системы, добавить или удалить пользователей, и если у вас не окажется соответствующих прав для выполнения подобных действий, то операционная система выдаст вам соответствующую ошибку.

Давайте теперь перейдём к описанию процесса аутентификации непосредственно в рамках среды ASP.NET, предоставляющей выбор из трех видов аутентификации:

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:

<authentication mode="Windows" />

Теперь можно приступить непосредственно к программированию и реализации аутентификации на основе Windows. .NET Framework предоставляет для этого два основных класса:

Имя пользователя и название группы хранятся в объекте WindowsIdentity в формате DOMAIN\UserName и DOMAIN\Group, соответственно. Исключение составляют лишь встроенные группы, например группа Administrators, обратиться к которой можно через WindowsIdentity, используя строку подключения: BUILTIN\Administrators. Другой способ задать встроенную группу – воспользоваться перечислением System.Security.Principal.WindowsBuiltInRole.

Из рисунка 1 видно, что объект WindowsIdentity позволяет:


Рисунок 1. Объект WindowsIdentity.

В приложениях ASP.NET к объекту WindowsIdentity можно обратиться следующим образом:

HttpContext.Current.User.Identity 

WindowsIdentity позволяет, кроме всего прочего, определить, к какой роли принадлежит текущий пользователь. Свойство User в этой цепочке реализует интерфейс IPrincipal, дающий возможность определить роль пользователя путём вызова функции IsInRole, имеющей следующий синтаксис:

      Public
      Overridable
      Function IsInRole(ByVal role AsString) AsBoolean
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 "'Этот вызов нужен Web Form Designer-у.
  <System.Diagnostics.DebuggerStepThrough()> PrivateSub InitializeComponent()

  EndSub'NOTE: The following placeholder declaration is required by the Web 'Form Designer. Do not delete or move it.Private designerPlaceholderDeclaration As System.ObjectPrivateSub Page_Init(ByVal sender As System.Object, _
      ByVal e As System.EventArgs) HandlesMyBase.Init
    'CODEGEN: This method call is required by the Web Form Designer'Do not modify it using the code editor.
    InitializeComponent()
  EndSub
#End Region

  PrivateSub Page_Load(ByVal sender As System.Object, _
      ByVal e As System.EventArgs) HandlesMyBase.Load
    Dim s AsString

    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)
  EndSubEndClass

Если был выбран режим аутентификации Windows, и настройки IIS не вызвали никаких конфликтных ситуаций, то вы получите соответствующую информацию о текущем пользователе. Если же поле имени пользователя и типа аутентификации оказались пустыми, нужно настроить IIS. Для этого выполните следующие действия:

  1. Откройте IIS и найдите виртуальный каталог с этим приложением.
  2. Откройте окно свойств для этого каталога и перейдите на закладку Безопасность каталога (Directory security).
  3. В рамке Анонимный доступ и проверка подлинности (Anonymous access and authentication control) нажмите кнопку Изменить….
  4. В появившемся окне (рисунок 2) снимите флажок Анонимный доступ (Anonymous access).


Рисунок 2. Настройка IIS.

На этом мы закончим рассмотрение Windows-аутентификации и перейдём к аутентификации формой.

Аутентификация формой

Аутентификация формой или, как её ещё называют, аутентификация на основе Cookie-файлов, имеет ряд преимуществ по сравнению с Windows-аутентификацией:

Но, несмотря на такое изобилие возможностей аутентификации на основе формы, существует и одно весомое ограничение – пользователь должен разрешить применение cookie-файлов. Без этого аутентификация формой с применением средств ASP.NET работать не будет. Обратите внимание на слова "…с применением средств ASP.NET…". Это означает, что не будет работать механизм, освобождающий разработчика от рутинных операций бесконечных проверок. Иными словами, все запросы, поступившие от пользователя, ещё не прошедшего аутентификацию, переадресовываются на страницу регистрации, где он вводит необходимую информацию (чаще всего имя пользователя и пароль). Полученные сведения передаются среде ASP.NET, где происходит их проверка. В случае успеха пользователю передаётся cookie-файл, в котором содержится билет для авторизации (Authorization ticket), имя пользователя и ключ для идентификации пользователя при следующих обращениях. В результате все последующие обращения броузера будут автоматически включать в заголовки сведения из cookie, направляемые на проверку в среду ASP.NET. Поэтому, если пользователь не разрешит использование cookie, проверять, прошёл ли он аутентификацию, придется при каждом обращении. В предыдущих версиях ASP для этого применяли, например, объект Session, примерно следующим образом:

      If
      Not (Session("Registered") = "1") Then
  Response.Redirect("login.asp")
EndIf

Для использования аутентификации формой сначала нужно настроить конфигурацию 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 определяет способ аутентификации. В предыдущих примерах использовалось значение Windows, которое включало режим Windows-аутентификации. Теперь же будет использоваться режим Forms. Кроме этих двух значений, допустимы Passport и None – первое определяет аутентификацию на основе Microsoft Passport, о которой речь пойдёт позже, вторая отключает её вообще. Тег <forms> присущ только аутентификации на основе формы и включает в себя следующие сведения:

Выше были описаны все возможные атрибуты тега 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

PublicClass _default
  Inherits System.Web.UI.Page

#Region" Web Form Designer Generated Code "'This call is required by the Web Form Designer.
  <System.Diagnostics.DebuggerStepThrough()> _
  PrivateSub InitializeComponent()

  EndSub' NOTE: The following placeholder declaration is required ' by the Web Form Designer.'Do not delete or move it.Private designerPlaceholderDeclaration As System.ObjectPrivateSub Page_Init(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) HandlesMyBase.Init
    'CODEGEN: This method call is required by the Web Form Designer'Do not modify it using the code editor.
    InitializeComponent()
  EndSub

#End Region

  PrivateSub Page_Load(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) HandlesMyBase.Load
    'Put user code to initialize the page hereIf context.Current.User.Identity.Name = ""Then
     Response.Redirect("login.aspx")
    Else
     Response.Write("<h2><I>Hello " _ 
       & context.Current.User.Identity.Name & "</I></h2>")
    EndIfEndSubEndClass
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

PublicClass WebForm1
  Inherits System.Web.UI.Page

  ProtectedWithEvents txtName As System.Web.UI.WebControls.TextBox
  ProtectedWithEvents txtPassword As System.Web.UI.WebControls.TextBox
  ProtectedWithEvents lbl As System.Web.UI.WebControls.Label
  ProtectedWithEvents 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()> PrivateSub InitializeComponent()

  EndSub'NOTE: The following placeholder declaration 'is required by the Web Form Designer.'Do not delete or move it.Private designerPlaceholderDeclaration As System.ObjectPrivateSub Page_Init(ByVal sender 
    As System.Object, ByVal e As System.EventArgs) HandlesMyBase.Init
    'CODEGEN: This method call is required by the Web Form Designer'Do not modify it using the code editor.
    InitializeComponent()
  EndSub

#End Region
  
  PrivateSub btnLogin_Click(ByVal sender AsObject, ByVal e As EventArgs) 
    Handles btnLogin.Click
    Dim xd AsNew XmlDocument, xr As XmlNodeReader
    Dim sName AsString, sPass AsString' Открываем XML-файл
    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 ThenIf xr.ReadString() = txtPassword.Text Then' Если пароли совпали, значит аутентификация проведена успешно
          FormsAuthentication.RedirectFromLoginPage(txtName.Text, True)
        Else' Если нет, то переходим к другому пользователю
          xr.Skip()
        EndIfEndIfEndWhile' Если эта строка выполняется, значит данные о пользователе 
    ‘ были введены неверно
    lbl.Visible = TrueEndSubEndClass

Давайте теперь проведём "разбор полётов". Все действия начинаются на странице 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>")
EndIf

Если имя есть, то на экран будет выведено приветствие, в противном случае пользователь будет переадресован на страницу регистрации 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 AsObject, _
    ByVal e As System.EventArgs) HandlesMyBase.Unload
  FormsAuthentication.SignOut()
EndSub

В результате, после выгрузки главной страницы, пользователь выйдет с сайта. При следующей попытке открыть на сайт ему будет предложено пройти аутентификацию.

Аутентификация формой с хранением информации в файле конфигурации

В предыдущем примере мы хранили все данные о пользователях в отдельном 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. Этот атрибут определяет способ хранения пароля и принимает следующие значения:

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

Теперь, когда мы имеем свежеиспечённую базу учётных записей, давайте вернёмся к предыдущему приложению и изменим код обработчика события нажатия кнопки регистрации в странице login.aspx:

login.aspx.vb:
      Private
      Sub btnLogin_Click(ByVal sender AsObject, ByVal e As EventArgs) _
  Handles btnLogin.Click
  If FormsAuthentication.Authenticate(txtName.Text, txtPassword.Text) Then' Если пользователь найден в разделе сертификатов, значит, ' регистрация проведена успешно
    FormsAuthentication.RedirectFromLoginPage(txtName.Text, False)
  Else' Иначе – выводим сообщение об ошибке
    lbl.Visible = TrueEndIfEndSub

Теперь сравните этот код с тем, который использовался в предыдущем примере. Как видите, он сократился до единственного запроса, возвращающего True или False — мы избавились от цикла и множества проверок.

Чтобы не забегать вперед, пока не будем рассматривать пример кода, работающего с хэшированными паролями. Дело в том, что в 3-й части этой статьи, которая будет посвящена криптографии, будет рассказано обо всех тонкостях хэширования и шифрования данных, и вы сможете сами применить эти методы на практике.

Аутентификация формой с использованием базы данных

Давайте теперь рассмотрим пример работы с ещё одним хранилищем данных о пользователях – с базой данных MS SQL Server. Большинство сайтов для хранения содержимого используют базы данных. Сведения о пользователях также не являются исключением и вполне могут занять своё место в общем пуле данных. Чтобы своими глазами увидеть, как всё это работает, давайте создадим тестовое приложение. Оно будет основано на уже знакомой по предыдущим примерам странице регистрации. Прежде всего, необходимо создать базу данных. Для этого в утилите SQL Query Analyzer нужно выполнить следующий код на языке TSQL:

FormAuthUsers.sql:
      -- Создание БД 'FormAuthUsers' и таблицы 'Users'
      CREATE
      DATABASE FormAuthUsers
GO
USE FormAuthUsers
GO
CREATETABLE [Users] (
  [ID] [int] IDENTITY (1, 1) NOTNULL,
  [UserName] [nvarchar] (50),
  [Password] [nvarchar] (50),
  CONSTRAINT [PK_Users] PRIMARYKEYCLUSTERED
  ([ID]) ON [PRIMARY]
) ON [PRIMARY]

GO

--Заполнение таблицы 'Users'INSERTINTO Users (UserName, Password)
VALUES('John'</str>, 'one')
GO
INSERTINTO Users (UserName, Password)
VALUES('Mike', 'two')
GO
INSERTINTO Users (UserName, Password)
VALUES('Bill', 'three')

GO

--Создание процедуры 'FindUser'CREATEPROCEDURE FindUser
  @Name nvarchar(50),
  @Password nvarchar(50)
ASSELECT COUNT(ID) FROM Users
  WHERE UserName = @Name AND Password = @Password

GO

В результате выполнения этого кода будет создана БД с именем "FormAuthUsers", содержащая таблицу Users с тремя записями и хранимую процедуру FindUser. Эта процедура возвращает количество имен пользователей, удовлетворяющих запросу, который формируется из передаваемых ей параметров.

Теперь, когда БД готова, можно приступить к созданию страницы, работающей с ней. Возьмите предыдущий пример и замените обработчик события нажатия кнопки на странице login.aspx.

login.aspx.vb:
      Imports System.Data.SqlClient
Imports System.Web.Security

PublicClass WebForm1
  Inherits System.Web.UI.Page

  ProtectedWithEvents txtName As System.Web.UI.WebControls.TextBox
  ProtectedWithEvents txtPassword As System.Web.UI.WebControls.TextBox
  ProtectedWithEvents lbl As System.Web.UI.WebControls.Label
  ProtectedWithEvents 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()> PrivateSub InitializeComponent()

  EndSub'NOTE: The following placeholder declaration 'is required by the Web Form Designer.'Do not delete or move it.Private designerPlaceholderDeclaration As System.ObjectPrivateSub Page_Init(ByVal sender As System.Object, _
      ByVal e As System.EventArgs) HandlesMyBase.Init
    'CODEGEN: This method call is required by the Web Form Designer'Do not modify it using the code editor.
    InitializeComponent()
  EndSub

#End Region

  PrivateSub btnLogin_Click(ByVal sender AsObject, ByVal e As EventArgs) _
      Handles btnLogin.Click
    Dim cn AsNew _
      SqlConnection("server=localhost;database=FormAuthUsers;uid=sa;pwd=;")
    Dim cm AsNew SqlCommand("FindUser", cn)
    Dim n AsInteger' Открываем соединениеTry
      cn.Open()
    Catch ex As SqlException
      Response.Write(ex.Message)
      ExitSubEndTry' Задаём тип команды
    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 = TrueEndIf

    cn.Close()
  EndSubEndClass

Убедитесь, что строка подключения соответствует вашей БД. Давайте разберёмся, что тут происходит. Во-первых, создаётся объект соединения SqlConnection, которому в качестве параметра передаётся строка подключения к базе данных:

      Dim cn AsNew _
  SqlConnection("server=localhost;database=FormAuthUsers;uid=sa;pwd=;")

После этого создаётся экземпляр объекта SqlCommand, служащий для выполнения команд работы с данными. Следующие строки кода открывают соединение, но при этом учитывается возможность исключений, которые вылавливаются обработчиком исключений try-catch.

      ' Открываем соединение
      Try
  cn.Open()
Catch ex As SqlException
  Response.Write(ex.Message)
  ExitSubEndTry

Если при открытии соединения возникают какие-либо сбои, пользователь получает соответствующее сообщение, и операция прерывается.

После этого объект SqlCommand настраивается на выполнение хранимой процедуры, и готовятся параметры для её запуска.

Процедура 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")> PublicClass Service1
  Inherits System.Web.Services.WebService

#Region" Web Services Designer Generated Code "PublicSubNew()
    MyBase.New()

    'This call is required by the Web Services Designer.
    InitializeComponent()

    'Add your own initialization code after the InitializeComponent() callEndSub'Required by the Web Services DesignerPrivate components As System.ComponentModel.IContainer

  'NOTE: The following procedure is required by the Web Services Designer'It can be modified using the Web Services Designer. 'Do not modify it using the code editor.
  <System.Diagnostics.DebuggerStepThrough()> PrivateSub InitializeComponent()
    components = New System.ComponentModel.Container()
  EndSubProtectedOverloadsOverridesSub Dispose(ByVal disposing AsBoolean)
    'CODEGEN: This procedure is required by the Web Services Designer'Do not modify it using the code editor.If disposing ThenIfNot (components IsNothing) Then
        components.Dispose()
      EndIfEndIfMyBase.Dispose(disposing)
  EndSub

#End Region

  ' Функция, осуществляющая проверку наличия пользователя с заданным именем и паролем
  <WebMethod()> PublicFunction Authenticate(ByVal UserName AsString, _
      ByVal Password AsString, ByRef ErrMessage AsString) AsBooleanDim cn AsNew _
      SqlConnection("server=localhost;database=FormAuthUsers;uid=sa;pwd=;")
    Dim cm AsNew SqlCommand("FindUser", cn)
    Dim n AsInteger' Открываем соединениеTry
      cn.Open()
    Catch ex As SqlException
      ' Если есть исключение, то передаём его описание параметру ErrMessage
      ErrMessage = ex.Message
      ExitFunctionEndTry' Задаём тип команды
    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' Если кого-то нашли, значит, регистрация пройдена успешноReturnTrueElse' если никого нет, значит, ошибкаReturnFalseEndIfEndFunctionEndClass

Вы можете тут же проверить работоспособность службы — просто запустите её на выполнение в среде 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
  ErrMessage = ex.Message
  ExitFunctionEndTry

В приложениях, которые будут использовать эту службу, нужно встроить проверку на наличие каких-либо исключений, и при их обнаружении выводить соответствующее сообщение.


Рисунок 5. Проверка работоспособности Web-службы.

Теперь давайте создадим приложение, которое будет использовать эту Web-службу, но только на этот раз для разнообразия создадим приложение Windows. Выполните следующую последовательность действий:

  1. Создайте новый проект типа Windows Application.
  2. Измените форму так, чтобы она была похожа на форму, изображённую на рисунке 6 .
  3. В окне SolutionExplorer щёлкните правой кнопкой мыши по папке References и выберите в появившемся контекстном меню команду Add Web Reference…
  4. Перед вами появится диалог установки ссылок к Web-сервисам. Введите в поле URL полный адрес к файлу .asmx и запустите поиск. В результате вы должны увидеть нечто подобное рисунку 7.
  5. Нажмите на кнопку Add Reference, и в вашем проекте появится ссылка на указанную Web-службу.


Рис. 6. Примерный вид тестового приложения


Рис. 7. Результаты поиска Web-службы

Теперь можно приступить к написанию программного кода, реализующего этот Web-сервис. Весь необходимый код приведён ниже.

AuthSrvcRelease.vb:
      Public
      Class Form1
  Inherits System.Windows.Forms.Form

#Region" Windows Form Designer generated code "PublicSubNew()
    MyBase.New()

    'This call is required by the Windows Form Designer.
    InitializeComponent()

    'Add any initialization after the InitializeComponent() callEndSub'Form overrides dispose to clean up the component list.ProtectedOverloadsOverridesSub Dispose(ByVal disposing AsBoolean)
    If disposing ThenIfNot (components IsNothing) Then
        components.Dispose()
      EndIfEndIfMyBase.Dispose(disposing)
  EndSub'Required by the Windows Form DesignerPrivate components As System.ComponentModel.IContainer

  'NOTE: The following procedure is required by the Windows Form Designer'It can be modified using the Windows Form Designer. 'Do not modify it using the code editor.FriendWithEvents Label1 As System.Windows.Forms.Label
  FriendWithEvents Label2 As System.Windows.Forms.Label
  FriendWithEvents txtName As System.Windows.Forms.TextBox
  FriendWithEvents txtPassword As System.Windows.Forms.TextBox
  FriendWithEvents cmdExit As System.Windows.Forms.Button
  FriendWithEvents cmdLogin As System.Windows.Forms.Button
  <System.Diagnostics.DebuggerStepThrough()> PrivateSub 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()
    ''Label1'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:"''Label2'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:"''txtName'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 = ""''txtPassword'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 = ""''cmdExit'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"''cmdLogin'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"''Form1'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 = FalseMe.MinimizeBox = FalseMe.Name = "Form1"Me.Text = "AuthSrvc Test application"Me.ResumeLayout(False)

  EndSub

#End Region

  PrivateSub cmdLogin_Click(ByVal sender As System.Object, _
      ByVal e As System.EventArgs) Handles cmdLogin.Click
    Dim au AsNew localhost.Service1
    Dim sErr AsString, bln AsBoolean' Осуществляем аутентификацию
    Cursor = Cursors.WaitCursor
    bln = au.Authenticate(txtName.Text, txtPassword.Text, sErr)
    Cursor = Cursors.Default' - Но сперва учтём возможные исключенияIf sErr <> ""Then
      MsgBox(sErr)
      ExitSubEndIf' - А теперь переходим к основной проверкеIf bln = TrueThen
      MsgBox("Hello " & txtName.Text, MsgBoxStyle.Information)
    Else
      MsgBox("Wrong data!", MsgBoxStyle.Exclamation)
    EndIfEndSubPrivateSub cmdExit_Click(ByVal sender As System.Object, ByVal e _
      As System.EventArgs) Handles cmdExit.Click
    EndEndSubEndClass

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

Как уже говорилось, Web-службы основаны на технологии SOAP и потому могут быть использованы приложениями, работающими совсем на другой платформе. Мы не будем уходить далеко, отрекаясь от Windows, но попробуем вызвать эту же самую Web-службу без применения технологий .NET, т. е. непосредственно через SOAP. Для этого создайте файл сценария на языке VBScript и запустите его на выполнение:

SOAP.vbs:
      ' Создаём экземпляр объекта SoapClient
      Set sc = CreateObject("MSSOAP.SoapClient")
' Соединяемся с веб-службой и вызываем метод Authenticate
sc.mssoapinit "http://localhost/AuthSrvc/AuthSrvc.asmx?WSDL"If sc.Authenticate ("John", "one", s) = TrueThen
  MsgBox "Hello John", 64
Else
  MsgBox "Ошибка!", 48
EndIf' Удаляем ссылку на объектSet sc = Nothing

Как видите, применяя объектную модель SOAP, можно обращаться к Web-службам, используя самые разнообразные языки программирования (даже скрипты!) и платформы.

Но не всё так гладко, как кажется. Под красивой обёрткой Web-сервисов скрываются подводные камни, в первую очередь – это их собственная безопасность. Сами Web-службы являются незащищенным протоколом, передающим информацию в виде XML. Чтобы исключить, а точнее — уменьшить вероятность утечки информации, необходимо обезопасить веб-службы. Для этих целей существует ряд технологий, но наиболее распространены только два из них: Secure Sockets Layer (SSL) и Virtual Private Network (VPN).

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

ПРИМЕЧАНИЕ

Несмотря на отсутствие официальной регистрации, триальный сертификат является легальным.

VPN – это организация виртуальной частной сети на основе глобальной, в частности, Internet’а. Например, пользователь, работающий на удалённой машине, может соединиться с локальной сетью через VPN, используя при этом Internet. С помощью этой технологии вы можете отправлять данные между компьютерами через защищённое соединение, поскольку 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-службы и средства их безопасности – это очень интересные и актуальные темы. С появлением .NET Framework и VS.NET наблюдается значительный рост популярности Web-сервисов. Но мы не станем дальше углубляться в подробности, а вернёмся в русло этой статьи.

Аутентификация с помощью Microsoft Passport

Passport – это единая система регистрации, созданная Microsoft, которой можно воспользоваться на любом Web-сайте, являющемся членом этой системы. Важным достоинством данной технологии является то, что пользователю не нужно помнить регистрационные данные для каждого сайта в отдельности. Passport позволяет решить проблему регистрации благодаря тому, что он использует общую базу о пользователях, поэтому на сайтах, поддерживающих Microsoft Passport, вы будете вводить всегда одни и те же регистрационные данные: ваш e-mail и пароль.

Метод Passport-аутентификации использует стандартные технологии Web:

Для использования Passport-аутентификации нужно выполнить следующие действия:

  1. Загрузить .NET Passport SDK (http://msdn.microsoft.com/library/default.asp?url=/downloads/list/websrvpass.asp);
  2. После этого нужно зарегистрировать свой сайт в службе .NET Passport: http://go.microsoft.com/fwlink/?LinkID=9732. Без этого ваши возможности будут крайне ограничены. Например, для выхода из системы (т. е. logout) вам придётся закрыть все окна броузера и после этого удалить все cookie-файлы с паспортными данными.

Так же, как и при использовании других типов аутентификации, сначала нужно настроить файл конфигурации проекта. Следующий листинг демонстрирует базовое содержание раздела <authentication> файла настройки:

<authentication mode="Passport"> 
  <passport redirectUrl="login.aspx" />
</authentication>

Здесь, как и раньше, задаётся тип аутентификации и один-единственный параметр – адрес страницы, на которую будет переадресован пользователь в случае необходимости пройти регистрацию:

<passport redirectUrl="login.aspx" />

Ещё одна черта, объединяющая все виды аутентификации, — это интерфейс IIdendity, на основе которого были созданы все классы сведений о пользователе для различных видов аутентификации. Passport-аутентификация не является исключением из этого списка. Средством, реализующим все основные свойства, стал объект System.Web.Security.PassportIdentity инфраструктуры .NET Framework.

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

passport.ascx.vb:
      Imports System.Web.Security

PublicClass passport
  Inherits System.Web.UI.UserControl

#Region" Web Form Designer Generated Code "'This call is required by the Web Form Designer.
  <System.Diagnostics.DebuggerStepThrough()> PrivateSub InitializeComponent()

  EndSub'NOTE: The following placeholder declaration 'is required by the Web Form Designer.'Do not delete or move it.Private designerPlaceholderDeclaration As System.ObjectPrivateSub Page_Init(ByVal sender As System.Object, _
      ByVal e As System.EventArgs) HandlesMyBase.Init
    'CODEGEN: This method call is required by the Web Form Designer'Do not modify it using the code editor.
    InitializeComponent()
  EndSub

#End Region

  PrivateSub Page_Load(ByVal sender As System.Object, _ 
      ByVal e As System.EventArgs) HandlesMyBase.Load
    Dim id As PassportIdentity

    ' Получаем данные о текущем пользователе
    id = CType(context.User.Identity, PassportIdentity)
    ' Отображаем кнопку регистрации
    Response.Write(id.LogoTag())
  EndSubEndClass
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 выходит с помощью этого объекта. Вам остаётся только пожинать плоды, но чтобы знать, что конкретно можно и нужно пожинать, обратитесь к таблице 1, в которой разъясняются все возможные атрибуты, описывающие зарегистрировавшегося пользователя.

Имя атрибута Описание
Accessibility Определяет, следует ли использовать опции доступности для данного пользователя на всех узлах, являющихся членами Microsoft Passport.
BDay_precision Определяет точность атрибута Birthdate.
Birthdate Содержит дату или год рождения пользователя, в зависимости от значения атрибута BDay_precision.
City Идентификатор GeoID, хранящий информацию о местоположении пользователя.
Country Код страны пользователя по стандарту ISO 3166.
Directory Пока не используется.
Firstname Имя пользователя.
Flags Содержит опции пользовательского профиля.
Gender Пол пользователя.
Lang_Preference Идентификатор LCID национального языка пользователя.
Lastname Фамилия пользователя.
MemberIDHigh Верхние 32 бита уникального идентификатора пользователя (PUID).
MemberIDLow Нижние 32 бита уникального идентификатора пользователя (PUID).
MemberName Содержит имя пользователя и имя домена, разделенные знаком "@".
Nickname Дружелюбное обращение к пользователю.
Occupation Род занятий.
PostalCode Почтовый индекс пользователя в США или в другой стране.
PreferredEmail Адрес электронной почты пользователя.
ProfileVersion Версия профиля пользователя.
Region Идентификатор GeoID, обозначающий место проживания пользователя.
TimeZone Часовой пояс, в котором проживает пользователь.
Таблица 1. Опции профиля пользователя.

Для получения доступа ко всем этим атрибутам есть два способа: методом GetProfileObject объекта PassportIdentity и через свойство Item того же объекта. Следующая программа написана на языке C# и демонстрирует оба эти способа.

default.aspx.cs:
      using System.Web.Security;
...
privatevoid 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

PublicClass WebForm1
  Inherits System.Web.UI.Page

  ProtectedWithEvents lbl As System.Web.UI.WebControls.Label
  ProtectedWithEvents lblLogin As System.Web.UI.WebControls.Label
  ProtectedWithEvents lblPUID As System.Web.UI.WebControls.Label
  ProtectedWithEvents lblFName As System.Web.UI.WebControls.Label
  ProtectedWithEvents lblLName As System.Web.UI.WebControls.Label
  ProtectedWithEvents lblEmail As System.Web.UI.WebControls.Label

#Region" Web Form Designer Generated Code "'This call is required by the Web Form Designer.
  <System.Diagnostics.DebuggerStepThrough()> PrivateSub InitializeComponent()

  EndSub'NOTE: The following placeholder declaration 'is required by the Web Form Designer.'Do not delete or move it.Private designerPlaceholderDeclaration As System.ObjectPrivateSub Page_Init(ByVal sender As System.Object, _
      ByVal e As System.EventArgs) HandlesMyBase.Init
    'CODEGEN: This method call is required by the Web Form Designer'Do not modify it using the code editor.
    InitializeComponent()
  EndSub

#End Region

  PrivateSub Page_Load(ByVal sender As System.Object, _
      ByVal e As System.EventArgs) HandlesMyBase.Load
    If User.Identity.IsAuthenticated Then' Если пользователь зарегистрирован, то' создаём объект PassportIdentity и' выводим информацию о нём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 = FalseElse' Если нет, то предлагаем ему зарегистрироваться' и скрываем таблицу
      lblLogin.Visible = True
      lbl.Visible = FalseEndIfEndSubEndClass

Обратите внимание, что в предыдущем примере одним из полей таблицы было поле PUID, и данные в него мы загружали из свойства User.Identity.Name. Это свойство хранит в себе уникальный идентификатор Passport User ID конкретного пользователя, и, если вам нужно будет получить данные на определённого пользователя, то для его нахождения и обозначения нужно использовать именно это свойство, а не, скажем, атрибут профиля пользователя MemberName. Несмотря на то, что данное свойство Name находится в объекте User.Identity, а не в PassportIdentity, оно содержит нужный вам PUID, поскольку объект User.Identity хранит информацию о текущем зарегистрированном пользователе.

На этом мы завершаем обзор средств аутентификации в среде ASP.NET. В следующей части статьи будет рассматриваться следующую часть системы безопасности ASP.NET – авторизацию.


Эта статья опубликована в журнале RSDN Magazine #2-2004. Информацию о журнале можно найти здесь
    Сообщений 4    Оценка 15        Оценить