آموزش تابع ORIGINAL_LOGIN در SQL Server
این راهنما تابع ORIGINAL_LOGIN را از مفهوم پایه تا کاربرد سازمانی بررسی میکند. برای مشاهده جایگاه این تابع در کنار سایر ابزارهای هویتی، راهنمای جامع توابع امنیتی SQL Server را نیز مطالعه کنید.
مقدمه
در SQL Server هر اتصال فقط یک نام ساده نیست؛ Login در سطح Instance، User در سطح Database، SID، شناسه عددی Principal و Context مؤثر اجرا لایههای جداگانهای هستند. تابع ORIGINAL_LOGIN برای پاسخ دادن به بخشی مشخص از این مدل طراحی شده است و نام Login اولیهای را برمیگرداند که نشست SQL Server را ایجاد کرده است، حتی اگر Context بعداً تغییر کند.
کاربرد اصلی آن شامل ممیزی غیرقابلابهام، تشخیص آغازکننده واقعی عملیات و بررسی زنجیرههای EXECUTE AS است. با این حال، خروجی تابع باید همراه نام دیتابیس، شناسه نشست، زمان و توابع مکمل تفسیر شود. ثبت یک نام بدون Context میتواند در زمان جعل هویت، اجرای ماژول با مالک متفاوت یا استفاده از Connection Pooling به برداشت نادرست منجر شود.
این مقاله مثالها را از فراخوانی پایه شروع میکند و سپس به گزارشگیری از Catalog Viewها، مدیریت NULL، ممیزی، خطای رایج و الگوی بهینه میرسد. همه Queryها برای Microsoft SQL Server نوشته شدهاند؛ عملیات وابسته به مجوز ممکن است در محیط محدود پیام کمبود دسترسی برگرداند.
تعریف، نحو و خروجی
نام Login اولیهای را برمیگرداند که نشست SQL Server را ایجاد کرده است، حتی اگر Context بعداً تغییر کند. محدوده معنایی این تابع «سرور و نشست» است؛ بنابراین نباید نتیجه آن را خودکار به Principal لایه دیگر تعمیم داد.
نحو تابع
SELECT ORIGINAL_LOGIN() AS SecurityValue;
پارامترها
- نحو رسمی: ORIGINAL_LOGIN()
- آرگومان اختیاری، اگر وجود داشته باشد، باید از نوع سازگار با نام یا شناسه همان سطح باشد.
- برای ورودی نامعتبر یا Principal غیرقابل مشاهده، NULL را بهعنوان یک حالت واقعی مدیریت کنید.
نوع خروجی
نوع خروجی مستند تابع sysname است. پیش از ذخیرهسازی، ستون مقصد را با همین نوع یا یک تبدیل آگاهانه تعریف کنید تا بریدگی متن، تبدیل ضمنی و از دست رفتن SID رخ ندهد.
تفاوت مهم با تابع نزدیک چنین است: SUSER_SNAME() هویت Login مؤثر جاری را نشان میدهد اما ORIGINAL_LOGIN() مبدأ نشست را نگه میدارد. نکته عملی نیز این است که Connection Pooling به معنی ایجاد اتصال فیزیکی تازه برای هر درخواست نیست؛ هویت برنامه و تنظیمات Pool باید در طراحی Audit لحاظ شوند.
مدل امنیتی و تفسیر درست نتیجه
Login اجازه ورود به موتور یا سرویس را مدل میکند، ولی Database User نماینده همان هویت یا یک هویت مستقل در دیتابیس است. نگاشت این دو معمولاً با SID انجام میشود. در نتیجه، مساوی بودن نامها یک قرارداد رایج است و تضمین معماری محسوب نمیشود.
هنگام استفاده از ORIGINAL_LOGIN ابتدا مشخص کنید سؤال شما درباره آغازکننده اتصال، Context مؤثر Login، User جاری دیتابیس، شناسه عددی یا SID است. سپس تابعی را انتخاب کنید که دقیقاً همان لایه را پوشش دهد و خروجی را کنار ORIGINAL_LOGIN()، SUSER_SNAME() و CURRENT_USER مقایسه کنید.
در سامانههای حرفهای، نتیجه یک تابع امنیتی نباید مستقیماً نقش مجوزدهنده داشته باشد. کنترل دسترسی با GRANT و DENY، Roleها، Row-Level Security، مالکیت و Module Signing انجام میشود؛ تابع هویتی بیشتر برای مشاهده، Audit، برچسبگذاری و عیبیابی است.
مثالهای عملی مستقل
مثال 1: فراخوانی پایه و مشاهده هویت جاری
در این سناریو هدف آن است که رفتار ORIGINAL_LOGIN در «فراخوانی پایه و مشاهده هویت جاری» بهصورت مستقل دیده شود. Query را در یک پنجره جدا اجرا کنید و نتیجه را با نوع اتصال و Context امنیتی همان نشست تطبیق دهید.
SELECT ORIGINAL_LOGIN() AS [ORIGINAL_LOGIN_Result];
| خروجی | تفسیر |
|---|
| یک نام یا شناسه وابسته به Context جاری | نتیجه واقعی تابع ORIGINAL_LOGIN به Principalها و مجوزهای محیط وابسته است. |
سادهترین آزمون برای شناخت نتیجه تابع در همان اتصال است. این نمونه بهجای اتکا به یک مقدار از پیشفرضشده، معنای خروجی و محدودیت محیط اجرا را صریح نگه میدارد.
مثال 2: ثبت نتیجه همراه با مشخصات نشست
در این سناریو هدف آن است که رفتار ORIGINAL_LOGIN در «ثبت نتیجه همراه با مشخصات نشست» بهصورت مستقل دیده شود. Query را در یک پنجره جدا اجرا کنید و نتیجه را با نوع اتصال و Context امنیتی همان نشست تطبیق دهید.
SELECT
@@SPID AS SessionId,
DB_NAME() AS DatabaseName,
ORIGINAL_LOGIN() AS SecurityValue,
SYSDATETIMEOFFSET() AS CapturedAt;
| خروجی | تفسیر |
|---|
| یک ردیف شامل نشست، دیتابیس، مقدار امنیتی و زمان | نتیجه واقعی تابع ORIGINAL_LOGIN به Principalها و مجوزهای محیط وابسته است. |
قرار دادن Context کنار نتیجه، شواهد ممیزی را قابل تفسیر میکند. این نمونه بهجای اتکا به یک مقدار از پیشفرضشده، معنای خروجی و محدودیت محیط اجرا را صریح نگه میدارد.
مثال 3: تبدیل و ذخیره نتیجه در متغیر یا جدول
در این سناریو هدف آن است که رفتار ORIGINAL_LOGIN در «تبدیل و ذخیره نتیجه در متغیر یا جدول» بهصورت مستقل دیده شود. Query را در یک پنجره جدا اجرا کنید و نتیجه را با نوع اتصال و Context امنیتی همان نشست تطبیق دهید.
DECLARE @Audit TABLE
(
EventName nvarchar(50),
SecurityValue nvarchar(128),
CapturedAt datetime2(0)
);
INSERT @Audit VALUES
(N'ورود به فرایند',CONVERT(nvarchar(128),ORIGINAL_LOGIN()),SYSDATETIME());
SELECT * FROM @Audit;
| خروجی | تفسیر |
|---|
| یک رخداد ممیزی با نام هویت مؤثر | نتیجه واقعی تابع ORIGINAL_LOGIN به Principalها و مجوزهای محیط وابسته است. |
این الگو نتیجه تابع را یکبار محاسبه میکند و برای ثبت Audit یا ادامه پردازش آماده نگه میدارد. این نمونه بهجای اتکا به یک مقدار از پیشفرضشده، معنای خروجی و محدودیت محیط اجرا را صریح نگه میدارد.
مثال 4: استفاده در شرط امنیتی کنترلشده
در این سناریو هدف آن است که رفتار ORIGINAL_LOGIN در «استفاده در شرط امنیتی کنترلشده» بهصورت مستقل دیده شود. Query را در یک پنجره جدا اجرا کنید و نتیجه را با نوع اتصال و Context امنیتی همان نشست تطبیق دهید.
SELECT
CASE
WHEN ORIGINAL_LOGIN() IS NULL THEN N'هویت قابل تشخیص نیست'
ELSE N'هویت شناسایی شد'
END AS SecurityCheck;
| خروجی | تفسیر |
|---|
| پیام وضعیت شناسایی هویت | نتیجه واقعی تابع ORIGINAL_LOGIN به Principalها و مجوزهای محیط وابسته است. |
وجود مقدار بهتنهایی مجوز ایجاد نمیکند؛ تصمیم دسترسی باید بر پایه Role و Permission باشد. این نمونه بهجای اتکا به یک مقدار از پیشفرضشده، معنای خروجی و محدودیت محیط اجرا را صریح نگه میدارد.
مثال 5: مقایسه هویت اولیه و هویت مؤثر
در این سناریو هدف آن است که رفتار ORIGINAL_LOGIN در «مقایسه هویت اولیه و هویت مؤثر» بهصورت مستقل دیده شود. Query را در یک پنجره جدا اجرا کنید و نتیجه را با نوع اتصال و Context امنیتی همان نشست تطبیق دهید.
SELECT
ORIGINAL_LOGIN() AS OriginalLogin,
SUSER_SNAME() AS EffectiveLogin,
CURRENT_USER AS DatabaseUser,
CONVERT(nvarchar(128),ORIGINAL_LOGIN()) AS FunctionValue;
| خروجی | تفسیر |
|---|
| چهار ستون برای تشخیص اختلاف Context | نتیجه واقعی تابع ORIGINAL_LOGIN به Principalها و مجوزهای محیط وابسته است. |
این مقایسه مرز Login سطح سرور و User سطح دیتابیس را روشن و جعل هویت را آشکار میکند. این نمونه بهجای اتکا به یک مقدار از پیشفرضشده، معنای خروجی و محدودیت محیط اجرا را صریح نگه میدارد.
مثال 6: مدیریت ورودی یا خروجی NULL
در این سناریو هدف آن است که رفتار ORIGINAL_LOGIN در «مدیریت ورودی یا خروجی NULL» بهصورت مستقل دیده شود. Query را در یک پنجره جدا اجرا کنید و نتیجه را با نوع اتصال و Context امنیتی همان نشست تطبیق دهید.
SELECT COALESCE(CONVERT(nvarchar(128),ORIGINAL_LOGIN()),N'نامشخص') AS SafeValue;
| خروجی | تفسیر |
|---|
| NULL یا مقدار جایگزین کنترلشده | نتیجه واقعی تابع ORIGINAL_LOGIN به Principalها و مجوزهای محیط وابسته است. |
کنترل صریح NULL مانع تصمیم اشتباه و ثبت داده مبهم در فرایندهای امنیتی میشود. این نمونه بهجای اتکا به یک مقدار از پیشفرضشده، معنای خروجی و محدودیت محیط اجرا را صریح نگه میدارد.
مثال 7: بررسی حالت مرزی و Context جانشین
در این سناریو هدف آن است که رفتار ORIGINAL_LOGIN در «بررسی حالت مرزی و Context جانشین» بهصورت مستقل دیده شود. Query را در یک پنجره جدا اجرا کنید و نتیجه را با نوع اتصال و Context امنیتی همان نشست تطبیق دهید.
BEGIN TRY
EXECUTE AS USER=N'dbo';
SELECT ORIGINAL_LOGIN() AS ValueUnderDatabaseImpersonation;
REVERT;
END TRY
BEGIN CATCH
IF USER_NAME()=N'dbo' REVERT;
SELECT ERROR_MESSAGE() AS ErrorMessage;
END CATCH;
| خروجی | تفسیر |
|---|
| مقدار Context جانشین یا پیام کمبود مجوز | نتیجه واقعی تابع ORIGINAL_LOGIN به Principalها و مجوزهای محیط وابسته است. |
حالتهای مرزی باید در محیط آزمایشی و با کمترین سطح دسترسی لازم بررسی شوند. این نمونه بهجای اتکا به یک مقدار از پیشفرضشده، معنای خروجی و محدودیت محیط اجرا را صریح نگه میدارد.
مثال 8: گزارش سازمانی از کاتالوگهای امنیتی
در این سناریو هدف آن است که رفتار ORIGINAL_LOGIN در «گزارش سازمانی از کاتالوگهای امنیتی» بهصورت مستقل دیده شود. Query را در یک پنجره جدا اجرا کنید و نتیجه را با نوع اتصال و Context امنیتی همان نشست تطبیق دهید.
SELECT TOP (20)
sp.name,sp.type_desc,sp.is_disabled,
CONVERT(nvarchar(128),ORIGINAL_LOGIN()) AS CurrentContextValue
FROM sys.server_principals AS sp
WHERE sp.type IN ('S','U','G','E','X')
ORDER BY sp.name;
| خروجی | تفسیر |
|---|
| فهرست Principalها همراه با Context اجرای گزارش | نتیجه واقعی تابع ORIGINAL_LOGIN به Principalها و مجوزهای محیط وابسته است. |
ترکیب تابع با Catalog View برای گزارش دسترسی مناسب است؛ مشاهده Metadata همچنان تابع مجوز اجراکننده است. این نمونه بهجای اتکا به یک مقدار از پیشفرضشده، معنای خروجی و محدودیت محیط اجرا را صریح نگه میدارد.
مثال 9: روش اشتباه و نسخه اصلاحشده
در این سناریو هدف آن است که رفتار ORIGINAL_LOGIN در «روش اشتباه و نسخه اصلاحشده» بهصورت مستقل دیده شود. Query را در یک پنجره جدا اجرا کنید و نتیجه را با نوع اتصال و Context امنیتی همان نشست تطبیق دهید.
-- روش اشتباه: اعطای مجوز فقط با مقایسه متن نام
-- IF CONVERT(nvarchar(128),ORIGINAL_LOGIN())=N'admin' SELECT N'مجاز';
-- روش صحیح: بررسی عضویت Role و مجوز واقعی
SELECT
IS_ROLEMEMBER(N'db_datareader') AS IsDataReader,
HAS_PERMS_BY_NAME(DB_NAME(),N'DATABASE',N'SELECT') AS HasSelectPermission;
| خروجی | تفسیر |
|---|
| صفر، یک یا NULL برای وضعیت Role و Permission | نتیجه واقعی تابع ORIGINAL_LOGIN به Principalها و مجوزهای محیط وابسته است. |
نام هویت داده ممیزی است؛ مجوز واقعی باید با سازوکار Role و Permission ارزیابی شود. این نمونه بهجای اتکا به یک مقدار از پیشفرضشده، معنای خروجی و محدودیت محیط اجرا را صریح نگه میدارد.
مثال 10: الگوی کارایی با محاسبه یکباره
در این سناریو هدف آن است که رفتار ORIGINAL_LOGIN در «الگوی کارایی با محاسبه یکباره» بهصورت مستقل دیده شود. Query را در یک پنجره جدا اجرا کنید و نتیجه را با نوع اتصال و Context امنیتی همان نشست تطبیق دهید.
DECLARE @SecurityValue nvarchar(128)=CONVERT(nvarchar(128),ORIGINAL_LOGIN());
SELECT o.name,o.type_desc,@SecurityValue AS SecurityValue
FROM sys.objects AS o
WHERE o.object_id>0
AND o.name LIKE N'sp[_]%'
ORDER BY o.name;
| خروجی | تفسیر |
|---|
| اشیای منطبق و یک مقدار امنیتی ثابت برای Query | نتیجه واقعی تابع ORIGINAL_LOGIN به Principalها و مجوزهای محیط وابسته است. |
در Queryهای بزرگ نتیجه ثابت نشست را یکبار محاسبه کنید؛ از قرار دادن تابع روی ستون فیلترشونده پرهیز کنید. این نمونه بهجای اتکا به یک مقدار از پیشفرضشده، معنای خروجی و محدودیت محیط اجرا را صریح نگه میدارد.
خطاهای رایج و روش رفع آنها
اولین خطا، تفسیر ORIGINAL_LOGIN در Scope اشتباه است. اگر تابع در سطح دیتابیس معنا دارد، نتیجه آن نام Login سرور نیست؛ اگر در سطح سرور کار میکند، از آن نمیتوان عضویت Role دیتابیس را نتیجه گرفت. Scope را پیش از نوشتن شرط مشخص کنید.
دومین خطا، نادیده گرفتن EXECUTE AS و زنجیره مالکیت است. یک Stored Procedure ممکن است با Context دیگری اجرا شود، در حالی که Login اولیه نشست ثابت مانده است. ثبت همزمان ORIGINAL_LOGIN()، SUSER_SNAME() و CURRENT_USER اختلاف را آشکار میکند.
سومین خطا، فرض غیرممکن بودن NULL یا اتکا به مشاهده کامل Metadata است. Principal حذفشده، شناسه نامعتبر، محدودیت مجوز یا تفاوت سرویس ابری میتواند خروجی را تغییر دهد. برای NULL مسیر کنترلشده، هشدار و آزمون خودکار تعریف کنید.
نکات کارایی و بهینهسازی
فراخوانی منفرد ORIGINAL_LOGIN معمولاً هزینه سنگینی ندارد؛ مشکل زمانی ایجاد میشود که همان مقدار ثابت نشست برای هر ردیف یک مجموعه بزرگ دوباره محاسبه یا به تبدیلهای زنجیرهای وارد شود. نتیجه را یکبار در متغیر با نوع مناسب ذخیره کنید.
در Predicateها تابع را روی ستون ایندکسشده اعمال نکنید. ابتدا مقدار امنیتی را به نوع ستون تبدیل و سپس ستون را مستقیماً با پارامتر مقایسه کنید. این الگو احتمال Seek، تخمین Cardinality بهتر و استفاده مجدد از Plan را افزایش میدهد.
برای ارزیابی واقعی از Actual Execution Plan، SET STATISTICS IO, TIME و Query Store استفاده کنید. قبل و بعد از تغییر را با داده و پارامتر مشابه اندازهگیری کنید؛ سریع بودن یک اجرای آزمایشی روی جدول کوچک معیار کافی برای محیط تولید نیست.
بهترین روشها
- Scope تابع و پرسش امنیتی را پیش از پیادهسازی مستند کنید.
- هویت اولیه و هویت مؤثر را در Audit از هم جدا نگه دارید.
- نتیجه را با نوع داده مناسب و بدون بریدگی ذخیره کنید.
- NULL و نبود مجوز مشاهده Metadata را مدیریت کنید.
- بهجای مقایسه نام، Permission و Role واقعی را بررسی کنید.
- برای عملیات حساس از کمترین سطح دسترسی و Module Signing بهره بگیرید.
- رفتار EXECUTE AS و REVERT را در تست خودکار پوشش دهید.
- تفاوت SQL Server، Azure SQL و Managed Instance را پیش از مهاجرت آزمایش کنید.
کاربردهای واقعی در پروژه
در سامانه مالی میتوان هویت اولیه اتصال و Context مؤثر را همراه شماره سند ثبت کرد تا تغییرات بعدی قابل پیگیری باشد. این داده باید فقط برای تیم مجاز قابل مشاهده و در برابر UPDATE یا DELETE غیرمجاز محافظت شود.
در یک پلتفرم چندمستاجری، تابع هویتی برای عیبیابی مفید است، اما Tenant از Claim یا جدول نگاشت معتبر استخراج میشود و Row-Level Security دسترسی ردیفی را اعمال میکند. آمیختن نام Login با شناسه مشتری یک ریسک طراحی است.
در پروژه مهاجرت، مقایسه SIDهای Login و User به کشف کاربران یتیم کمک میکند. تهیه گزارش قبل از Cutover، بازسازی Loginها با SID درست و آزمون مجوزهای مؤثر از قطعی سرویس و دسترسی بیش از حد جلوگیری میکند.
سؤالات متداول
پرسش 1: ORIGINAL_LOGIN دقیقاً چه مسئلهای را حل میکند؟
هویت یا شناسه امنیتی مرتبط با Context اجرا را بهشکل استاندارد SQL Server در اختیار Query میگذارد. نتیجه برای عیبیابی، Audit و گزارش مجوزها ارزشمند است، اما بهتنهایی جایگزین کنترل Permission، Role و سیاست حداقل دسترسی نیست. در مورد ORIGINAL_LOGIN نیز باید محدودیت «Connection Pooling به معنی ایجاد اتصال فیزیکی تازه برای هر درخواست نیست؛ هویت برنامه و تنظیمات Pool باید در طراحی Audit لحاظ شوند» در آزمونها لحاظ شود.
پرسش 2: برای شروع یادگیری ORIGINAL_LOGIN چه پیشنیازی لازم است؟
شناخت تفاوت Login سطح سرور، User سطح دیتابیس، SID، Context نشست و دستور EXECUTE AS ضروری است. تمرین روی یک Instance آزمایشی با چند Login و User باعث میشود تفاوت خروجیها بهصورت عملی و بدون خطر برای محیط تولید دیده شود. در مورد ORIGINAL_LOGIN نیز باید محدودیت «Connection Pooling به معنی ایجاد اتصال فیزیکی تازه برای هر درخواست نیست؛ هویت برنامه و تنظیمات Pool باید در طراحی Audit لحاظ شوند» در آزمونها لحاظ شود.
پرسش 3: آیا استفاده از ORIGINAL_LOGIN در پروژههای تجاری مفید است؟
بله، بهویژه در سامانههای چندکاربره، پنلهای مدیریتی و فرایندهای ممیزی. ارزش تجاری زمانی ایجاد میشود که خروجی تابع همراه زمان، نشست، نام برنامه، عملیات و شناسه رکورد ثبت شود تا تحلیل رخداد و پاسخگویی ممکن باشد. در مورد ORIGINAL_LOGIN نیز باید محدودیت «Connection Pooling به معنی ایجاد اتصال فیزیکی تازه برای هر درخواست نیست؛ هویت برنامه و تنظیمات Pool باید در طراحی Audit لحاظ شوند» در آزمونها لحاظ شود.
پرسش 4: برای طراحی Audit سازمانی با ORIGINAL_LOGIN چه روشی مناسب است؟
ابتدا نیازهای حقوقی و عملیاتی تعیین و سپس هویت اولیه و مؤثر، زمان UTC، شناسه نشست و جزئیات عملیات ثبت شود. در پروژههای حساس، بازبینی معماری امنیت، مشاوره SQL Server و آزمون نفوذ مجوزها پیش از انتشار توصیه میشود. در مورد ORIGINAL_LOGIN نیز باید محدودیت «Connection Pooling به معنی ایجاد اتصال فیزیکی تازه برای هر درخواست نیست؛ هویت برنامه و تنظیمات Pool باید در طراحی Audit لحاظ شوند» در آزمونها لحاظ شود.
پرسش 5: ORIGINAL_LOGIN با توابع مشابه چه تفاوتی دارد؟
مرز اصلی در Scope و نوع شناسه است: برخی توابع Login سطح سرور، برخی User سطح دیتابیس و برخی SID یا شناسه عددی را برمیگردانند. انتخاب درست باید بر پایه سؤال دقیق کسبوکار باشد، نه شباهت ظاهری نام توابع. در مورد ORIGINAL_LOGIN نیز باید محدودیت «Connection Pooling به معنی ایجاد اتصال فیزیکی تازه برای هر درخواست نیست؛ هویت برنامه و تنظیمات Pool باید در طراحی Audit لحاظ شوند» در آزمونها لحاظ شود.
پرسش 6: آیا میتوان از نتیجه تابع در Trigger یا Stored Procedure استفاده کرد؟
از نظر فنی در بسیاری از سناریوها بله، اما باید رفتار مالکیت، EXECUTE AS، ماژول امضاشده و Connection Pooling آزمایش شود. پیش از پیادهسازی تراکنشی، نوع و طول ستون Audit و سیاست خطا نیز مشخص شود تا عملیات اصلی مختل نشود. در مورد ORIGINAL_LOGIN نیز باید محدودیت «Connection Pooling به معنی ایجاد اتصال فیزیکی تازه برای هر درخواست نیست؛ هویت برنامه و تنظیمات Pool باید در طراحی Audit لحاظ شوند» در آزمونها لحاظ شود.
پرسش 7: رایجترین خطا هنگام استفاده از ORIGINAL_LOGIN چیست؟
رایجترین خطا یکی دانستن Login و Database User و سپس اعطای دسترسی بر پایه مقایسه یک رشته است. خطای دیگر نادیده گرفتن NULL، Metadata Visibility و Context جانشین است. ثبت خروجی توابع مکمل به تشخیص علت کمک میکند. در مورد ORIGINAL_LOGIN نیز باید محدودیت «Connection Pooling به معنی ایجاد اتصال فیزیکی تازه برای هر درخواست نیست؛ هویت برنامه و تنظیمات Pool باید در طراحی Audit لحاظ شوند» در آزمونها لحاظ شود.
پرسش 8: آیا فراخوانی ORIGINAL_LOGIN باعث افت کارایی میشود؟
یک فراخوانی معمولاً سبک است، اما تکرار غیرضروری در میلیونها ردیف یا قرار دادن تبدیل روی ستون ایندکسشده میتواند هزینه بسازد. مقدار ثابت نشست را یکبار در متغیر بگیرید و Predicate را SARGable نگه دارید. در مورد ORIGINAL_LOGIN نیز باید محدودیت «Connection Pooling به معنی ایجاد اتصال فیزیکی تازه برای هر درخواست نیست؛ هویت برنامه و تنظیمات Pool باید در طراحی Audit لحاظ شوند» در آزمونها لحاظ شود.
پرسش 9: بهترین روش امنیتی برای استفاده از نتیجه چیست؟
نتیجه را برای مشاهده و ممیزی بهکار ببرید و تصمیم مجوز را به Role، GRANT، DENY، Row-Level Security یا ماژول امضاشده بسپارید. داده ممیزی باید حداقل دسترسی، نگهداری مشخص و محافظت در برابر تغییر داشته باشد. در مورد ORIGINAL_LOGIN نیز باید محدودیت «Connection Pooling به معنی ایجاد اتصال فیزیکی تازه برای هر درخواست نیست؛ هویت برنامه و تنظیمات Pool باید در طراحی Audit لحاظ شوند» در آزمونها لحاظ شود.
پرسش 10: سازگاری تابع در نسخههای SQL Server و Azure چگونه است؟
هسته تابع در نسخههای رایج پشتیبانی میشود، اما Azure SQL Database، Managed Instance، Fabric و Synapse در Metadata سطح سرور یا EXECUTE AS تفاوت دارند. پیش از مهاجرت، مستندات نسخه هدف و تست خودکار سازگاری بررسی شود. در مورد ORIGINAL_LOGIN نیز باید محدودیت «Connection Pooling به معنی ایجاد اتصال فیزیکی تازه برای هر درخواست نیست؛ هویت برنامه و تنظیمات Pool باید در طراحی Audit لحاظ شوند» در آزمونها لحاظ شود.
سؤالات مصاحبه تخصصی
سؤال مصاحبه 1: تفاوت Login و User چیست؟
Login Principal سطح سرور برای ورود است و User Principal سطح دیتابیس برای مجوزهای همان دیتابیس. نگاشت معمولاً با SID انجام میشود و نام یکسان تضمینکننده یکسان بودن هویت نیست.
سؤال مصاحبه 2: ORIGINAL_LOGIN چه Scope و خروجیای دارد؟
Scope آن سرور و نشست و نوع خروجی sysname است. پاسخ کامل باید کاربرد، رفتار NULL، جعل هویت و تفاوت با تابع مشابه را نیز توضیح دهد.
سؤال مصاحبه 3: چرا ORIGINAL_LOGIN و SUSER_SNAME را همزمان ثبت میکنیم؟
اولی آغازکننده نشست و دومی Context مؤثر Login را نشان میدهد. اختلاف آنها میتواند اجرای EXECUTE AS LOGIN یا زنجیرهای از جعل هویت را مشخص کند.
سؤال مصاحبه 4: چگونه از افت کارایی جلوگیری میکنید؟
مقدار ثابت نشست را یکبار محاسبه، نوع داده را هماهنگ و Predicate را SARGable میکنم؛ سپس Plan واقعی، IO، CPU و Query Store را پیش و پس از تغییر مقایسه میکنم.
سؤال مصاحبه 5: آیا نام کاربر برای مجوزدهی کافی است؟
خیر. نام برای مشاهده مناسب است؛ مجوز باید با Role، Permission، RLS یا Module Signing اعمال شود و همه مسیرها با کمترین سطح دسترسی آزمون شوند.
چکلیست نهایی
- Scope سرور یا دیتابیس مشخص شد.
- نوع خروجی و ستون مقصد هماهنگ است.
- NULL و Principal نامعتبر پوشش داده شد.
- هویت اولیه و مؤثر جدا ثبت میشوند.
- مجوز بر پایه Role و Permission است.
- EXECUTE AS در تست وجود دارد.
- Plan و IO در بار واقعی اندازهگیری شده است.
- محدودیت نسخه مقصد بررسی شده است.
جمعبندی
تابع ORIGINAL_LOGIN زمانی ارزش واقعی دارد که در مدل درست امنیت SQL Server تفسیر شود. نام Login اولیهای را برمیگرداند که نشست SQL Server را ایجاد کرده است، حتی اگر Context بعداً تغییر کند و برای ممیزی غیرقابلابهام، تشخیص آغازکننده واقعی عملیات و بررسی زنجیرههای EXECUTE AS مناسب است. نتیجه باید همراه Context، زمان و توابع مکمل ثبت شود و هرگز بهتنهایی جایگزین کنترل مجوز نباشد.
برای مرور تفاوت همه توابع این مجموعه به مقاله مادر توابع امنیتی SQL Server بازگردید. در محیط تولید، ابتدا سناریوهای Login، User، SID، EXECUTE AS، NULL و Metadata Visibility را در محیط آزمایشی تکرار و سپس با پایش Query Store منتشر کنید.