فصل ۲۳ — بهدستآوردن Login ID
Applicationهای Access Multiuser هستند و ممکن است چند User همزمان آنها را Load کنند. اگر Application روی Server سازمان قرار گیرد و Protection نداشته باشد، هرکس File را پیدا کند میتواند آن را باز و استفاده کند؛ موضوعی که برای Data Security و Confidentiality مشکل جدی ایجاد میکند.
میتوان Database را با Password ذخیره کرد، اما Password ممکن است بین افراد غیرمجاز پخش شود و در آن حالت باز هم نمیدانید چه کسی Application را استفاده میکند. علاوه بر آن، User ممکن است واردکردن Password جداگانه را آزاردهنده بداند، در حالی که از قبل به PC خود Login کرده و Windows هویت او را میداند.
با API Call ساده میتوان User Name ویندوز را هنگام ورود به Application دریافت کرد. Module جدید بسازید و Declaration زیر را در General/Declarations Section قرار دهید:
Public Declare Function GetUserName Lib "advapi32.dll" Alias _
"GetUserNameA" (ByVal lpBuffer As String, nSize As Long) As Long
این Declaration به Functionِ GetUserName در advapi32.dll که بخشی از Windows است Link میشود.
سپس Function زیر را در همان Module اضافه کنید:
Public Function ReturnUserName()
Dim strUser As String, X As Integer
strUser = Space$(256)
X = GetUserName(strUser, 256)
strUser = RTrim(strUser)
ReturnUserName = Left(strUser, Len(strUser) - 1)
End Function
Variableِ strUser Buffer نام User و X Return Value مربوط به Success/Failure API را نگه میدارد. Space$(256) Buffer با 256 Character ایجاد میکند که طبق مثال برای Maximum Size نام کاربر کافی است. GetUserName نام را در Buffer قرار میدهد، RTrim Spaceهای انتهایی را حذف و در پایان Character آخر نیز حذف میشود، زیرا API String را همراه Terminator برمیگرداند.
برای استفاده، در Open Eventِ Form بنویسید:
MsgBox ReturnUserName()
Form را در View Mode باز کنید و User Name سیستم در Message Box ظاهر میشود. اگر همان Application روی PC همکار اجرا شود نام او برگردانده میشود. قرار دادن این Function در Startup Form راهی مستقیم برای تشخیص User واردشونده به Application فراهم میکند.
البته User میتواند هنگام Load شدن Database کلید SHIFT/BYPASS را نگه دارد و Startup Behavior را دور بزند. راههای Lock کردن این مسیر در فصل ۲۴ بررسی میشوند.
یک کاربرد سادهٔ User Name
پس از شناخت User، نخستین سؤال این است: «آیا این User مجاز است وارد Application شود؟» برای کنترل ساده، Table تکستونی AuthorizedUsers با Fieldِ UserName بسازید و نام Userهای مجاز را در آن قرار دهید.
Sub CheckUser()
Dim RcSet As Recordset
Set RcSet = CurrentDb.OpenRecordset _
("select * from AuthorizedUsers where UserName='" & ReturnUserName & "'")
If RcSet.RecordCount = 0 Then
MsgBox "You are not authorized to use this application", vbInformation
DoCmd.Quit
Else
MsgBox "Welcome to " & ReturnUserName & ",vbInformation"
End If
End Sub
Recordset روی AuthorizedUsers با UserName برابر خروجی ReturnUserName Filter میشود. اگر RecordCount صفر باشد User مجاز نیست؛ Message نمایش داده و Application با DoCmd.Quit بسته میشود. در غیر این صورت Welcome Message نشان داده میشود و برنامه فعال میماند.
تشخیص User امکان کنترل رفتار Application بر اساس اشخاص مختلف را فراهم میکند؛ فصل ۴۰ سطوح دسترسی User را با جزئیات بیشتری بررسی میکند.
UserNameهای Table باید دقیقاً با String برگشتی API مطابقت داشته باشند. غلط املایی باعث میشود User معتبر Unauthorized تشخیص داده شود. Access در Comparison به Case حساس نیست، بنابراین Upper/Lower Case مشکل ایجاد نمیکند.
نویسنده تجربهای مشابه در Oracle—که Case-sensitive بود—شرح میدهد. Adminها گاهی User جدید را با Case یا Spelling اشتباه وارد میکردند و User نمیتوانست Login کند. استفاده از Lower روی هر دو String مشکل Case را حل میکرد، اما Spelling اشتباه را نمیتوان صرفاً با Code برطرف کرد.
فصل ۲۴ — ایمنسازی Database
پس از ساخت Application باید مانع شوید Userها خارج از User Interface طراحیشده Structure برنامه را تغییر دهند. قطعاً نباید Code را ویرایش کنند. برای Protect کردن VBA، از VBE گزینهٔ Project Properties را باز کنید، Protection Tab را انتخاب، Lock Project for Viewing را فعال و Password را دوبار وارد کنید. Project را Save کنید.
اما Application فقط Code نیست؛ Table، Query، Form و Report نیز دارد. User میتواند Table را Delete یا Report را Edit کند و چون Database Multiuser است، این تغییر روی دیگر کاربران نیز اثر میگذارد. فصل چند راه Protection را بررسی میکند.
استفاده از ACCDE برای Protect کردن Application
Database را میتوان به ACCDE Compile کرد. در Access 2010 از File و Save Database As/Make ACCDE استفاده میشود. ACCDE اجازهٔ تغییر Form، Report یا VBA Code را به User نمیدهد؛ اما Table و Query و Data همچنان تا حدی قابل تغییرند، پس Protection کامل نیست.
مشکل دیگر این است که Developer نیز در همان ACCDE نمیتواند Form، Report یا VBA را تغییر دهد. در Application حرفهای Userها معمولاً پس از Rollout تغییرات میخواهند؛ بسیاری از Problemها نیز فقط بعد از استفادهٔ جدی چند User آشکار میشوند.
برای تغییر باید ACCDB اصلی را ویرایش و ACCDE جدید بسازید. اگر Data در ACCDE/نسخهٔ عملیاتی تغییر کرده باشد باید Data را به ACCDB اصلی برگردانید. این Process میتواند پیچیده و مستعد Error شود.
Lock کردن Application با VBA
میتوان Database Propertyها را طوری تنظیم کرد که User فقط مسیرهای تعریفشده در UI را داشته باشد. همچنین میتوان روی Opening Form و Formهای بعدی Custom Ribbon قرار داد.
در Module استاندارد:
Sub DisableStartupProperties()
ChangeProperty "StartupShowDBWindow", dbBoolean, False
ChangeProperty "StartupShowStatusBar", dbBoolean, False
ChangeProperty "AllowBuiltinToolbars", dbBoolean, False
ChangeProperty "AllowFullMenus", dbBoolean, False
ChangeProperty "AllowBreakIntoCode", dbBoolean, False
ChangeProperty "AllowSpecialKeys", dbBoolean, False
ChangeProperty "AllowBypassKey", dbBoolean, False
ChangeProperty "AllowShortcutMenus", dbBoolean, False
End Sub
Function ChangeProperty(strPropName As String, _
varPropType As Variant, varPropValue As Variant) As Integer
Dim dbs As Database, prp As Property
Const conPropNotFoundError = 3270
Set dbs = CurrentDb
On Error GoTo Change_Err
dbs.Properties(strPropName) = varPropValue
ChangeProperty = True
Change_Bye:
Exit Function
Change_Err:
If Err = conPropNotFoundError Then
Set prp = dbs.CreateProperty(strPropName, varPropType, varPropValue)
dbs.Properties.Append prp
Resume Next
Else
ChangeProperty = False
Resume Change_Bye
End If
End Function
ChangeProperty Property موجود را تغییر میدهد و اگر Property پیدا نشود با Error 3270 آن را Create و Append میکند. DisableStartupProperties Propertyهای Startup، Toolbar/Menu، Break Into Code، Special Key، Bypass Key و Shortcut Menu را False میکند. در نتیجه مثلاً SHIFT/BYPASS و BREAK برای دورزدن Startup محدود میشوند و Navigation Window نمایش داده نمیشود.
پس از اجرای Code فوراً Database را نبندید تا مراحل بعد تکمیل شوند. تغییر Propertyها پس از Exit و Load دوباره اثر میگذارند.
ساخت Ribbon خالی
Table سیستمی USysRibbons بسازید با دو Field:
RibbonName از نوع TextRibbonXML از نوع Memo
برای دیدن System Tableها، Navigation Options را باز و Show System Objects را فعال کنید. در USysRibbons یک Record با RibbonName برابر MyRibbon و XML زیر وارد کنید:
<customUI
xmlns="http://schemas.microsoft.com/office/2006/01/customui">
<ribbon startFromScratch="true">
</ribbon>
</customUI>
startFromScratch="true" Ribbon را از صفر میسازد و در این مثال عملاً فقط File Tab باقی میماند. در Application واقعی میتوان Commandهای Custom را به XML افزود.
یک Opening Form مانند Main بسازید و از Access Options در بخش Current Database آن را بهعنوان Display Form انتخاب کنید. در Design View، Propertyِ Ribbon Name Form را روی MyRibbon قرار دهید.
ساخت Back Door برای Maintenance
اگر همهٔ Propertyها Lock شوند، Developer نیز باید راهی برای Maintenance داشته باشد. کتاب یک Hotkey مخفی پیشنهاد میکند. روی Opening Form، Propertyِ Key Preview را Yes کنید تا Keypressها به Form Event برسند.
در Module استاندارد Procedure معکوس بسازید:
Sub EnableStartupProperties()
ChangeProperty "StartupShowDBWindow", dbBoolean, True
ChangeProperty "StartupShowStatusBar", dbBoolean, True
ChangeProperty "AllowBuiltinToolbars", dbBoolean, True
ChangeProperty "AllowFullMenus", dbBoolean, True
ChangeProperty "AllowBreakIntoCode", dbBoolean, True
ChangeProperty "AllowSpecialKeys", dbBoolean, True
ChangeProperty "AllowBypassKey", dbBoolean, True
ChangeProperty "AllowShortcutMenus", dbBoolean, True
End Sub
و در Form:
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
If KeyCode = 191 And Shift = 1 Then
EnableStartupProperties
MsgBox "Security Disabled", vbInformation
End If
End Sub
در متن کتاب KeyCode برابر 191 برای Question Mark و Shift=1 در نظر گرفته شده است. با Focus روی Form و زدن SHIFT+?، Security Disabled Message ظاهر میشود. سپس Database را Close/Reload کنید تا تغییرها اثر کنند. Ribbon نیز باید از طریق File Tab به Default Access برگردانده شود.
نویسنده توصیه میکند این Hotkey را مستقیماً روی Live Version برای Maintenance استفاده نکنید، چون میتواند نسخهٔ عملیاتی را برای دیگران باز بگذارد. بهتر است Copy بگیرید، Security را روی Copy غیرفعال و تغییرها را انجام دهید، سپس نسخهٔ اصلاحشده را جایگزین Live Version کنید؛ با برنامهریزی مناسب Data عملیاتی باید حفظ شود.
شکل ۲۴-۱ — Opening Screen یک Database قفلشده
پس از Reload، File Tab Optionهای بسیار محدودی دارد، Access Settings حذف شده و Quick Access Toolbar نیز قابل Customize نیست. User عملاً فقط مسیر User Interface طراحیشده را دنبال میکند؛ Developer همچنان Hotkey مخفی خود را برای بازگرداندن Access دارد.
صفحهٔ پایانی فصل در نسخهٔ اصلی عمداً خالی است.