Избавляемся от базы стандартных пользователей ASP.NET на MS SQL - пример ASP.NET сайта на MySQL.
MS SQL является тяжелейшим обременителем технологии ASP.NET. Я многократно разъяснял причины этого - повторятся не будем, интересующихся отсылаю к страничкам - Используем MySQL вместо MS SQL в проектах на ASP.NET, Программирование в SQL SERVER, Осторожно Microsoft. Вероятно, наличие именно этого безумно дорогого продукта в пакете технологий ASP.NET и приводит к тому, что эта неплохая в целом технология занимает всего 0,4% рынка Web-технологий.
Поэтому очевидно, что все что может интересовать на практике ASP.NET-программистов - это снижение стоимости их законченных ASP.NET-сайтов для конечных потребителей. В первую очередь путем избавления от немыслимо дорогого MS SQL-сервера и от Windows конечно тоже. Тем более конкурирующие бесплатные продукты не хуже, а лучше билогейтсовских. Просто их бренды не настолько раскрученные и их не навязывают детям на уроках дэз-информатики в школе. Да и навязывать и раскручивать бесплатные продукты особо некому - не то что шестерки Билла Гейтса с чемоданами баксов, проталкивающие Windows.
Собственно же ASP.NET-программирование c СУБД MySQL не требует хитростей типа сохранения коннекта (как это требуется в PostgreSQL - Этюды на ASP.NET. Пример сайта на СУБД PostgreSQL) - техника ASP-NET программирования с MySQL ничем не отличается от техники программирования с MS SQL. Поэтому я сделал этот пример не просто примером сайта с MySQL - а примером ASP.NET-сайта с отказом от стандартных пользователей ASP.NET, обычно устанавливаемых в MS SQL.
Описанное здесь решение является сильно упрощенной реализацией моего популярного коммерческого решения для управления ASP.NET-пользователями, описанного здесь AspNet_UserManager - компонент сайта для управления пользователями. Здесь, как вы понимаете все правильно - для платного микрософтовского MS SQL Server у меня рапространяется платное управления ASP.NET-пользователями, а для бесплатного MySQL аналогичное по функционалу решение - полностью OpenSource. Кроме того, платное решение включает в себя мою фирменную и пока никем не взломанную капчу и представляет собой просто библитеку, которую надо положить в BIN-директорию проекта и просто оплатить, а описанный на этой страничке OpenSource-проект - это конструктор, из которого вы сами должны выделить в свой проект нужные вам фрагменты кода.
Еще один пример использования MySQL вместо MS SQL вы можете посмотреть у меня на страничке Как сделать SOAP/WSDL-вебсервис на ASP.NET/MONO для вызова его из FLEX.
Итак, если призадуматься, то использование стандартных ASP.NET-пользователей (устанавливаемых обычно мастером aspnet_regsql.exe) непонятно что приносит больше - пользы или вреда:
- Трудно сконфигурировать многочисленные параметры Web-конфига, которым управляются стандартные пользователи. Это сотни параметров, вникать в которые никому не хочется. В результате на практике (при эксплуатации сайта) возникают непонятные проблемы в непонятном месте от того, что ASP.NET-девелоперы проявляют неуважение к своим потребителями и нагружают эксплуатационные службы горой каких-то плохоуправляемых микрософтовских помоев. Например юзер ввел четыре раза неверный пароль и почему-то заблокировался. Чтобы понять как его разблокировать - надо не только сделать сложные ручные манипуляции с базой, но и правильно поправить умалчиваемые настройки в конфиге. Но все дело в том, что там СОТНИ настроек. И ими все равное нельзя получить все, что хочешь. Получается, что ты пользуешься неуправляемой пирамидой чужого и ненужного кода. И делаешь это фактически из хулиганских побуждений - ибо всю эту пирамиду можно легко заменить десятью строчками собственного кода, которые будут перед глазами суппорта и будут делать конкретно то, что требуется в данном проекте.
- Стандартные ASP-NET профили сделаны вообще адски. С нарушением всех мыслимых законов нормализации данных. Похоже микрософтовские индусы просто не слышали о нормализации данных. Отбирать что-то по данным профилям на уровне SQL можно только собственными CLR-сборками. Что еще глубже затягивает вас в пучину микрософтовских технологий, ибо те же сборки невозможно сделать на MySQL - только на MS SQL. Который работает только на Windows. Подробнее эту тему с профилями я осветил здесь - Сборка для работы с данными стандартных ASP.NET-профилей на уровне SQL.
- Микрософтовские индусы провели границу между стандартным повторяющимся из-проекта в проект кодом и меняющимся кодом не там, где это нужно. Эта граница выглядит как пакт Молотова-Рибентропа, проведенный по Волге. Они не включили в повторяющийся код активацию логина с использованием указанного почтового адреса пользователя - зато включили в стандартный код горы всякой ерунды, (параметры управления которой вы можете видеть в web.config) и кучу еще более глупых web-контролов. В описанном ниже решении я проведу границу между стандартным, повторяющимся из проекта в проект кодом иначе, чем его проводит микрософт.
Итак, вы выполнили инсталяцию MySQL, установили коннектор к MySQL - как это описано на этой моей страничке Используем MySQL вместо MS SQL в проектах на ASP.NET. Скопировали MySql.Data.dll в папку BIN проекта и лучше даже прописали его в Mashine.config (это должен автоматически сделать инсталятор коннектора).
MySQL Connector Net состоит с точки зрения .NET-программиста из четырех компонентов:
- MySql.Data.dll - доступ к MySQL из .NET и ASP.NET
- MySql.Data.Entity.dll - работа с LINQ
- MySql.Data.CF.dll - общее определение типов
- MySql.Web.dll - работа с профилями и встроенными пользователями ASP.NET
Последняя сборка как раз и предназначена для тех, кто не хотел бы отказываться от стандартных пользователей в базах aspnet_users, aspnet_membership, считывания/записи пользователей из этих баз с помощью заведомо сделанной микрософтом обвязки Membership.GetUser/Membership.Save. А также сохранения/загрузки профиля ASP.NET пользователя с помощью встроенных микрософтовских классов UserProfile.GetProfile и UserProfile.Save.
Теперь посмотрим, как программистам, травмированным Microsoft Sql Server, создать юзера release для работы сайта, назначить ему нужные права, создать базу release и необходимую структуру данных в ней. Те, чей мозг не травмирован Microsoft SQL Server - могут этот раздел пропустить.
При инсталяции MySQL вы указывали пароль MySQL-юзера root и возможно ставили галку анонимного доступа к MySQL. Теперь (последовательно) приконнектитесь к вашему MySQL из под root, создайте себе базу для сайта, создайте юзера для работы сайта и поставьте ему доступ по чтению на базу MySQL и полный доступ на свою базу:
Далее необходимо переконнектится к серверу уже из-под вновь созданного юзера и начать создавать нужную структуру таблиц в базе:
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
Эту структуру (если она будет меняться в вашем проекте) вы можете в любой момент заскриптовать и сохранить в тектовом виде в своем SQL-проекте (см скрины ниже). Кроме того, при работе с MySQL под Windows важно правильно выставить во всех местах кодировку UTF-8 - иначе будет бесконечная чехарда с русскими буквами. В студии DevArt (если вы будете что-то править руками в таблицах и хотете там видеть русский текст, а не абракадабру) - это ставится в свойствах коннекта. А для работы сайта я просто добавляю в конфигурационном файле MySQL.ini команду SET NAMES utf8 (на скринах вы видите куда это вписывается). Кроме того, как вы видите на скринах - я сделал скриптик для рестарта MySQL и указал файл журнала для профилирования SQL-запросов (в журнале видно, как я из админки забанил какого-то юзера).
![]() |
![]() |
![]() |
![]() |
![]() |
Для учета пользователей нашего сайта мы создадим следующую структуру таблиц и процедур:
1: -- Скрипт сгенерирован Devart dbForge Studio for MySQL, Версия 4.50.285.1
2: -- Дата: 19/07/2010 23:10:21
3: -- Версия сервера: 5.1.48-community
4: -- Версия клиента: 4.1
5:
6: USE release;
7:
8: CREATE TABLE release.aspnet_users(
9: i INT(12) NOT NULL AUTO_INCREMENT,
10: id VARCHAR(36),
11: Email VARCHAR(50) NOT NULL,
12: Pass VARCHAR(50) NOT NULL,
13: ActivateID VARCHAR(36) NOT NULL,
14: IsActivate TINYINT(1) DEFAULT NULL,
15: CrDate DATETIME NOT NULL,
16: UserName VARCHAR(50) NOT NULL,
17: Name1 VARCHAR(50) DEFAULT NULL,
18: Name2 VARCHAR(50) DEFAULT NULL,
19: IP VARCHAR(16) NOT NULL,
20: IsAdmin TINYINT(1) DEFAULT NULL,
21: IsBan TINYINT(1) DEFAULT NULL,
22: PRIMARY KEY (i, id),
23: UNIQUE INDEX ActivateID (ActivateID),
24: UNIQUE INDEX Email (Email)
25: )
26: ENGINE = INNODB
27: AUTO_INCREMENT = 28
28: AVG_ROW_LENGTH = 16384
29: CHARACTER SET utf8
30: COLLATE utf8_general_ci;
31:
32: CREATE TABLE release.sendmail(
33: i INT(12) NOT NULL AUTO_INCREMENT,
34: CrDate DATETIME NOT NULL,
35: ToAddr VARCHAR(250) NOT NULL,
36: MailSubject VARCHAR(500) NOT NULL,
37: Body VARCHAR(4000) DEFAULT NULL,
38: SendError TINYINT(1) DEFAULT NULL,
39: PRIMARY KEY (i)
40: )
41: ENGINE = INNODB
42: AUTO_INCREMENT = 18
43: CHARACTER SET utf8
44: COLLATE utf8_general_ci;
45:
46: DELIMITER $$
47:
48: CREATE DEFINER = 'release'@'%'
49: PROCEDURE release.AddMail(IN ToAddr VARCHAR(256), IN MailSubject VARCHAR(500), IN Body VARCHAR(4000))
50: BEGIN
51: START TRANSACTION;
52: INSERT
53: release.sendmail (CrDate, ToAddr, MailSubject, Body) VALUES (NOW(), ToAddr, MailSubject, Body);
54: SELECT
55: LAST_INSERT_ID() AS MailId;
56: COMMIT;
57: END
58: $$
59:
60: CREATE DEFINER = 'release'@'%'
61: PROCEDURE release.AddMailError(IN i1 INTEGER, IN SendError1 VARCHAR(1000))
62: BEGIN
63: UPDATE
64: release.sendmail
65: SET
66: SendError = SendError1
67: WHERE
68: i = i1;
69: END
70: $$
71:
72: CREATE DEFINER = 'release'@'%'
73: PROCEDURE release.ClearAllUserInfo(IN id1 VARCHAR(36))
74: BEGIN
75: DECLARE EXIT HANDLER FOR SQLEXCEPTION
76: BEGIN
77: SELECT
78: mysql_error() AS Error_message;
79: END;
80:
81: DELETE
82: FROM
83: release.aspnet_users
84: WHERE
85: id = id1;
86: SELECT
87: NULL AS Error_Number;
88: END
89: $$
90:
91: CREATE DEFINER = 'release'@'%'
92: PROCEDURE release.CreateUser(IN Email VARCHAR(50), IN Pass VARCHAR(50), IN UserName VARCHAR(50), IN Name1 VARCHAR(50), IN Name2 VARCHAR(50), IN IP VARCHAR(16))
93: BEGIN
94: START TRANSACTION;
95: INSERT
96: release.aspnet_users (id, Email, Pass, ActivateID, IsActivate, CrDate, UserName, Name1, Name2, IP, IsAdmin) VALUES (release.StrongGuid(), Email, Pass, release.StrongGuid(), FALSE, NOW(), UserName, Name1, Name2, IP, FALSE);
97: SELECT
98: *
99: FROM
100: release.aspnet_users
101: WHERE
102: i = LAST_INSERT_ID();
103: COMMIT;
104: END
105: $$
106:
107: CREATE DEFINER = 'release'@'%'
108: FUNCTION release.StrongGuid()
109: RETURNS CHAR(36) CHARSET utf8
110: BEGIN
111: DECLARE MD5_hash CHAR(32);
112:
113: SET MD5_hash = MD5(UUID());
114: RETURN CONCAT(
115: SUBSTRING(MD5_hash, 1, 8),
116: '-',
117: SUBSTRING(MD5_hash, 9, 4),
118: '-',
119: SUBSTRING(MD5_hash, 13, 4),
120: '-',
121: SUBSTRING(MD5_hash, 17, 4),
122: '-',
123: SUBSTRING(MD5_hash, 21, 12));
124: END
125: $$
126:
127: DELIMITER ;
Как видите, в этой структуре нет ничего необычного - табличко aspnet_users для учета пользователей, табличко sendmail для учета отправленных писем, табличко audio для работы моего сайтика. Процедурко AddMail для отправки писем и AddMailError для фиксации опибиок при отправке писем, процедурко CreateUser для создания пользователей и ClearAllUserInfo для удаления пользователей. Процедурко CreateAudio для работы моего сайтика и фнукиця StrongGuid для генерации строгого GUID.
Обратите также внимание на имена пользователей - они самодокументируемые в MySQL - после знака @ у них указывается хост - с которого можно входить в MySQL - если % - то с любого.
Теперь посмотрим как правильно сконфигурировать конфиг проекта. Для NET 3.5 полный конфиг проекта будет выглядеть вот так:
1: <?xml version="1.0"?>
2: <configuration>
3: <configSections>
4: <sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
5: <sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
6: <section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
7: <sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
8: <section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="Everywhere"/>
9: <section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
10: <section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
11: <section name="roleService" type="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication"/>
12: </sectionGroup>
13: </sectionGroup>
14: </sectionGroup>
15: </configSections>
16: <appSettings>
17: <!-- Этот адрес нужен для активации логина -->
18: <add key="HostingURL" value="release.asp-net.ru"/>
19: <add key="NameURL" value="release.ru"/>
20: <add key="AdminURL" value="release-admin.asp-net.ru"/>
21: <!-- Доступ к почтовому серверу -->
22: <add key="SMTP_FromAddr" value="[email protected]"/>
23: <add key="SMTP_Server" value="XXX.XXX.XXX.XXX"/>
24: <add key="SMTP_Port" value="125"/>
25: <add key="SMTP_Login" value="[email protected]"/>
26: <add key="SMTP_Pass" value="XXXXXXXXXXXXXXX"/>
27: <!-- Реквизиты главного неудаляемого админа сайта -->
28: <add key="Admin_Login" value="release"/>
29: <add key="Admin_Pass" value="XXXXXXXXXXXXXXX"/>
30: <add key="Admin_Mail" value="[email protected]"/>
31: </appSettings>
32: <connectionStrings>
33: <add name="MySQLConnectionString" connectionString="Server=release.asp-net.ru;Database=release;User ID=release;Password=XXXXXXXXXX;Connection Timeout=2;Max Pool Size=500;" providerName="MySql.Data.MySqlClient"/>
34: </connectionStrings>
35: <system.web>
36: <compilation debug="true" strict="false" explicit="true">
37: <assemblies>
38: <add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
39: <add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
40: <add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
41: <add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
42: <add assembly="MySql.Data, Version=6.2.2.0, Culture=neutral, PublicKeyToken=C5687FC88969C44D"/>
43: <add assembly="MySql.Web, Version=6.2.2.0, Culture=neutral, PublicKeyToken=C5687FC88969C44D"/>
44: </assemblies>
45: </compilation>
46: <pages>
47: <namespaces>
48: <clear/>
49: <add namespace="System"/>
50: <add namespace="System.Collections"/>
51: <add namespace="System.Collections.Generic"/>
52: <add namespace="System.Collections.Specialized"/>
53: <add namespace="System.Configuration"/>
54: <add namespace="System.Text"/>
55: <add namespace="System.Text.RegularExpressions"/>
56: <add namespace="System.Linq"/>
57: <add namespace="System.Xml.Linq"/>
58: <add namespace="System.Web"/>
59: <add namespace="System.Web.Caching"/>
60: <add namespace="System.Web.SessionState"/>
61: <add namespace="System.Web.Security"/>
62: <add namespace="System.Web.Profile"/>
63: <add namespace="System.Web.UI"/>
64: <add namespace="System.Web.UI.WebControls"/>
65: <add namespace="System.Web.UI.WebControls.WebParts"/>
66: <add namespace="System.Web.UI.HtmlControls"/>
67: </namespaces>
68: <controls>
69: <add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
70: <add tagPrefix="asp" namespace="System.Web.UI.WebControls" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
71: </controls>
72: </pages>
73: <authentication mode="Forms"/>
74: <httpHandlers>
75: <remove verb="*" path="*.asmx"/>
76: <add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
77: <add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
78: <add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" validate="false"/>
79: </httpHandlers>
80: <httpModules>
81: <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
82: </httpModules>
83: </system.web>
84: <system.codedom>
85: <compilers>
86: <compiler language="c#;cs;csharp" extension=".cs" warningLevel="4" type="Microsoft.CSharp.CSharpCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
87: <providerOption name="CompilerVersion" value="v3.5"/>
88: <providerOption name="WarnAsError" value="false"/>
89: </compiler>
90: <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" warningLevel="4" type="Microsoft.VisualBasic.VBCodeProvider, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
91: <providerOption name="CompilerVersion" value="v3.5"/>
92: <providerOption name="OptionInfer" value="true"/>
93: <providerOption name="WarnAsError" value="false"/>
94: </compiler>
95: </compilers>
96: </system.codedom>
97: <!--
98: The system.webServer section is required for running ASP.NET AJAX under Internet
99: Information Services 7.0. It is not necessary for previous version of IIS.
100: -->
101: <system.webServer>
102: <validation validateIntegratedModeConfiguration="false"/>
103: <modules>
104: <remove name="ScriptModule"/>
105: <add name="ScriptModule" preCondition="managedHandler" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
106: </modules>
107: <handlers>
108: <remove name="WebServiceHandlerFactory-Integrated"/>
109: <remove name="ScriptHandlerFactory"/>
110: <remove name="ScriptHandlerFactoryAppServices"/>
111: <remove name="ScriptResource"/>
112: <add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
113: <add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
114: <add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
115: </handlers>
116: </system.webServer>
117: <runtime>
118: <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
119: <dependentAssembly>
120: <assemblyIdentity name="System.Web.Extensions" publicKeyToken="31bf3856ad364e35"/>
121: <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/>
122: </dependentAssembly>
123: <dependentAssembly>
124: <assemblyIdentity name="System.Web.Extensions.Design" publicKeyToken="31bf3856ad364e35"/>
125: <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/>
126: </dependentAssembly>
127: </assemblyBinding>
128: </runtime>
129: </configuration>
Это совершенно стандартный конфиг ASP.NEt 3.5 за исключением параметров, которые я внес в секцию <appSettings> и параметров коннекта серверу MySQL - которые опять же совершенно понятны, возможно за исключением параметра Timeout=2, который означает время жизни SQL-запроса в сервере MySQL. Это достаточно важный параметр, если его не закрутить в минимум, то пул коннектов коннектов в MySQL (максимальное количество которых установлено в конфиге) мгновенно исчерпается.
Теперь перейдем к коду сайта. Он будет состоять из пяти компонентов, доступных пользователю и трех компонентов админки. Публичная часть сайта будет состоять из контрола для регистрации left.ascx, странички для регистрации Register.aspx, странички ожидания подтверждения регистрации Pending.aspx, странички активации логина ActivateLogin.aspx и странички напоминания пароля RestorePass.aspx.
Итак, в некотором месте моего проекта (в контроле, размещенном на master.page) лежил код разметки для логина в сайт (в данном случае это контрол left.ascx):
![](/MySQL_ASPNET_Users/Login.gif)
1: <asp:Panel ID="Panel1" runat="server">
2: <table border="0" cellpadding="0" cellspacing="0" style="width: 250px; vertical-align: top;
3: text-align: left">
4: <tr>
5: <td>
6: <asp:TextBox ID="txLogin" runat="server" Width="150px"></asp:TextBox>
7: <asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server" ControlToValidate="txLogin"
8: ErrorMessage="*" ValidationGroup="Login"></asp:RequiredFieldValidator>
9: </td>
10: <td rowspan="2">
11: <asp:ImageButton ID="btLogin" runat="server" ImageUrl="~/Image/Login.png" ValidationGroup="Login" />
12: <asp:Label ID="Lerr1" runat="server" ForeColor="Red"></asp:Label>
13: </td>
14: </tr>
15: <tr>
16: <td>
17: <asp:TextBox ID="txPass" runat="server" Width="150px"></asp:TextBox>
18: <asp:RequiredFieldValidator ID="RequiredFieldValidator3" runat="server" ControlToValidate="txPass"
19: ErrorMessage="*" ValidationGroup="Login"></asp:RequiredFieldValidator>
20: </td>
21: <td>
22: </td>
23: </tr>
24: <tr style="height: 10px">
25: <td>
26: </td>
27: <td>
28: </td>
29: </tr>
30: <tr>
31: <td>
32: <asp:HyperLink ID="ForgotPass" runat="server" ForeColor="White" Font-Names="Segoe UI"
33: Font-Size="12px" NavigateUrl="~/RestorePass.aspx">Forgot our password</asp:HyperLink>
34: </td>
35: <td>
36: </td>
37: </tr>
38: <tr>
39: <td>
40: <asp:HyperLink ID="CreateAccount" runat="server" ForeColor="White" Font-Names="Segoe UI"
41: Font-Size="12px" NavigateUrl="~/Register.aspx">Create new account</asp:HyperLink>
42: </td>
43: <td>
44: </td>
45: </tr>
46: </table>
47: </asp:Panel>
48: <asp:Panel ID="Panel2" runat="server">
49: <asp:HyperLink ID="CabLink1" runat="server" ForeColor="White" Font-Names="Segoe UI"
50: Font-Size="12px" ></asp:HyperLink>
51: <br />
52: <asp:LinkButton ID="LogoutButton1" runat="server" ForeColor="White" Font-Names="Segoe UI"
53: Font-Size="12px">Logout</asp:LinkButton>
54:
55: <asp:LinkButton ID="AdminButton1" runat="server" ForeColor="White" Font-Names="Segoe UI"
56: Font-Size="12px">Admin</asp:LinkButton>
57:
58: <div style="height:63px"/>
59: </asp:Panel>
Как видите, контрол логина состоит из двух панелей, которые переключаются в зависимости от того, залогинен юзер или нет. А код контрола залогинивания выглядит вот так:
1: Partial Class Left
2: Inherits System.Web.UI.UserControl
3:
4: Protected Sub Left_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
5: If Not IsPostBack Then
6: If HttpContext.Current.User.Identity.IsAuthenticated Then
7: Panel1.Visible = False
8: Panel2.Visible = True
9: CabLink1.Text = CType(Me.Page, BasePage).User_UserName
10: CabLink1.NavigateUrl = "Cab.aspx?user=" & CType(Me.Page, BasePage).User_id
11: If CType(Me.Page, BasePage).User_IsAdmin Then
12: AdminButton1.Visible = True
13: AdminButton1.PostBackUrl = "http://" & System.Configuration.ConfigurationManager.AppSettings("AdminURL").ToString
14: Else
15: AdminButton1.Visible = False
16: End If
17: Else
18: Panel1.Visible = True
19: Panel2.Visible = False
20: End If
21: End If
22: End Sub
23:
24:
25: Protected Sub btLogin_Click(ByVal sender As Object, ByVal e As System.Web.UI.ImageClickEventArgs) Handles btLogin.Click
26: Try
27: Dim GetOneUser As New ExecMySQL_RDR("UserName", txLogin.Text)
28: Dim DR1 As MySql.Data.MySqlClient.MySqlDataReader = GetOneUser.ExecMySQL("select * from releasebeat.aspnet_users where UserName=@UserName", Data.CommandType.Text)
29: If DR1.Read Then
30: If DR1("Pass") = txPass.Text Then
31: FormsAuthentication.SetAuthCookie(txLogin.Text, True)
32: Panel1.Visible = False
33: Panel2.Visible = True
34: CabLink1.Text = DR1("UserName")
35: CabLink1.NavigateUrl = "Cab.aspx?user=" & DR1("id")
36: If DR1("IsAdmin") Then
37: AdminButton1.Visible = True
38: AdminButton1.PostBackUrl = "http://" & System.Configuration.ConfigurationManager.AppSettings("AdminURL").ToString
39: Else
40: AdminButton1.Visible = False
41: End If
42: If Not DR1("IsActivate") Then
43: Panel1.Visible = False
44: Panel2.Visible = True
45: Response.Redirect("Pending.aspx")
46: End If
47: End If
48: End If
49: Lerr1.Text = ""
50: Catch ex As Exception
51: Lerr1.Text = ex.Message
52: End Try
53: End Sub
54:
55: Protected Sub LinkButton1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles LogoutButton1.Click
56: FormsAuthentication.SignOut()
57: Panel1.Visible = True
58: Panel2.Visible = False
59: End Sub
60:
61: End Class
Как видите, это совершенно тривиальный код обращения в базу и проверки - есть ли там нужный нам юзер. Обратите внимание, что обращение в базу производится с помощью моей ADO.NET обвязка для работы с MySQL в ASP.NET-сайтах под Windows.
Как я уже говорил, я провожу границу стандартного и нестандартного кода каждого сайта не там, где ее проводит микрософт. Для меня это обязательно капча при регистрации и письмо об активации. Для микрософта это что-то совершенно иное - тмпо их убогих активационных контролов. Поэтому мой следующий фрагмент стандартного ASP-NET сайта - это страничка регистрации Register.aspx, высылающая активационные письма. Ссылка на эту страничку стоит в контроле залогинивания, а в страничке регистрации есть фрагмент с полями, которые должен заполнить юзер, главное из которых его Email-адрес:
1: <table cellpadding="0" cellspacing="0" border="0" style="display: inline">
2: <tr>
3: <td>
4: <asp:Label ID="lblNewError" runat="server" Visible="false" CssClass="error" Text="You have entered incorrect login or password."></asp:Label>
5: <br />
6: <div class="form">
7: Please fill in the form to create a new account.<br />
8: <span>First Name:</span>
9: <asp:RequiredFieldValidator ID="RequiredFieldValidator1" runat="server"
10: ErrorMessage="*" ControlToValidate="tbxFirstName" ValidationGroup="Create1"></asp:RequiredFieldValidator>
11: <asp:TextBox ID="tbxFirstName" runat="server"></asp:TextBox><br />
12: <br />
13: <span>Last Name:</span>
14: <asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server"
15: ErrorMessage="*" ControlToValidate="tbxLastName" ValidationGroup="Create1"></asp:RequiredFieldValidator>
16: <asp:TextBox ID="tbxLastName" runat="server"></asp:TextBox><br />
17: <br />
18: <span>Login:</span>
19: <asp:RequiredFieldValidator ID="RequiredFieldValidator3" runat="server"
20: ErrorMessage="*" ControlToValidate="tbxNewLogin" ValidationGroup="Create1"></asp:RequiredFieldValidator>
21: <asp:TextBox ID="tbxNewLogin" runat="server"></asp:TextBox><br />
22: <br />
23: <span>Password:</span>
24: <asp:RequiredFieldValidator ID="RequiredFieldValidator4" runat="server"
25: ErrorMessage="*" ControlToValidate="tbxNewPassword" ValidationGroup="Create1"></asp:RequiredFieldValidator>
26: <asp:TextBox ID="tbxNewPassword" runat="server" TextMode="Password"></asp:TextBox><br />
27: <br />
28: <span>Email:</span>
29: <asp:RequiredFieldValidator ID="RequiredFieldValidator5" runat="server"
30: ErrorMessage="*" ControlToValidate="tbxNewEmail" ValidationGroup="Create1"></asp:RequiredFieldValidator>
31: <asp:TextBox ID="tbxNewEmail" runat="server"></asp:TextBox><br />
32: <br />
33: <span>I agree with the terms<asp:CheckBox ID="cbxAgree" runat="server"></asp:CheckBox></span><br />
34: <br />
35: <div class="agreement">
36: According to author's right all materials which presented on <b>releasebeat.ru</b>
37: website are presented for advertising and acquaintance purposes and shouldn't be
38: used for further coping public presentation. Otherwise you should take personal
39: responsibility for illegal coping of materials. After downloading mp-3 files you
40: must buy the licensed product of the author you prefer.<br />
41: <br />
42: </div>
43: * all fields are obligatory<br />
44: <br />
45: </div>
46: <asp:Button ID="btnCreate" runat="server" CssClass="button" Text="Create" ValidationGroup="Create1" />
47: </td>
48: </tr>
49: </table>
Как я уже говорил, моя капча в ее нынешнем виде не является OpenSource-кодом - это элемент защиты сайта от взлома и такие вещи, которые могут нанести ущерб моим партнерам и заказчикам - я не публикую. Поэтому этот OpenSource-код побликуется без капчи - хотя в нормальном сайте регисрации без кампчи конечно быть не может. (моя капча входит в состав моего решения AspNet_UserManager - компонент сайта для управления пользователями).
Код странички регистрации выглядит вот так:
1: Partial Class Register
2: Inherits BasePage
3:
4: Protected Sub CreateCommand(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnCreate.Click
5: Dim UserID As String, ActivateID As String
6: Try
7: CreateUser.SelectParameters("Email").DefaultValue = tbxNewEmail.Text
8: CreateUser.SelectParameters("Pass").DefaultValue = tbxNewPassword.Text
9: CreateUser.SelectParameters("UserName").DefaultValue = tbxNewLogin.Text
10: CreateUser.SelectParameters("Name1").DefaultValue = tbxFirstName.Text
11: CreateUser.SelectParameters("Name2").DefaultValue = tbxLastName.Text
12: CreateUser.SelectParameters("IP").DefaultValue = HttpContext.Current.Request.UserHostAddress
13: Dim DV1 As Data.DataView = CreateUser.Select(New DataSourceSelectArguments)
14: If DV1 IsNot Nothing Then
15: If DV1.Count > 0 Then
16: UserID = DV1(0)("ID")
17: ActivateID = DV1(0)("ActivateID")
18: Else
19: lblNewError.Visible = True
20: lblNewError.Text = "CreateUser Error 1"
21: Exit Sub
22: End If
23: Else
24: lblNewError.Visible = True
25: lblNewError.Text = "CreateUser Error 2"
26: Exit Sub
27: End If
28: Catch ex1 As MySql.Data.MySqlClient.MySqlException
29: If ex1.Message.StartsWith("Duplicate entry") Then
30: lblNewError.Visible = True
31: lblNewError.Text = "Такой пользователь уже зарегистрирован"
32: Exit Sub
33: Else
34: lblNewError.Visible = True
35: lblNewError.Text = "CreateUser Error" & vbCrLf & ex1.Message
36: Exit Sub
37: End If
38: Catch ex As Exception
39: lblNewError.Visible = True
40: lblNewError.Text = "CreateUser Error" & vbCrLf & ex.Message
41: Exit Sub
42: End Try
43: '
44: Try
45: FormsAuthentication.SetAuthCookie(tbxNewEmail.Text, True)
46: '
47: 'признак аутентификации для клиентского скрипта
48: Dim AU_Cook As New HttpCookie("AU")
49: AU_Cook.Item("U") = 1
50: Catch ex As Exception
51: lblNewError.Visible = True
52: lblNewError.Text = "Cookie Error" & vbCrLf & ex.Message
53: Exit Sub
54: End Try
55: '
56: Try
57: 'и отправляем мыло для активации логина
58: 'тут тоже возможен баг - SendMail_Error: Mailbox unavailable. The server response was: non-local recipient verification failed
59: Mail1.SendMail(tbxNewEmail.Text, "Активация логина " & System.Configuration.ConfigurationManager.AppSettings("NameURL"), "<html><body>Здравствуйте, " & tbxNewLogin.Text & " <br><br>Добро пожаловать на сайт " & System.Configuration.ConfigurationManager.AppSettings("NameURL") & " <br><br>Параметры вашей учётной записи таковы: " & _
60: "<br><br><b>Логин:</b>" & tbxNewLogin.Text & _
61: "<br><br><b>Пароль:</b> " & tbxNewPassword.Text & _
62: "<br><br>Ваша учётная запись ещё не активна. Вы не сможете ей пользоваться, пока не перейдёте по следующей ссылке:" & _
63: "<br><a href=""http://" & System.Configuration.ConfigurationManager.AppSettings("HostingURL") & "/ActivateLogin.aspx?i=" & UserID & "&j=" & ActivateID & """> http://" & System.Configuration.ConfigurationManager.AppSettings("HostingURL") & "/ActivateLogin.aspx?i=" & UserID & "&j=" & ActivateID & "</a><br>" & _
64: "<br><br>Если указанная выше ссылка не открывается, скопируйте ее в буфер обмена, вставьте в адресную строку браузера и нажмите ввод." & _
65: "<br><br>Желаем Вам удобного, приятного общения и хорошего отдыха!" & _
66: "<br><br>Если данное письмо послано Вам ошибочно, то проигнорируйте его и все данные будут автоматически удалены." & _
67: "<br><br>___________________<br>C уважением,<br> Администрация <a href='http://" & System.Configuration.ConfigurationManager.AppSettings("HostingURL") & "'>" & System.Configuration.ConfigurationManager.AppSettings("NameURL") & "</a></body></html>")
68: System.Web.Security.FormsAuthentication.RedirectFromLoginPage(tbxNewEmail.Text, True)
69: Response.Redirect("Pending.aspx")
70: Catch ex As Exception
71: Response.Redirect("Pending.aspx?txt=" & "Ошибка, пользователь создан, но из-за почтовых проблем сообщение для активации не отправлено. Попробуйте повторно выслать письмо активации из кабинета пользователя." & ex.Message)
72: End Try
73: End Sub
74: End Class
Эта страничка рассылает вот такие письма об активации.
![](/MySQL_ASPNET_Users/SendMail.gif)
Теперь нам потребуется еще страничка ожидания Pending.aspx, куда юзер попадает после регистрации. Она тоже состоит из двух панелей (в зависимости есть кука залогиненного юзера или нет) и кнопки повторения посылки активационного письма:
1: <asp:Content ID="Content3" ContentPlaceHolderID="RightPlaceHolder2" runat="Server">
2: <table cellpadding="0" cellspacing="0" border="0" style="display: inline">
3: <tr>
4: <td>
5: <asp:Panel ID="Panel1" runat="server">
6: <asp:Label ID="Label1" runat="server">Вам выслано письмо об активации.<br>
7: Пока вы не активируете свой логин - работа с сайтом невозможна.<br />
8: Вы можете выслать повторно письмо об активации, однако несколько одинаковых писем<br />
9: могут привести к полной блокировке отправителя на вашем почтовом сервере.<br />
10: Если письма об активации не доходят совершенно, попробуйте зарегистрироваться еще раз<br />
11: с почтовым ящиков на другом почтовом сервере.</asp:Label>
12: <br />
13: <br />
14: <asp:LinkButton ID="LinkButton1" runat="server">Выслать письмо для активации повторно</asp:LinkButton>
15: </asp:Panel>
16: <asp:Panel ID="Panel2" runat="server">
17: <asp:ImageButton ID="ImageButton1" runat="server" ImageUrl="Image/Logo.png" />
18: </asp:Panel>
19: <asp:Label ID="Lerr1" runat="server" ForeColor="Red"></asp:Label>
20:
21: </td>
22: </tr>
23: </table>
24: <asp:SqlDataSource ID="GetOneUser" runat="server" ConnectionString="<%$ ConnectionStrings:MySQLConnectionString %>"
25: ProviderName="<%$ ConnectionStrings:MySQLConnectionString.ProviderName %>"
26: SelectCommand="select * from releasebeat.aspnet_users where email=@Email;">
27: <SelectParameters>
28: <asp:Parameter Name="Email" Type="String" />
29: </SelectParameters>
30: </asp:SqlDataSource>
31: </asp:Content>
Код странички Pending.aspx такой:
1: Partial Class Pending
2: Inherits BasePage
3:
4: Protected Sub Pending_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
5: If Not IsPostBack Then
6: If HttpContext.Current.User.Identity.IsAuthenticated Then
7: Panel1.Visible = True
8: Panel2.Visible = False
9: Else
10: Panel1.Visible = False
11: Panel2.Visible = True
12: End If
13: End If
14: End Sub
15:
16: Protected Sub LinkButton1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles LinkButton1.Click
17: Try
18: GetOneUser.SelectParameters("Email").DefaultValue = "[email protected]" 'HttpContext.Current.User.Identity.Name"
19: Dim Dv1 As Data.DataView = GetOneUser.Select(New DataSourceSelectArguments)
20: If Dv1 IsNot Nothing Then
21: If Dv1.Count > 0 Then
22: Try
23: Mail1.SendMail(Dv1(0)("Email"), "Активация логина " & System.Configuration.ConfigurationManager.AppSettings("NameURL"), "<html><body>Здравствуйте, " & Dv1(0)("UserName") & " <br><br>Добро пожаловать на сайт " & System.Configuration.ConfigurationManager.AppSettings("NameURL") & " <br><br>Параметры вашей учётной записи таковы: " & _
24: "<br><br><b>Логин:</b>" & Dv1(0)("UserName") & _
25: "<br><br><b>Пароль:</b> " & Dv1(0)("Pass") & _
26: "<br><br>Ваша учётная запись ещё не активна. Вы не сможете ей пользоваться, пока не перейдёте по следующей ссылке:" & _
27: "<br><a href=""http://" & System.Configuration.ConfigurationManager.AppSettings("HostingURL") & "/ActivateLogin.aspx?i=" & Dv1(0)("id") & "&j=" & Dv1(0)("ActivateID") & """> http://" & System.Configuration.ConfigurationManager.AppSettings("HostingURL") & "/ActivateLogin.aspx?i=" & Dv1(0)("id") & "&j=" & Dv1(0)("ActivateID") & "</a><br>" & _
28: "<br><br>Если указанная выше ссылка не открывается, скопируйте ее в буфер обмена, вставьте в адресную строку браузера и нажмите ввод." & _
29: "<br><br>Желаем Вам удобного, приятного общения и хорошего отдыха!" & _
30: "<br><br>Если данное письмо послано Вам ошибочно, то проигнорируйте его и все данные будут автоматически удалены." & _
31: "<br><br>___________________<br>C уважением,<br> Администрация <a href='http://" & System.Configuration.ConfigurationManager.AppSettings("HostingURL") & "'>" & System.Configuration.ConfigurationManager.AppSettings("NameURL") & "</a></body></html>")
32: Catch ex As Exception
33: Lerr1.Text = "SendMail Error. " & vbCrLf & ex.Message
34: End Try
35: Else
36: Lerr1.Text = "Error 1"
37: End If
38: Else
39: Lerr1.Text = "Error 2"
40: End If
41: Catch ex As Exception
42: Lerr1.Text = "Error. " & vbCrLf & ex.Message
43: End Try
44: End Sub
45:
46:
47: End Class
Эти странички рассылают письма с помощью вот такой небольшой обвязки вокруг класса MailClient, который ведет журнал рассылки активационных писем в базе MySQL:
1: Imports Microsoft.VisualBasic
2: Imports System, System.Web
3:
4: Public Class Mail1
5: Public Shared Sub SendMail(ByVal ToAddr As String, ByVal Subject As String, ByVal Body As String)
6: Dim SendedMailID As Integer
7: Dim AddMail As New ExecMySQL_RDR("ToAddr", ToAddr, "MailSubject", Subject, "Body", Body)
8: Dim DR1 As MySql.Data.MySqlClient.MySqlDataReader = AddMail.ExecMySQL("AddMail", Data.CommandType.StoredProcedure)
9: If DR1.Read Then
10: SendedMailID = DR1("MailId")
11: End If
12: Try
13: Dim Email As New System.Net.Mail.MailMessage(System.Configuration.ConfigurationManager.AppSettings("SMTP_FromAddr"), ToAddr, Subject, Body)
14: Email.IsBodyHtml = True 'для форматированной почты
15: 'Email.Attachments.Add(New system.Net.Mail.Attachment(...))
16: Dim MailClient As New System.Net.Mail.SmtpClient()
17: Dim basicAuthenticationInfo As New System.Net.NetworkCredential(System.Configuration.ConfigurationManager.AppSettings("SMTP_Login"), System.Configuration.ConfigurationManager.AppSettings("SMTP_Pass"))
18: MailClient.Host = System.Configuration.ConfigurationManager.AppSettings("SMTP_Server")
19: MailClient.Port = System.Configuration.ConfigurationManager.AppSettings("SMTP_Port")
20: MailClient.UseDefaultCredentials = False
21: MailClient.Credentials = basicAuthenticationInfo
22: MailClient.Send(Email)
23: Catch ex As Exception
24: My.Log.WriteEntry(System.Configuration.ConfigurationManager.AppSettings("SMTP_FromAddr") & "->" & ToAddr & ":" & Subject & ":" & Body & vbCrLf & "SendMail_Error: " & ex.Message)
25: Dim AddMailError As New ExecMySQL_RDR("i1", SendedMailID, "SendError1", ex.Message)
26: AddMailError.ExecMySQL("AddMailError", Data.CommandType.StoredProcedure)
27: End Try
28: End Sub
29:
30: End Class
Обрабатывает активационные письма страничка ActivateLogin.aspx. Для разнообразия я сделал в ней обращения в MySQL Через SqlDataSource - хотя мой опыт показывает что работает он нестабильно - и даже когда у него все параметры сконфигурированы - он часто падает, ибо обращается к провайдеру MS SQL.
Поэтому, посмотрев на логику этой странички, вам лучше ее заменить на обращения к MySQL через мой более надежно работающий враппер ExecMySQL_RDR.
1: <asp:Content ID="Content3" ContentPlaceHolderID="RightPlaceHolder2" runat="Server">
2: <table cellpadding="0" cellspacing="0" border="0" style="display: inline">
3: <tr>
4: <td>
5: <asp:Literal ID="Literal1" runat="server"></asp:Literal>
6: </td>
7: </tr>
8: </table>
9: <asp:SqlDataSource ID="GetOneUser" runat="server" ConnectionString="<%$ ConnectionStrings:MySQLConnectionString %>"
10: ProviderName="<%$ ConnectionStrings:MySQLConnectionString.ProviderName %>"
11: SelectCommand="select * from releasebeat.aspnet_users where id=@id;">
12: <SelectParameters>
13: <asp:Parameter Name="id" Type="String" />
14: </SelectParameters>
15: </asp:SqlDataSource>
16:
17: <asp:SqlDataSource ID="ActivateUser" runat="server" ConnectionString="<%$ ConnectionStrings:MySQLConnectionString %>"
18: ProviderName="<%$ ConnectionStrings:MySQLConnectionString.ProviderName %>"
19: SelectCommand="Update releasebeat.aspnet_users Set IsActivate=True where id=@id;">
20: <SelectParameters>
21: <asp:Parameter Name="id" Type="String" />
22: </SelectParameters>
23: </asp:SqlDataSource>
24: </asp:Content>
Собственно код странички активации выглядит вот так:
1: Partial Class ActivateLogin
2: Inherits BasePage
3:
4: Protected Sub ActivateLogin_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
5: If Not IsPostBack Then
6: If Context.Request.QueryString("i") <> "" And Context.Request.QueryString("j") <> "" Then
7: Dim UserID As Guid
8: Dim ActivateID As Guid
9: Try
10: UserID = New Guid(Context.Request.QueryString("i"))
11: ActivateID = New Guid(Context.Request.QueryString("j"))
12: Catch ex As Exception
13: Throw New Exception("Указаны неверные параметры")
14: End Try
15: GetOneUser.SelectParameters("id").DefaultValue = UserID.ToString
16: Dim DV1 As Data.DataView = GetOneUser.Select(New DataSourceSelectArguments)
17: If DV1 IsNot Nothing Then
18: Dim SavedGuid As String = DV1(0)("ActivateID")
19: If SavedGuid = Context.Request.QueryString("j") Then
20: If Not DV1(0)("IsActivate") Then
21: Try
22: ActivateUser.SelectParameters("id").DefaultValue = UserID.ToString
23: ActivateUser.Select(New DataSourceSelectArguments)
24: Catch ex As Exception
25: Throw New Exception("Ошибка." & ex.Message)
26: End Try
27: Literal1.Text = "Поздравляем!<br> Вы зарегистрированы в проекте " & System.Configuration.ConfigurationManager.AppSettings("RealURL") & "<br>Желаем Вам приятного отдыха!<br><br>"
28: Response.Redirect("Default.aspx")
29: Else
30: Literal1.Text = "Вы уже активированны в проекте " & System.Configuration.ConfigurationManager.AppSettings("RealURL") & "<br>Желаем Вам удобного, приятного отдыха!<br><br>"
31: End If
32: Else
33: Literal1.Text = "Неверный параметр активации."
34: End If
35: Else
36: Literal1.Text = "Пользователя не существует."
37: End If
38: Else
39: Throw New Exception("Dos атака")
40: End If
41: End If
42:
43: End Sub
44:
45:
46: End Class
Все что нам нужно на внешней контактной поверхности сайта - это еще страничка напоминания пароля RestorePass.aspx (ссылка на которую тоже должны быть на залогинивающем контроле). Эта страничка может выглядеть так:
1: <asp:Content ID="Content3" ContentPlaceHolderID="RightPlaceHolder2" runat="Server">
2:
3: <table cellpadding="0" cellspacing="0" border="0" style="display: inline">
4: <tr>
5: <td>
6: <asp:Label ID="lblMessage" runat="server" Visible="false" Text=""></asp:Label>
7: <asp:Panel ID="pnlForgotPass" runat="server">
8: <asp:Label ID="lblError" runat="server" Visible="false" CssClass="error" Text="You have entered incorrect login or password."></asp:Label>
9: <br />
10: Type your login or email if you want to restore your password.
11: <div class="form">
12: <br />
13: <br />
14: <span>Login:</span>
15: <asp:TextBox ID="tbxForgotLogin" runat="server"></asp:TextBox><br />
16: <br />
17: OR<br />
18: <br />
19: <span>Email:</span>
20: <asp:TextBox ID="tbxForgotEmail" runat="server"></asp:TextBox><br />
21: <br />
22: </div>
23: <asp:Button ID="btnRemember" runat="server" CssClass="button" Text="REMEMBER" OnClick="RememberCommand" />
24: <br /><asp:Label ID="Lerr1" runat="server" ForeColor="Red"></asp:Label>
25: </asp:Panel>
26: </td>
27: </tr>
28: </table>
29:
30: <asp:SqlDataSource ID="GetUserForName" runat="server" ConnectionString="<%$ ConnectionStrings:MySQLConnectionString %>"
31: ProviderName="<%$ ConnectionStrings:MySQLConnectionString.ProviderName %>"
32: SelectCommand="select * from releasebeat.aspnet_users where UserName=@UserName;">
33: <SelectParameters>
34: <asp:Parameter Name="UserName" Type="String" />
35: </SelectParameters>
36: </asp:SqlDataSource>
37:
38: <asp:SqlDataSource ID="GetUserForMail" runat="server" ConnectionString="<%$ ConnectionStrings:MySQLConnectionString %>"
39: ProviderName="<%$ ConnectionStrings:MySQLConnectionString.ProviderName %>"
40: SelectCommand="select * from releasebeat.aspnet_users where Email=@Email;">
41: <SelectParameters>
42: <asp:Parameter Name="Email" Type="String" />
43: </SelectParameters>
44: </asp:SqlDataSource>
45:
46: </asp:Content>
1: Partial Class RestorePass
2: Inherits BasePage
3:
4: Protected Sub RememberCommand(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnRemember.Click
5: Try
6: If tbxForgotEmail.Text <> "" Then
7: GetUserForMail.SelectParameters("Email").DefaultValue = tbxForgotEmail.Text
8: Dim DV1 As Data.DataView = GetUserForMail.Select(New DataSourceSelectArguments)
9: If DV1 IsNot Nothing Then
10: If DV1.Count > 0 Then
11: If DV1(0)("IsActive") Then
12: Mail1.SendMail(DV1(0)("Email"), "Активация логина " & System.Configuration.ConfigurationManager.AppSettings("NameURL"), "<html><body>Здравствуйте, " & DV1(0)("UserName") & " <br><br>Добро пожаловать на сайт " & System.Configuration.ConfigurationManager.AppSettings("NameURL") & " <br><br>Параметры вашей учётной записи таковы: " & _
13: "<br><br><b>Логин:</b>" & DV1(0)("UserName") & _
14: "<br><br><b>Пароль:</b> " & DV1(0)("Pass") & _
15: "<br><br>Если данное письмо послано Вам ошибочно, то проигнорируйте его." & _
16: "<br><br>___________________<br>C уважением,<br> Администрация <a href='http://" & System.Configuration.ConfigurationManager.AppSettings("HostingURL") & "'>" & System.Configuration.ConfigurationManager.AppSettings("NameURL") & "</a></body></html>")
17: End If
18: End If
19: End If
20: ElseIf tbxForgotLogin.Text <> "" Then
21: GetUserForName.SelectParameters("UserName").DefaultValue = tbxForgotLogin.Text
22: Dim DV2 As Data.DataView = GetUserForName.Select(New DataSourceSelectArguments)
23: If DV2 IsNot Nothing Then
24: If DV2.Count > 0 Then
25: If DV2(0)("IsActive") Then
26: Mail1.SendMail(DV2(0)("Email"), "Активация логина " & System.Configuration.ConfigurationManager.AppSettings("NameURL"), "<html><body>Здравствуйте, " & DV2(0)("UserName") & " <br><br>Добро пожаловать на сайт " & System.Configuration.ConfigurationManager.AppSettings("NameURL") & " <br><br>Параметры вашей учётной записи таковы: " & _
27: "<br><br><b>Логин:</b>" & DV2(0)("UserName") & _
28: "<br><br><b>Пароль:</b> " & DV2(0)("Pass") & _
29: "<br><br>Если данное письмо послано Вам ошибочно, то проигнорируйте его." & _
30: "<br><br>___________________<br>C уважением,<br> Администрация <a href='http://" & System.Configuration.ConfigurationManager.AppSettings("HostingURL") & "'>" & System.Configuration.ConfigurationManager.AppSettings("NameURL") & "</a></body></html>")
31: End If
32: End If
33: End If
34: End If
35: Response.Redirect("Default.aspx")
36: Catch ex As Exception
37: Lerr1.Text = ex.Message
38: End Try
39:
40: End Sub
Все что нам нужно еще в части управления пользователями - это смена пароля. Это можно сделать в кабинете пользователя наряду с другими специфическими параметрами профиля пользователя. С точки зрения управления пользователями - это простой Update в базу.
Теперь рассмотрим ту часть управления пользователями, которую видит только админ сайта. Как вы понимаете, админка - это совсем другой сайт. Например для сайта votpusk.ru админка выглядит вот так - Опыт видео-конвертации. Хотя во множестве проектов у меня нету выделенной админки - формы управления юзерами находятся в основном проекте. Если же есть выделенная админка в другом домене, то ее конфиг точно такой же, как конфиг основного сайта.
Для нашего OpenSource-проекта админка юзеров сайта будет состоять из трех небольших страничек admin_user_activate.aspx, admin_user_list.aspx, admin_clear_user.aspx.
![]() |
Страничка admin_user_activate.aspx предназначена для активации пользователей вручную - в тех случаях когда они просят об этом по телефону из-за того, что активационное мыло до них не проходит спам-фильтры. |
1: <%@ Page Language="VB" MasterPageFile="~/M1.master" AutoEventWireup="false" CodeFile="admin_user_activate.aspx.vb" Inherits="admin_user_activate" %>
2:
3: <asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
4: <h4>Активация пользователя</h4>
5:
6: <table>
7:
8: <tr><td colspan="2"><asp:Label ID="Label2" runat="server" Text="UserName"></asp:Label></td></tr>
9: <tr><td><asp:TextBox ID="TextBox1" runat="server" Width="300px"></asp:TextBox>
10: </td><td><asp:Button ID="Button1" runat="server" Text="Проверить" Width="100px" />
11:
12: </td></tr><tr><td><asp:Label ID="Label1" runat="server"></asp:Label>
13: </td><td><asp:Button ID="Button2" runat="server" Enabled="False" Text="Активировать" Width="100px" />
14: </td></tr></table>
15: <asp:Label ID="Lerr1" runat="server" ForeColor="Red"></asp:Label>
16:
17: <asp:SqlDataSource ID="GetOneUserByName" runat="server" ConnectionString="<%$ ConnectionStrings:MySQLConnectionString %>"
18: ProviderName="<%$ ConnectionStrings:MySQLConnectionString.ProviderName %>"
19: SelectCommand="select * from releasebeat.aspnet_users where UserName=@UserName;">
20: <SelectParameters>
21: <asp:Parameter Name="UserName" Type="String" />
22: </SelectParameters>
23: </asp:SqlDataSource>
24:
25: <asp:SqlDataSource ID="GetOneUserByID" runat="server" ConnectionString="<%$ ConnectionStrings:MySQLConnectionString %>"
26: ProviderName="<%$ ConnectionStrings:MySQLConnectionString.ProviderName %>"
27: SelectCommand="select * from releasebeat.aspnet_users where id=@id;">
28: <SelectParameters>
29: <asp:Parameter Name="id" Type="String" />
30: </SelectParameters>
31: </asp:SqlDataSource>
32:
33:
34: <asp:SqlDataSource ID="ActivateUser" runat="server" ConnectionString="<%$ ConnectionStrings:MySQLConnectionString %>"
35: ProviderName="<%$ ConnectionStrings:MySQLConnectionString.ProviderName %>"
36: SelectCommand="Update releasebeat.aspnet_users Set IsActivate=True where id=@id;">
37: <SelectParameters>
38: <asp:Parameter Name="id" Type="String" />
39: </SelectParameters>
40: </asp:SqlDataSource>
41:
42: </asp:Content>
В сущности это просто запись однобитного флажка в базу MySQL:
1:
2: Partial Class admin_user_list
3: Inherits BasePage
4:
5: Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
6: If Not IsPostBack Then
7: If Session("admin_user_list_filter") Is Nothing Then Session("admin_user_list_filter") = ""
8: FilterBox.Text = Session("admin_user_list_filter")
9: CurrentFields.Value = "UserName"
10: CurrentDirection.Value = WebControls.SortDirection.Ascending
11: Refresh()
12: End If
13: End Sub
14:
15: Sub Refresh()
16: Try
17: Dim Filter As String = Session("admin_user_list_filter")
18:
19: Dim DT As New Data.DataTable("Filtered_users")
20: DT.Columns.Add("i", GetType(System.Int32))
21: DT.Columns.Add("id", GetType(System.String))
22: DT.Columns.Add("Email", GetType(System.String))
23: DT.Columns.Add("Pass", GetType(System.String))
24: DT.Columns.Add("IsActivate", GetType(System.Boolean))
25: DT.Columns.Add("CrDate", GetType(System.DateTime))
26: DT.Columns.Add("UserName", GetType(System.String))
27: DT.Columns.Add("Name1", GetType(System.String))
28: DT.Columns.Add("Name2", GetType(System.String))
29: DT.Columns.Add("IP", GetType(System.String))
30: DT.Columns.Add("IsAdmin", GetType(System.Boolean))
31: DT.Columns.Add("IsBan", GetType(System.Boolean))
32:
33: Dim GetAllUsers2 As New ExecMySQL_RDR()
34: Dim DR1 As MySql.Data.MySqlClient.MySqlDataReader = GetAllUsers2.ExecMySQL("select * from releasebeat.aspnet_users order by i", Data.CommandType.Text)
35: While DR1.Read
36: If Filter = "" Or DR1("UserName").Contains(Filter) Then
37: Dim OneRow As System.Data.DataRow = DT.NewRow
38: OneRow("i") = DR1("i")
39: OneRow("id") = DR1("id")
40: OneRow("Email") = DR1("Email")
41: OneRow("Pass") = DR1("Pass")
42: OneRow("IsActivate") = DR1("IsActivate")
43: OneRow("CrDate") = DR1("CrDate")
44: OneRow("UserName") = DR1("UserName")
45: OneRow("Name1") = DR1("Name1")
46: OneRow("Name2") = DR1("Name2")
47: OneRow("IP") = DR1("IP")
48: OneRow("IsAdmin") = DR1("IsAdmin")
49: OneRow("IsBan") = DR1("IsBan")
50: DT.Rows.Add(OneRow)
51: End If
52: End While
53:
54: GridView1.AutoGenerateColumns = False
55: 'Dim UserNameColumn As New ui.WebControls.HyperLinkField 'колонки можно выставить и в коде
56: Dim SortExpression As String
57: If CurrentDirection.Value = WebControls.SortDirection.Ascending Then
58: SortExpression = CurrentFields.Value & " asc"
59: Else
60: SortExpression = CurrentFields.Value & " desc"
61: End If
62: Dim DV1 As Data.DataView
63: If Filter = "" Then
64: DV1 = New Data.DataView(DT, "UserName like '%*%'", SortExpression, Data.DataViewRowState.CurrentRows)
65: Else
66: DV1 = New Data.DataView(DT, "UserName like '%" & Filter & "%'", SortExpression, Data.DataViewRowState.CurrentRows)
67: End If
68: GridView1.DataSource = DV1
69: GridView1.DataMember = "Filtered_users"
70: Dim KeyArr() As String = {"id"}
71: GridView1.DataKeyNames = KeyArr 'баг бейсика - запрет онлайнового обьявления массива
72: GridView1.DataBind()
73: Catch ex As Exception
74: Lerr1.Text = ex.Message
75: End Try
76:
77: End Sub
78:
79:
80: Protected Sub GridView1_PageIndexChanging(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewPageEventArgs) Handles GridView1.PageIndexChanging
81: GridView1.PageIndex = e.NewPageIndex
82: Refresh()
83: End Sub
84:
85: Protected Sub GridView1_Sorting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewSortEventArgs) Handles GridView1.Sorting
86: CurrentFields.Value = e.SortExpression
87: If CurrentDirection.Value = WebControls.SortDirection.Ascending Then
88: CurrentDirection.Value = WebControls.SortDirection.Descending
89: Else
90: CurrentDirection.Value = WebControls.SortDirection.Ascending
91: End If
92: Refresh()
93: End Sub
94:
95: Protected Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView1.RowDataBound
96: If e.Row.DataItem IsNot Nothing Then
97: Dim UnBan_Button1 As LinkButton = CType(e.Row.FindControl("UnBan_Button1"), LinkButton)
98: Dim Ban_Button1 As LinkButton = CType(e.Row.FindControl("Ban_Button1"), LinkButton)
99: If IsDBNull(e.Row.DataItem("IsBan")) Then
100: Ban_Button1.Enabled = True
101: UnBan_Button1.Enabled = False
102: Ban_Button1.ForeColor = Drawing.Color.Red
103: Else
104: If Not e.Row.DataItem("IsBan") Then
105: Ban_Button1.Enabled = True
106: UnBan_Button1.Enabled = False
107: Ban_Button1.ForeColor = Drawing.Color.Red
108: Else
109: Ban_Button1.Enabled = False
110: UnBan_Button1.Enabled = True
111: UnBan_Button1.ForeColor = Drawing.Color.Red
112: End If
113: End If
114:
115: Dim UserNameColumns As HyperLink = CType(e.Row.FindControl("UserNameColumns"), HyperLink)
116: UserNameColumns.NavigateUrl = "http://" & ConfigurationManager.AppSettings("HostingURL")
117: End If
118: End Sub
119:
120: Protected Sub Ban_Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
121: Try
122: Dim UserID As String = CType(sender, LinkButton).CommandArgument
123: Dim BanUser As New ExecMySQL_RDR("id", UserID)
124: Dim DR1 As MySql.Data.MySqlClient.MySqlDataReader = BanUser.ExecMySQL("Update releasebeat.aspnet_users set IsBan=True where id=@id", Data.CommandType.Text)
125: Refresh()
126: Catch ex As Exception
127: Lerr1.Text = ex.Message
128: End Try
129:
130: End Sub
131:
132: Protected Sub UnBan_Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs)
133: Try
134: Dim UserID As String = CType(sender, LinkButton).CommandArgument
135: Dim BanUser As New ExecMySQL_RDR("id", UserID)
136: Dim DR1 As MySql.Data.MySqlClient.MySqlDataReader = BanUser.ExecMySQL("Update releasebeat.aspnet_users set IsBan=NULL where id=@id", Data.CommandType.Text)
137: Refresh()
138: Catch ex As Exception
139: Lerr1.Text = ex.Message
140: End Try
141: End Sub
142:
143: Protected Sub SetFilter_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles SetFilter.Click
144: Session("admin_user_list_filter") = FilterBox.Text
145: Refresh()
146: End Sub
147:
148:
149: End Class
![]() |
Следующая форма admin_user_list.aspx - это тоже в сущности запись одного бита в таблицу учета пользователей - только здесь есть еще сервис для отбора пользователей (когда их становятся тысячи и десятки тысяч): |
1: <asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
2:
3: <asp:HiddenField ID="CurrentFields" runat="server" />
4: <asp:HiddenField ID="CurrentDirection" runat="server" />
5:
6: <h4>Забанить/разбанить пользователя</h4>
7: <asp:TextBox ID="FilterBox" runat="server"></asp:TextBox>
8: <asp:Button ID="SetFilter" runat="server" Text="Отфильтровать" />
9: <br><br>
10: <asp:GridView ID="GridView1" runat="server" AllowPaging="True" AllowSorting="True" AutoGenerateColumns="False" PageSize="25" Width="100%" CellPadding="5">
11: <Columns>
12: <asp:BoundField DataField="i" HeaderText="i" SortExpression="i" />
13: <asp:TemplateField>
14: <ItemTemplate>
15: <asp:LinkButton ID="Ban_Button1" runat="server"
16: CommandArgument='<%# Eval("id")%>' CommandName="Ban"
17: onclick="Ban_Button1_Click" >Забанить</asp:LinkButton>
18: <asp:LinkButton ID="UnBan_Button1" runat="server"
19: CommandArgument='<%# Eval("id")%>' CommandName="UnBan"
20: onclick="UnBan_Button1_Click" >Разбанить</asp:LinkButton>
21: </ItemTemplate>
22: </asp:TemplateField>
23: <asp:TemplateField HeaderText="UserName" SortExpression="UserName">
24: <ItemTemplate>
25: <asp:HyperLink ID="UserNameColumns" runat="server" Text='<%# Eval("UserName") %>' ></asp:HyperLink>
26: </ItemTemplate>
27: </asp:TemplateField>
28: <asp:CheckBoxField DataField="IsActivate" HeaderText="IsActivate" SortExpression="IsActivate" />
29: <asp:CheckBoxField DataField="IsAdmin" HeaderText="IsAdmin" SortExpression="IsAdmin" />
30: <asp:CheckBoxField DataField="IsBan" HeaderText="IsBan" SortExpression="IsBan" />
31: <asp:BoundField DataField="Email" HeaderText="Email" SortExpression="Email" />
32: <asp:BoundField DataField="IP" HeaderText="IP" SortExpression="IP" />
33: <asp:BoundField DataField="CrDate" HeaderText="CrDate" SortExpression="CrDate" DataFormatString="{0:dd/MM/yyyy}" HtmlEncode="False" />
34: </Columns>
35: </asp:GridView>
36: <asp:Label ID="Lerr1" runat="server" ForeColor="#CC3300" Text=""></asp:Label>
37:
38:
39: </asp:Content>
40:
1: Partial Class admin_audio_ban
2: Inherits BasePage
3:
4: Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
5: If Not IsPostBack Then
6: Refresh()
7: End If
8: End Sub
9:
10: Sub Refresh()
11: Try
12: Dim CreateAudio As New ExecMySQL_RDR()
13: Dim DR1 As MySql.Data.MySqlClient.MySqlDataReader = CreateAudio.ExecMySQL("select * from releasebeat.audio", Data.CommandType.Text)
14: Dim DT1 As New Data.DataTable("Track")
15: DT1.Load(DR1)
16: GridView1.DataSource = DT1
17: GridView1.DataBind()
18: Catch ex As Exception
19: Lerr1.Text = ex.Message
20: End Try
21: End Sub
22:
23: Protected Sub GridView1_PageIndexChanging(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewPageEventArgs) Handles GridView1.PageIndexChanging
24: GridView1.PageIndex = e.NewPageIndex
25: Refresh()
26: End Sub
27:
28:
29: Protected Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView1.RowDataBound
30: If e.Row.DataItem IsNot Nothing Then
31: Dim UnBan_Button1 As LinkButton = CType(e.Row.FindControl("UnBanButton"), LinkButton)
32: Dim Ban_Button1 As LinkButton = CType(e.Row.FindControl("BanButton"), LinkButton)
33: If IsDBNull(e.Row.DataItem("IsBan")) Then
34: Ban_Button1.Enabled = True
35: UnBan_Button1.Enabled = False
36: Ban_Button1.ForeColor = Drawing.Color.Red
37: Else
38: If Not e.Row.DataItem("IsBan") Then
39: Ban_Button1.Enabled = True
40: UnBan_Button1.Enabled = False
41: Ban_Button1.ForeColor = Drawing.Color.Red
42: Else
43: Ban_Button1.Enabled = False
44: UnBan_Button1.Enabled = True
45: UnBan_Button1.ForeColor = Drawing.Color.Red
46: End If
47: End If
48: End If
49: End Sub
50:
51: Protected Sub BanButton_Click(ByVal sender As Object, ByVal e As System.EventArgs)
52: Dim ID As String = CType(sender, LinkButton).CommandArgument
53: Try
54: Dim DeleteAudio As New ExecMySQL_RDR("id1", ID)
55: Dim DR1 As MySql.Data.MySqlClient.MySqlDataReader = DeleteAudio.ExecMySQL("update releasebeat.audio set IsBan=True where id=@id1", Data.CommandType.Text)
56: Refresh()
57: Catch ex As Exception
58: Lerr1.Text = ex.Message
59: End Try
60: End Sub
61:
62: Protected Sub UnBanButton_Click(ByVal sender As Object, ByVal e As System.EventArgs)
63: Dim ID As String = CType(sender, LinkButton).CommandArgument
64: Try
65: Dim DeleteAudio As New ExecMySQL_RDR("id1", ID)
66: Dim DR1 As MySql.Data.MySqlClient.MySqlDataReader = DeleteAudio.ExecMySQL("update releasebeat.audio set IsBan=NULL where id=@id1", Data.CommandType.Text)
67: Refresh()
68: Catch ex As Exception
69: Lerr1.Text = ex.Message
70: End Try
71: End Sub
72:
73: End Class
![]() |
И, наконец, последняя форма админки, которую я опишу в этом OpenSource-коплекте для работы с MySQL в ASP-NET - это форма admin_clear_user.aspx, предназначенная для полной очистки базы от данных пользователя: |
1: <%@ Page Language="VB" MasterPageFile="~/M1.master" AutoEventWireup="false" CodeFile="admin_clear_user.aspx.vb" Inherits="admin_clear_user" %>
2:
3: <asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
4: <h4>Полная очистка базы от всех данных пользователя</h4>
5:
6: <asp:TextBox ID="FilterBox" runat="server"></asp:TextBox>
7: <asp:Button ID="SetFilter" runat="server" Text="Отфильтровать" />
8:
9: <asp:GridView ID="GridView1" runat="server" AllowPaging="True"
10: AutoGenerateColumns="False" DataKeyNames="Id" PageSize="20">
11: <Columns>
12: <asp:TemplateField HeaderText="UserId" SortExpression="Id">
13: <EditItemTemplate>
14: <asp:Label ID="Label1" runat="server" Text='<%# Eval("Id") %>'></asp:Label>
15: </EditItemTemplate>
16: <ItemTemplate>
17: <asp:LinkButton ID="LinkClear" runat="server" onclick="LinkClear_Click">Очистить базу</asp:LinkButton>
18: <asp:HiddenField ID="HiddenField1" runat="server" />
19: </ItemTemplate>
20: </asp:TemplateField>
21: <asp:BoundField DataField="Email" HeaderText="Email" SortExpression="Email" />
22: <asp:BoundField DataField="UserName" HeaderText="UserName"
23: SortExpression="UserName" />
24: <asp:BoundField DataField="CrDate" HeaderText="Создан"
25: SortExpression="CrDate" />
26: <asp:BoundField DataField="Name1" HeaderText="Name1"
27: SortExpression="Name1" />
28: <asp:BoundField DataField="Name2" HeaderText="Name2"
29: SortExpression="Name2" />
30: </Columns>
31: </asp:GridView>
32: <asp:Label ID="Lerr1" runat="server" ForeColor="#CC3300" Text=""></asp:Label>
33:
34:
35: </asp:Content>
36:
В сущности это тоже вызов одной MySQL-процедуры, которая и должна в соответствии со структурой контрейнсов почистить базу. На этой форме тоже реализован сервис йильтрации юзеров.
1:
2: Partial Class admin_clear_user
3: Inherits BasePage
4:
5:
6: Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
7: If Not IsPostBack Then
8: If Session("admin_clear_user_filter") Is Nothing Then Session("admin_clear_user_filter") = ""
9: FilterBox.Text = Session("admin_clear_user_filter")
10: GridView1_DataBind()
11: End If
12: End Sub
13:
14: Sub GridView1_DataBind()
15: Try
16: Dim Filter As String = Session("admin_clear_user_filter")
17: Dim DV1 As Data.DataView '= GetAllUsers1.Select(New DataSourceSelectArguments)
18: Dim GetAllUsers2 As New ExecMySQL_RDR()
19: Dim DR1 As MySql.Data.MySqlClient.MySqlDataReader = GetAllUsers2.ExecMySQL("select * from releasebeat.aspnet_users order by i", Data.CommandType.Text)
20: Dim DT1 As New Data.DataTable("aspnet_users")
21: DT1.Load(DR1)
22: DV1 = DT1.DefaultView
23: If Filter <> "" Then
24: DV1.RowFilter = "UserName like '*" & Filter & "*'"
25: End If
26: GridView1.DataSource = DV1
27: GridView1.DataBind()
28: Catch ex As Exception
29: Lerr1.Text = ex.Message
30: End Try
31:
32: End Sub
33:
34: Protected Sub GridView1_PageIndexChanging(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewPageEventArgs) Handles GridView1.PageIndexChanging
35: GridView1.PageIndex = e.NewPageIndex
36: GridView1_DataBind()
37: End Sub
38:
39: Protected Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView1.RowDataBound
40: If e.Row.DataItem IsNot Nothing Then
41: Dim LinkClear As LinkButton = CType(e.Row.FindControl("LinkClear"), LinkButton)
42: Dim UserGuid As String = CType(e.Row.DataItem, Data.DataRowView)("Id").ToString
43: Dim HiddenField1 As HiddenField = CType(e.Row.FindControl("HiddenField1"), HiddenField)
44: HiddenField1.Value = UserGuid.ToString
45: If CType(e.Row.DataItem, Data.DataRowView)("UserName") = ConfigurationManager.AppSettings("Admin_Login").ToString Then
46: LinkClear.Enabled = False
47: End If
48: End If
49: End Sub
50:
51: Protected Sub LinkClear_Click(ByVal sender As Object, ByVal e As System.EventArgs)
52: Dim LinkClear As LinkButton = CType(sender, LinkButton)
53: Dim HiddenFields1 As HiddenField = CType(LinkClear.Parent.FindControl("HiddenField1"), HiddenField)
54: Dim DV1 As Data.DataView
55: Try
56: 'ClearAllUserInfo.SelectParameters("Id1").DefaultValue = HiddenFields1.Value
57: 'DV1 = ClearAllUserInfo.Select(New DataSourceSelectArguments)
58: Dim ClearAllUserInfo2 As New ExecMySQL_RDR("Id1", HiddenFields1.Value)
59: Dim DR1 As MySql.Data.MySqlClient.MySqlDataReader = ClearAllUserInfo2.ExecMySQL("ClearAllUserInfo", Data.CommandType.StoredProcedure)
60:
61: Catch X As System.Exception
62: If DV1 IsNot Nothing Then
63: If DV1.Count > 0 Then
64: Lerr1.Text = X.Message & vbCrLf & DV1(0)("ErrorMessage")
65: Else
66: Lerr1.Text = X.Message
67: End If
68: Else
69: Lerr1.Text = X.Message
70: End If
71: Exit Sub
72: End Try
73: lerr1.text = ""
74: GridView1_DataBind()
75: End Sub
76:
77: Protected Sub SetFilter_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles SetFilter.Click
78: Session("admin_clear_user_filter") = FilterBox.Text
79: GridView1_DataBind()
80: End Sub
81:
82:
83: End Class
Теперь рассмотрим еще пару общих компонентов управления пользователями любого ASP.NET-сайта. Это задание для удаления неактивированных логинов, базовая страничка и общие потоки проекта от global.asax для создания неудаляемого админа и других общих задач.
К счастью, MySQL является более развитым, чем MS SQL - в частности задания SQL JOB у него входят в бесплатную комплектацию, а не стоят 7 тысяч долларов, как у билогейтсовского сервера. Поэтому вы можете просто сконфигурировать SqlJob непосредственно в оснастке управления MySQL и удалять там неактивированные логины. Все это уже неоднократно и достаточно подробно разжевано у мня на сайте - Выполнение периодических задач в ASP.NET.
Базовые странички у меня тоже разжеваны до предела на моем сайте - читайте например Базовые странички ASP.NET. Ну а для этого OpenSource-шаблона я покажу какую-нибудь самую простую базовую страничку, которая в найпростейшем варианте может выглядеть вот так:
1: Imports Microsoft.VisualBasic
2:
3: Public Class BasePage
4: Inherits System.Web.UI.Page
5:
6: 'i INT(12) NOT NULL AUTO_INCREMENT,
7: 'id VARCHAR(36),
8: 'Email VARCHAR(50) NOT NULL,
9: 'Pass VARCHAR(50) NOT NULL,
10: 'ActivateID VARCHAR(36) NOT NULL,
11: 'IsActivate TINYINT(1) DEFAULT NULL,
12: 'CrDate DATETIME NOT NULL,
13: 'UserName VARCHAR(50) NOT NULL,
14: 'Name1 VARCHAR(50) DEFAULT NULL,
15: 'Name2 VARCHAR(50) DEFAULT NULL,
16: 'IP VARCHAR(16) NOT NULL,
17: 'IsAdmin TINYINT(1) DEFAULT NULL,
18:
19: Dim _User_I As Integer
20: Public ReadOnly Property User_I() As Integer
21: Get
22: Return _User_I
23: End Get
24: End Property
25:
26: Dim _User_id As String
27: Public ReadOnly Property User_id() As String
28: Get
29: Return _User_id
30: End Get
31: End Property
32:
33: Dim _User_Email As String
34: Public ReadOnly Property User_Email() As String
35: Get
36: Return _User_Email
37: End Get
38: End Property
39:
40: Dim _User_IsActivate As Boolean
41: Public ReadOnly Property User_IsActivate() As Boolean
42: Get
43: Return _User_IsActivate
44: End Get
45: End Property
46:
47: Dim _User_UserName As String
48: Public ReadOnly Property User_UserName() As String
49: Get
50: Return _User_UserName
51: End Get
52: End Property
53:
54: Dim _User_IsAdmin As Boolean
55: Public ReadOnly Property User_IsAdmin() As Boolean
56: Get
57: Return _User_IsAdmin
58: End Get
59: End Property
60:
61: Dim _User_Pass As String
62: Public ReadOnly Property User_Pass() As String
63: Get
64: Return _User_Pass
65: End Get
66: End Property
67:
68: Private Sub BasePage_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
69:
70: If HttpContext.Current.User.Identity.IsAuthenticated Then
71: 'If Session("UserPropertyExists") Is Nothing Then
72: 'аутенфицированный юзер, но свойства его еще не загружены в контекст странички
73: Dim GetOneUser As New ExecMySQL_RDR("Email", HttpContext.Current.User.Identity.Name)
74: Dim DR1 As MySql.Data.MySqlClient.MySqlDataReader = GetOneUser.ExecMySQL("select * from releasebeat.aspnet_users where email=@email", Data.CommandType.Text)
75: If DR1.Read Then
76: Session("UserPropertyExists") = "OK"
77: _User_I = DR1("I")
78: _User_id = DR1("id")
79: _User_Email = DR1("Email")
80: _User_UserName = DR1("UserName")
81: _User_Pass = DR1("Pass")
82: _User_IsActivate = DR1("IsActivate")
83: _User_IsAdmin = DR1("IsAdmin")
84:
85: End If
86: 'End If
87: End If
88: End Sub
89:
90: End Class
Все странички проекта наследуются от базовой странички вот так:
1: Partial Class Cab
2: Inherits BasePage
3:
4: Protected Sub Cab_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
5: Try
6: 'тут код странички
7: Catch ex As Exception
8: Lerr1.Text = ex.Message
9: End Try
10:
11:
12: End Sub
13: End Class
И тогда на каждой страничке проекта автоматически видно - в залогиненном ли контексте она вызывается (и кем именно) или в анонимном.
![](http://forum.vb-net.com/GetTopicCount.png?id=F85629A4-C541-4810-8A7A-623A249F6536)
<SITEMAP> <MVC> <ASP> <NET> <DATA> <KIOSK> <FLEX> <SQL> <NOTES> <LINUX> <MONO> <FREEWARE> <DOCS> <ENG> <CHAT ME> <ABOUT ME> < THANKS ME> |