К 2000 году казахстанские компании начали воспринимать сайт не как интернет-визитку, а как рабочий инструмент. Нужны были личные кабинеты для клиентов, системы онлайн-заказов, закрытые разделы с прайс-листами для партнёров. Всё это требовало авторизации.
В Алматы 2000 года в корпоративной среде господствовал Microsoft: Windows NT/2000 на серверах, SQL Server 7, Exchange, IIS. Выбор ASP как технологии для первого корпоративного веб-приложения был логичен - тот же стек, те же администраторы, та же документация на русском в MSDN.
Полная система авторизации: ASP + SQL Server
<%
' login.asp - авторизация для казахстанского корпоративного сайта, 2000 год
' VBScript, IIS 5, SQL Server 2000
' Кодировка: windows-1251
Option Explicit
Dim strError
strError = ""
If Request.ServerVariables("REQUEST_METHOD") = "POST" Then
Dim strLogin, strPassword
strLogin = Trim(Request.Form("login"))
strPassword = Trim(Request.Form("password"))
If strLogin = "" Or strPassword = "" Then
strError = "Введите логин и пароль."
Else
If CheckLogin(strLogin, strPassword) Then
Session("IsAuth") = True
Session("Login") = strLogin
Session("AuthTime") = Now()
' Редирект в личный кабинет
Dim returnUrl
returnUrl = Request.QueryString("return")
If returnUrl = "" Then returnUrl = "cabinet.asp"
Response.Redirect returnUrl
Response.End
Else
strError = "Неверный логин или пароль."
End If
End If
End If
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Вход в систему</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
</head>
<body bgcolor="#F0F0F0">
<br><br>
<table width="350" border="0" cellpadding="0" cellspacing="0" align="center">
<tr>
<td bgcolor="#003399">
<font face="Arial" size="2" color="#FFFFFF">
<b> Вход в систему</b>
</font>
</td>
</tr>
<tr>
<td bgcolor="#FFFFFF" style="border:1px solid #003399; padding:15px;">
<% If strError <> "" Then %>
<p><font face="Arial" size="2" color="#CC0000">
<b><%= Server.HTMLEncode(strError) %></b>
</font></p>
<% End If %>
<form method="POST" action="login.asp">
<table border="0" cellpadding="4">
<tr>
<td><font face="Arial" size="2">Логин:</font></td>
<td><input type="text" name="login" size="20"
style="border:1px solid #999999;"></td>
</tr>
<tr>
<td><font face="Arial" size="2">Пароль:</font></td>
<td><input type="password" name="password" size="20"
style="border:1px solid #999999;"></td>
</tr>
<tr>
<td></td>
<td>
<input type="submit" value="Войти"
style="background:#003399; color:#fff; border:0;
padding:4px 12px; cursor:pointer;">
</td>
</tr>
</table>
</form>
</td>
</tr>
</table>
</body>
</html>
Проверка пароля через ADODB
<%
' Функция CheckLogin - аутентификация через SQL Server
Function CheckLogin(strLogin, strPassword)
CheckLogin = False
Dim oConn, oCmd, oRS
Set oConn = Server.CreateObject("ADODB.Connection")
' Строка подключения к SQL Server - типовая для Windows 2000 Server
' Server.CreateObject("ADODB.Connection") = COM-объект через IIS
oConn.Open "Provider=SQLOLEDB;" & _
"Data Source=(local);" & _
"Initial Catalog=CompanyDB;" & _
"Integrated Security=SSPI;"
' SSPI = Windows-аутентификация - без логина/пароля в строке подключения
' Это более безопасно, чем хранить пароль в коде
Set oCmd = Server.CreateObject("ADODB.Command")
Set oCmd.ActiveConnection = oConn
' Параметризованный запрос - защита от SQL-инъекций
oCmd.CommandText = "SELECT UserID, PasswordMD5, IsActive, FullName " & _
"FROM Users WHERE Login = ?"
oCmd.CommandType = 1
oCmd.Parameters.Append _
oCmd.CreateParameter("@login", 200, 1, 50, strLogin)
Set oRS = oCmd.Execute()
If Not oRS.EOF Then
If oRS("IsActive") = True Then
' MD5-хеш пароля - стандарт 2000 года
' md5.asp - внешний include-файл, скачанный с asp101.com
Dim inputHash
inputHash = MD5(strPassword)
If LCase(inputHash) = LCase(oRS("PasswordMD5")) Then
CheckLogin = True
' Сохраняем дополнительные данные пользователя в сессии
Session("FullName") = oRS("FullName")
Session("UserID") = CStr(oRS("UserID"))
' Обновляем дату последнего входа
Call UpdateLastLogin(CStr(oRS("UserID")), oConn)
End If
End If
End If
oRS.Close
oConn.Close
Set oRS = Nothing
Set oCmd = Nothing
Set oConn = Nothing
End Function
Sub UpdateLastLogin(strUserID, oConn)
Dim oCmd
Set oCmd = Server.CreateObject("ADODB.Command")
Set oCmd.ActiveConnection = oConn
oCmd.CommandText = "UPDATE Users SET LastLogin = GETDATE() WHERE UserID = ?"
oCmd.Parameters.Append oCmd.CreateParameter("@id", 3, 1, 4, CLng(strUserID))
oCmd.Execute
Set oCmd = Nothing
End Sub
%>
auth_check.asp: защита страниц
<%
' auth_check.asp - включается в начало каждой защищённой страницы
' Использование: <!-- #include file="auth_check.asp" -->
' Проверка авторизации
If Not CBool(Session("IsAuth")) Then
Dim strCurrentUrl
strCurrentUrl = Request.ServerVariables("URL")
Response.Redirect "login.asp?return=" & Server.URLEncode(strCurrentUrl)
Response.End
End If
' Таймаут: 45 минут неактивности = выход
If IsDate(Session("AuthTime")) Then
If DateDiff("n", Session("AuthTime"), Now()) > 45 Then
Session.Abandon
Response.Redirect "login.asp?msg=session_expired"
Response.End
End If
End If
Session("AuthTime") = Now()
%>
Страница личного кабинета:
<%
Option Explicit
%>
<!-- #include file="auth_check.asp" -->
<!-- #include file="header.asp" -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Личный кабинет</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
</head>
<body>
<h2>Добро пожаловать, <%= Server.HTMLEncode(Session("FullName")) %>!</h2>
<p>Ваш логин: <b><%= Server.HTMLEncode(Session("Login")) %></b></p>
<hr>
<%
' Загружаем заказы пользователя из БД
Dim oConn, oRS
Set oConn = Server.CreateObject("ADODB.Connection")
oConn.Open Application("ConnString")
Dim oCmd
Set oCmd = Server.CreateObject("ADODB.Command")
Set oCmd.ActiveConnection = oConn
oCmd.CommandText = "SELECT OrderID, OrderDate, TotalKZT, Status " & _
"FROM Orders WHERE UserID = ? ORDER BY OrderDate DESC"
oCmd.Parameters.Append oCmd.CreateParameter("@uid", 3, 1, 4, CLng(Session("UserID")))
Set oRS = oCmd.Execute()
%>
<h3>Мои заказы</h3>
<% If oRS.EOF Then %>
<p>Заказов пока нет.</p>
<% Else %>
<table border="1" cellpadding="5" cellspacing="0">
<tr bgcolor="#003399">
<th><font color="#FFFFFF">№</font></th>
<th><font color="#FFFFFF">Дата</font></th>
<th><font color="#FFFFFF">Сумма (тг)</font></th>
<th><font color="#FFFFFF">Статус</font></th>
</tr>
<% Do While Not oRS.EOF %>
<tr>
<td><%= oRS("OrderID") %></td>
<td><%= FormatDateTime(oRS("OrderDate"), 2) %></td>
<td><%= FormatNumber(oRS("TotalKZT"), 2) %></td>
<td><%= Server.HTMLEncode(oRS("Status")) %></td>
</tr>
<% oRS.MoveNext : Loop %>
</table>
<% End If %>
<%
oRS.Close : oConn.Close
Set oRS = Nothing : Set oConn = Nothing
%>
<p><a href="logout.asp">Выйти из системы</a></p>
</body>
</html>
Схема БД для казахстанского интернет-магазина 2000 года
-- SQL Server 2000 / Query Analyzer
-- Таблицы в тенге (KZT) - основная валюта операций
CREATE TABLE Users (
UserID INT IDENTITY(1,1) PRIMARY KEY,
Login VARCHAR(50) NOT NULL UNIQUE,
PasswordMD5 VARCHAR(32) NOT NULL,
FullName NVARCHAR(100) NOT NULL, -- NVARCHAR для казахских букв
Phone VARCHAR(20) NULL,
City VARCHAR(50) NULL DEFAULT 'Алматы',
IsActive BIT NOT NULL DEFAULT 1,
CreatedAt DATETIME NOT NULL DEFAULT GETDATE(),
LastLogin DATETIME NULL
)
GO
CREATE TABLE Orders (
OrderID INT IDENTITY(1,1) PRIMARY KEY,
UserID INT NOT NULL REFERENCES Users(UserID),
OrderDate DATETIME NOT NULL DEFAULT GETDATE(),
TotalKZT DECIMAL(12,2) NOT NULL,
Status VARCHAR(20) NOT NULL DEFAULT 'new',
Notes NVARCHAR(500) NULL
)
GO
Особенности ASP-разработки в казнете 2000 года
NVARCHAR для казахского языка. В 2000 году SQL Server 2000 поддерживал Unicode через NVARCHAR и NTEXT. Однако большинство казахстанских сайтов использовали VARCHAR с windows-1251 - казахские специфические буквы просто не отображались. Правильным решением уже тогда был NVARCHAR:
' Вставка казахского текста через NVARCHAR:
oCmd.Parameters.Append oCmd.CreateParameter("@name", 202, 1, 100, strFullName)
' 202 = adVarWChar (Unicode VarChar) вместо 200 (adVarChar)
Глобализация. ASP на IIS 5 с Windows 2000 Server по умолчанию использовал системную локаль. На казахстанском сервере с русской Windows это означало FormatDate, FormatNumber в российском формате - что обычно было нормально, но иногда давало неожиданное поведение с датами.
Переход к ASP.NET (2002). Казахстанские компании, вложившиеся в IIS/ASP-стек, естественно мигрировали на ASP.NET в 2002-2003 годах. Переход был относительно безболезненным: те же абстракции Request/Response/Session, та же интеграция с Windows-инфраструктурой, только код теперь компилировался.
Classic ASP на казахстанских сайтах встречался до 2006-2008 годов. Некоторые государственные системы работали на нём ещё дольше.