(ASP.NET) ASP.NET (2005 год)

Аутентификация, авторизация (+имперсонализация), персонализация в ASP2

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


Но для того чтобы работать с поддержкой аутентификации и персонализации, зашитой в ASP2, надо выполнить ряд предварительных настроек:


Итак мы познакомились со всеми базовыми элементами аутентификации/авторизации ASP2. В этой короткой заметке я упомяну лишь еще пару моментов ASP2-техники.

  • Придание юзерам свойства группы - роли. И управление сайтом на базе прав, назначенных определенным ролям. Эту технику я рассмотрю подробнее в самом конце этой странички.
  • Созданная нами база применяется не только для аутентификации, но и для сохранения персональных данных, связанных с каждым юзером (в том числе комплект данных для анонимного юзера). Доступ к персональному профилю осуществляется через обьект HttpContext.Profile. В данном случае я определил в Web-конфиге параметр BodyColor с типом данных Integer (можно любой сериализуемый тип) - и наблюдаю значение этого параметра в контексте конкретного пользователя. Более подробно я описал эту тему здесь.
  • Имперсонализация - это особый вид авторизации, когда текущему контексту ASP.NET-приложения присваиваются права не анонимного юзера (как предусмотрено по умолчанию), а прав Windows-юзера, запросившего исполнение ASP2-приложения. Или даже произвольно указанного юзера в теге Identity. По умолчанию имперсонализация не применяется и вот такой код возвращает нам вот такие контексты. Однако достаточно добавить в Web-конфиг тег <identity impersonate="true" /> и ситуация с авторизацией меняется самым существенным образом. Теперь доступ к SQL и NTFS-ресурсам ведет вовсе не анонимный интернет-юзер, а конкретная Win-учетная запись. Это позволяет подключаться к SQL-серверу с разными учетными записями и правами и разрганичивать выполняемые права на операции в SQL-сервере в зависимости от того, как юзер залогинился в Windows. Это особенно важно в Интрасетях, когда, скажем, менеджеру даются права на редактирование отпускных цен, а кладовщику на редактирование остатков по складу и т.д.

    Любопытно, что хост-процесс девелоперского сервера студии всегда возвращает имперсонализированный контекст (в отличии от контекста IIS, рассмотренного выше), именно поэтому мы обычно наблюдаем при первом запуске приложения под IIS такую картинку.


    В заключение я опишу способ разрешения одной небольшой проблемки, возникающей при использовании стандартных конфигурационных баз ASP2. Дело в том, что при проэктировании сайта ВЕСЬМА УДОБНО работать на основании ролей. Например, проверять принадлежность к той или иной роли в CMS. Или, как было показано - менять меню сайта в зависимости от роли, к которой принадлежит юзер. Но...

    Но как заказчику назначить в пустой базе (где еще нету юзеров вообще, а только сконфигурены роли) того самого первого админа в базе, из под которого админу заказчика удасться залогинится и назначить принадлежность всем прочим юзерам к различным заведомо сконфигуренным группам? Скопировать WSAT на хостинг? Или переопределить на машине заказчика MashineConfig - чтобы его LocalSqlServer указывал на сервер хостинга? Но для этого заказчику придется у себя еще и VS2005 поставить. В общем, проблема неразрешима без отдельного сайта, производящего ПЕРВИЧНУЮ ИНИЦИАЛИЗАЦИЮ базы на хостинге. Причем силами самого заказчика. Его админа, который впишет туда свой первичный пароль, из под которого позже залогинится сам и станет раздавать всем прочим права. Причем этот пароль будет недоступен девелоперу.


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


    Этот простой сайт будет состоять из ОДНОЙ странички и разворачивается админом заказчика в любой из подкаталогов CMS. У него очень простой CONFIG, который надо будет приконнектить к конфигурируемой базе:

    00001: <?xml version="1.0"?>
    00002: <configuration>
    00003:     <appSettings/>
    00004:     <connectionStrings>
    00005:         <remove name="LocalSqlServer"/>
    00006:         <add name="LocalSqlServer" connectionString="server=XXXXXXXXXX;Initial Catalog=YYYYYYYY;User ID=ZZZZZZZZ;Password=WWWWWWWWW" providerName="System.Data.SqlClient"/>
    00007:         <add name="ConnStr" connectionString="server=XXXXXXXXXX;Initial Catalog=YYYYYYYY;User ID=ZZZZZZZZ;Password=WWWWWWWWW" providerName="System.Data.SqlClient"/>
    00008:     </connectionStrings>
    00009:     <system.web>
    00010:         <authentication mode="Windows"/>
    00011:         <roleManager enabled="true" />
    00012:         <compilation debug="true" strict="true" explicit="true"/>
    00013:         <pages>
    00014:             <namespaces>
    00015:                 <clear/>
    00016:                 <add namespace="System"/>
    00017:                 <add namespace="System.Collections"/>
    00018:                 <add namespace="System.Collections.Specialized"/>
    00019:                 <add namespace="System.Configuration"/>
    00020:                 <add namespace="System.Text"/>
    00021:                 <add namespace="System.Text.RegularExpressions"/>
    00022:                 <add namespace="System.Web"/>
    00023:                 <add namespace="System.Web.Caching"/>
    00024:                 <add namespace="System.Web.SessionState"/>
    00025:                 <add namespace="System.Web.Security"/>
    00026:                 <add namespace="System.Web.Profile"/>
    00027:                 <add namespace="System.Web.UI"/>
    00028:                 <add namespace="System.Web.UI.WebControls"/>
    00029:                 <add namespace="System.Web.UI.WebControls.WebParts"/>
    00030:                 <add namespace="System.Web.UI.HtmlControls"/>
    00031:             </namespaces>
    00032:         </pages>
    00033:     </system.web>
    00034: </configuration>
    

    И такая же простая, но важная страничка:

    00001: <%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default.aspx.vb" Inherits="Configure_Default"
    00002:     Theme="SkinFile" %>
    00003: 
    00004: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    00005: <html xmlns="http://www.w3.org/1999/xhtml">
    00006: <head id="Head1" runat="server">
    00007:     <title>ASP_Configure</title>
    00008: </head>
    00009: <body>
    00010:     <form id="form1" runat="server">
    00011:         <asp:Label ID="Label8" runat="server" Text="Вы вошли как : "></asp:Label>
    00012:         <asp:Label ID="L0" runat="server"></asp:Label><br />
    00013:         <asp:MultiView ID="MV1" runat="server" ActiveViewIndex="0">
    00014:             <asp:View ID="Anon" runat="server">
    00015:                 <asp:Label ID="Label9" runat="server" Text="Сорри, на эту страничку непозволительно заходить без Windows-аутентификации"></asp:Label>
    00016:                 <br />
    00017:                 <asp:Label ID="Label10" runat="server" Text="Для входа на эту страничку сконфигурируйте эту директорию как отдельный сайт и запретите вход сюда анонимам."></asp:Label>
    00018:                 <br />
    00019:                 <asp:Image ID="Image1" runat="server" ImageUrl="~/Configure.gif" />
    00020:                 <br />
    00021:                 <asp:Label runat="server" ID="Label12" Text="Проверьте в конфигурации этого файла наличие строки:"></asp:Label>
    00022:                 <br />
    00023:                 <asp:Image ID="Image2" runat="server" ImageUrl="Configure1.gif" />
    00024:                 <br />
    00025:                 <asp:Label ID="Label11" runat="server" Text="Это обязательные условия безопасности для запуска этой странички."></asp:Label>
    00026:             </asp:View>
    00027:             <asp:View ID="NotAnon" runat="server">
    00028:                 <div>
    00029:                     <asp:Label ID="Label1" runat="server" Text="На этой страничке производится конфигурирование администраторов сайта и занесение учетных данных администраторов в базу."></asp:Label>
    00030:                     <br /><br /><br />
    00031:                     <table>
    00032:                         <tr>
    00033:                             <td>
    00034:                                 <asp:Label ID="Label2" runat="server" Text="Логин администратора сайта"></asp:Label>
    00035:                             </td>
    00036:                             <td>
    00037:                                 <asp:TextBox ID="TextBox1" runat="server"></asp:TextBox></td>
    00038:                             <td>
    00039:                                 <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server" ErrorMessage="*"
    00040:                                     ControlToValidate="TextBox1"></asp:RequiredFieldValidator>
    00041:                             </td>
    00042:                         </tr>
    00043:                         <tr>
    00044:                             <td>
    00045:                                 <asp:Label ID="Label3" runat="server" Text="Пароль администратора сайта"></asp:Label></td>
    00046:                             <td>
    00047:                                 <asp:TextBox ID="TextBox2" runat="server" TextMode="Password"></asp:TextBox></td>
    00048:                             <td>
    00049:                                 <asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server" ErrorMessage="*"
    00050:                                     ControlToValidate="TextBox2"></asp:RequiredFieldValidator>
    00051:                             </td>
    00052:                         </tr>
    00053:                         <tr>
    00054:                             <td>
    00055:                                 <asp:Label ID="Label4" runat="server" Text="Пароль еще раз"></asp:Label>
    00056:                                 <asp:CompareValidator ID="CompareValidator1" runat="server" ControlToCompare="TextBox2"
    00057:                                     ControlToValidate="TextBox3" ErrorMessage="*"></asp:CompareValidator></td>
    00058:                             <td>
    00059:                                 <asp:TextBox ID="TextBox3" runat="server" TextMode="Password"></asp:TextBox></td>
    00060:                             <td>
    00061:                                 <asp:RequiredFieldValidator ID="RequiredFieldValidator3" runat="server" ErrorMessage="*"
    00062:                                     ControlToValidate="TextBox3"></asp:RequiredFieldValidator>
    00063:                             </td>
    00064:                         </tr>
    00065:                         <tr>
    00066:                             <td>
    00067:                                 <asp:Label ID="Label5" runat="server" Text="Email администратора сайта"></asp:Label>
    00068:                             </td>
    00069:                             <td>
    00070:                                 <asp:TextBox ID="TextBox4" runat="server"></asp:TextBox></td>
    00071:                             <td>
    00072:                                 <asp:RequiredFieldValidator ID="RequiredFieldValidator4" runat="server" ErrorMessage="*"
    00073:                                     ControlToValidate="TextBox4"></asp:RequiredFieldValidator>
    00074:                             </td>
    00075:                         </tr>
    00076:                         <tr>
    00077:                             <td>
    00078:                                 <asp:Label ID="Label7" runat="server" Text="Секретный вопрос админу для восстановления забытого пароля"></asp:Label>
    00079:                             </td>
    00080:                             <td>
    00081:                                 <asp:TextBox ID="TextBox5" runat="server"></asp:TextBox></td>
    00082:                             <td>
    00083:                                 <asp:RequiredFieldValidator ID="RequiredFieldValidator5" runat="server" ErrorMessage="*"
    00084:                                     ControlToValidate="TextBox5"></asp:RequiredFieldValidator>
    00085:                             </td>
    00086:                         </tr>
    00087:                         <tr>
    00088:                             <td>
    00089:                                 <asp:Label ID="Label6" runat="server" Text="Ответ"></asp:Label>
    00090:                             </td>
    00091:                             <td>
    00092:                                 <asp:TextBox ID="TextBox6" runat="server"></asp:TextBox></td>
    00093:                             <td>
    00094:                                 <asp:RequiredFieldValidator ID="RequiredFieldValidator6" runat="server" ErrorMessage="*"
    00095:                                     ControlToValidate="TextBox6"></asp:RequiredFieldValidator>
    00096:                             </td>
    00097:                         </tr>
    00098:                         <tr>
    00099:                             <td>
    00100:                                 <asp:Label ID="Label13" runat="server" Text="Администратор является членом предварительно сконфигурированной роли"></asp:Label>
    00101:                                 </td>
    00102:                             <td align="center">
    00103:                                 <asp:DropDownList ID="DropDownList1" runat="server" DataMember="DefaultView" DataSourceID="SqlDataSource1"
    00104:                                     DataTextField="RoleName" DataValueField="RoleName" Width="100%">
    00105:                                 </asp:DropDownList></td>
    00106:                             <td>
    00107:                             </td>
    00108:                         </tr>
    00109:                         <tr>
    00110:                             <td>
    00111:                                 <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:ConnStr %>"
    00112:                                     SelectCommand="exec dbo.aspnet_Roles_GetAllRoles @ApplicationName=N'/'">
    00113:                                     <SelectParameters>
    00114:                                         <asp:Parameter Name="ApplicationName" DefaultValue="/" />
    00115:                                     </SelectParameters>
    00116:                                 </asp:SqlDataSource>
    00117:                             </td>
    00118:                             <td align="center">
    00119:                                 <asp:Button ID="Button1" runat="server" Text="OK" Width="100px" /></td>
    00120:                             <td>
    00121:                             </td>
    00122:                         </tr>
    00123:                         <tr>
    00124:                             <td>
    00125:                                 <asp:Label ID="Err" runat="server" ForeColor="Red"></asp:Label></td>
    00126:                             <td align="center">
    00127:                             </td>
    00128:                             <td>
    00129:                             </td>
    00130:                         </tr>
    00131:                     </table>
    00132:                 </div>
    00133:             </asp:View>
    00134:         </asp:MultiView>
    00135:     </form>
    00136: </body>
    00137: </html>
    
    00001: Partial Class Configure_Default
    00002:     Inherits System.Web.UI.Page
    00003: 
    00004:     Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    00005:         If Not IsPostBack Then
    00006:             If System.Security.Principal.WindowsIdentity.GetCurrent.IsAuthenticated Then
    00007:                 L0.Text = System.Security.Principal.WindowsIdentity.GetCurrent.Name
    00008:                 If System.Security.Principal.WindowsIdentity.GetCurrent.IsAnonymous Then
    00009:                     MV1.SetActiveView(Anon)
    00010:                 Else
    00011:                     If System.Security.Principal.WindowsIdentity.GetCurrent.Name = "NT AUTHORITY\NETWORK SERVICE" Then
    00012:                         MV1.SetActiveView(Anon)
    00013:                     Else
    00014:                         MV1.SetActiveView(NotAnon)
    00015:                         Me.DataBind()
    00016:                     End If
    00017:                 End If
    00018:             Else
    00019:                 MV1.SetActiveView(Anon)
    00020:             End If
    00021:         End If
    00022:     End Sub
    00023: 
    00024:     Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
    00025:         Dim Result As MembershipCreateStatus
    00026:         Try
    00027:             Dim Admin As MembershipUser = Membership.CreateUser(TextBox1.Text, TextBox2.Text, TextBox4.Text, TextBox5.Text, TextBox6.Text, True, Result)
    00028:             If Admin Is Nothing Then
    00029:                 Err.Text = Result.ToString
    00030:             Else
    00031:                 Roles.AddUserToRole(TextBox1.Text, DropDownList1.Text)
    00032:                 Err.Text = "Новый администратор создан."
    00033:             End If
    00034:         Catch ex As Exception
    00035:             Err.Text = ex.Message
    00036:         End Try
    00037: 
    00038:     End Sub
    00039: End Class
    

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



    Comments ( )
    <00>  <01>  <02>  <03>  <04>  <05>  <06>  <07>  <08>  <09>  <10>  <11>  <12>  <13>  <14>  <15>  <16>  <17>  <18>  <19>  <20>  <21>  <22>  <23
    Link to this page: //www.vb-net.com/asp2/3/index.htm
    <SITEMAP>  <MVC>  <ASP>  <NET>  <DATA>  <KIOSK>  <FLEX>  <SQL>  <NOTES>  <LINUX>  <MONO>  <FREEWARE>  <DOCS>  <ENG>  <CHAT ME>  <ABOUT ME>  < THANKS ME>