ما هي أفضل طريقة للتحقق من وجود ملف من إجراء SQL Server 2005 المخزن؟

StackOverflow https://stackoverflow.com/questions/16634

  •  08-06-2019
  •  | 
  •  

سؤال

لقد استخدمنا الإجراء xp_fileexist المخزن "غير الموثق" لسنوات في SQL Server 2000 ولم نواجه أي مشكلة فيه.في عام 2005، يبدو أنهم قاموا بتعديل السلوك قليلاً ليُرجع دائمًا الرقم 0 إذا لم يكن حساب المستخدم المُنفِّذ مسؤول نظام.يبدو أيضًا أنه يُرجع صفرًا إذا كانت خدمة SQL Server تعمل ضمن حساب LocalSystem وكنت تحاول التحقق من ملف على الشبكة.

أرغب في الابتعاد عن xp_fileexist.هل لدى أي شخص طريقة أفضل للتحقق من وجود ملف في موقع الشبكة من داخل الإجراء المخزن؟

هل كانت مفيدة؟

المحلول

ربما يكون الإجراء المخزن لـ CLR هو ما تبحث عنه.تُستخدم هذه بشكل عام عندما تحتاج إلى التفاعل مع النظام بطريقة ما.

نصائح أخرى

سيتعين عليك وضع علامة على CLR كـ EXTERNAL_ACCESS حتى تتمكن من الوصول إلى مساحة الاسم System.IO، ولكن مع سير الأمور، فهذه ليست طريقة سيئة للقيام بذلك.

SAFE هي مجموعة الأذونات الافتراضية، ولكنها مقيدة للغاية.باستخدام الإعداد SAFE، يمكنك الوصول فقط إلى البيانات من قاعدة بيانات محلية لتنفيذ المنطق الحسابي على تلك البيانات.EXTERNAL_ACCESS هي الخطوة التالية في التسلسل الهرمي للأذونات.يتيح لك هذا الإعداد الوصول إلى الموارد الخارجية مثل نظام الملفات وعارض الأحداث في Windows وخدمات الويب.هذا النوع من الوصول إلى الموارد غير ممكن في SQL Server 2000 والإصدارات الأقدم.تعمل مجموعة الأذونات هذه أيضًا على تقييد العمليات مثل الوصول إلى المؤشر الذي يؤثر على قوة التجميع الخاص بك.تفترض مجموعة أذونات UNSAFE الثقة الكاملة في التجميع وبالتالي لا تفرض أي قيود على "أمان الوصول إلى التعليمات البرمجية".يشبه هذا الإعداد الطريقة التي تعمل بها الإجراءات المخزنة الموسعة، حيث تفترض أن التعليمات البرمجية بأكملها آمنة.ومع ذلك، يقوم هذا الإعداد بتقييد إنشاء التجميعات غير الآمنة للمستخدمين الذين لديهم أذونات مسؤول النظام.توصي Microsoft بتجنب إنشاء تجميعات غير آمنة قدر الإمكان.

ما زلت أعتقد أن إجراء CLR قد يكون أفضل رهان.لذا، أنا أقبل هذه الإجابة.ومع ذلك، إما أنني لست ذكيًا أو أنه من الصعب جدًا التنفيذ.تعمل خدمة SQL Server الخاصة بنا ضمن حساب محلي لأنه، وفقًا لميركوسوفت، هذه هي الطريقة الوحيدة للحصول على خادم مرتبط iSeries يعمل من مثيل SQL Server 2005 64 بت.عندما نقوم بتغيير خدمة SQL Server لتعمل باستخدام حساب مجال، فإن الأمر xp_fileexist يعمل بشكل جيد مع الملفات الموجودة على الشبكة.

لقد قمت بإنشاء هذا الإجراء المخزن لـ CLR وقمت بإنشائه باستخدام مستوى الإذن المعين على خارجي وقمت بالتوقيع عليه:

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Security.Principal;

public partial class StoredProcedures
{
    [Microsoft.SqlServer.Server.SqlProcedure]
    public static void FileExists(SqlString fileName, out SqlInt32 returnValue)
    {
        WindowsImpersonationContext originalContext = null;

        try
        {
            WindowsIdentity callerIdentity = SqlContext.WindowsIdentity;
            originalContext = callerIdentity.Impersonate();

            if (System.IO.File.Exists(Convert.ToString(fileName)))
            {
                returnValue = 1;
            }
            else
            {
                returnValue = 0;
            }
        }
        catch (Exception)
        {
            returnValue = -1;
        }
        finally
        {
            if (originalContext != null)
            {
                originalContext.Undo();
            }
        }
    }
}

ثم قمت بتشغيل أوامر TSQL هذه:

USE master
GO
CREATE ASYMMETRIC KEY FileUtilitiesKey FROM EXECUTABLE FILE = 'J:\FileUtilities.dll' 
CREATE LOGIN CLRLogin FROM ASYMMETRIC KEY FileUtilitiesKey 
GRANT EXTERNAL ACCESS ASSEMBLY TO CLRLogin 
ALTER DATABASE database SET TRUSTWORTHY ON;

ثم قمت بنشر CLR المخزن في قاعدة البيانات المستهدفة من Visual Studio واستخدمت TSQL للتنفيذ من SSMS الذي تم تسجيل الدخول باستخدام مصادقة Windows:

DECLARE @i INT
--EXEC FileExists '\\\\server\\share\\folder\\file.dat', @i OUT
EXEC FileExists 'j:\\file.dat', @i OUT
SELECT @i

سواء قمت بتجربة ملف محلي أو ملف شبكة، أحصل دائمًا على 0.ربما سأحاول مرة أخرى لاحقًا، لكن في الوقت الحالي، سأحاول السير في طريق مختلف.إذا كان لدى أي شخص بعض الضوء ليلقيه، فسيكون موضع تقدير كبير.

@ بول، يبدو أن هذا الرمز يجب أن يعمل.هل حاولت وضع بعض التتبع بهذه الطريقة للتأكد Convert.ToString(fileName) لا يتم رش الطريق بطريقة أو بأخرى؟

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top