سؤال

لقد قمت بكتابة تطبيق Silverlight 2 للتواصل مع خدمة WCF (BasicHttpBinding).الموقع الذي يستضيف محتوى Silverlight محمي باستخدام موفر عضوية ASP.NET.يمكنني الوصول إلى المستخدم الحالي باستخدام HttpContext.Current.User.Identity.Name من خدمة WCF الخاصة بي، وقمت بتشغيل AspNetCompatibilityRequirementsMode.

أريد الآن كتابة تطبيق Windows باستخدام نفس خدمة الويب بالضبط.للتعامل مع المصادقة قمت بتمكين خدمة المصادقة, ، ويمكن الاتصال بـ "تسجيل الدخول" لمصادقة المستخدم الخاص بي ...اوكي كل خير ...ولكن كيف يمكنني الحصول على ملف تعريف ارتباط المصادقة هذا على عميل الخدمة الآخر الخاص بي؟!

تتم استضافة كلتا الخدمتين على نفس المجال

  • MyDataService.svc <- الذي يتعامل مع بياناتي
  • AuthenticationService.svc <- الذي يجب على تطبيق Windows الاتصال به للمصادقة.

لا أرغب في إنشاء خدمة جديدة لعميل Windows أو استخدام رابط آخر...

تعد خدمات تطبيقات العميل بديلاً آخر، ولكن جميع الأمثلة تقتصر على إظهار كيفية الحصول على المستخدم والأدوار وملف التعريف الخاص به...ولكن بمجرد أن تتم مصادقتنا باستخدام خدمات تطبيقات العميل، يجب أن تكون هناك طريقة لإرفاق ملف تعريف ارتباط المصادقة بعملاء الخدمة عند الاتصال مرة أخرى بالخادم نفسه.

وفقًا لمدخلات الزملاء، فإن الحل هو إضافة نقطة نهاية wsHttpBinding، ولكنني آمل أن أتمكن من التغلب على ذلك...

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

المحلول

لقد وجدت أخيرًا طريقة لإنجاز هذا العمل.للمصادقة أنا أستخدم "خدمة المصادقة WCF".عند مصادقة الخدمة سيحاول تعيين ملف تعريف ارتباط المصادقة.أحتاج إلى إخراج ملف تعريف الارتباط هذا من الاستجابة، وإضافته إلى أي طلب آخر يتم تقديمه إلى خدمات الويب الأخرى على نفس الجهاز.يبدو الكود للقيام بذلك كما يلي:

var authService = new AuthService.AuthenticationServiceClient();
var diveService = new DiveLogService.DiveLogServiceClient();

string cookieHeader = "";
using (OperationContextScope scope = new OperationContextScope(authService.InnerChannel))
{
    HttpRequestMessageProperty requestProperty = new HttpRequestMessageProperty();
    OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = requestProperty;
    bool isGood = authService.Login("jonas", "jonas", string.Empty, true);
    MessageProperties properties = OperationContext.Current.IncomingMessageProperties;
    HttpResponseMessageProperty responseProperty = (HttpResponseMessageProperty)properties[HttpResponseMessageProperty.Name];
    cookieHeader = responseProperty.Headers[HttpResponseHeader.SetCookie];                
}

using (OperationContextScope scope = new OperationContextScope(diveService.InnerChannel))
{
    HttpRequestMessageProperty httpRequest = new HttpRequestMessageProperty();
    OperationContext.Current.OutgoingMessageProperties.Add(HttpRequestMessageProperty.Name, httpRequest);
    httpRequest.Headers.Add(HttpRequestHeader.Cookie, cookieHeader);
    var res = diveService.GetDives();
}      

كما ترون، لدي عميلان للخدمة، أحدهما لخدمة المصادقة والآخر للخدمة التي سأستخدمها بالفعل.ستستدعي الكتلة الأولى طريقة تسجيل الدخول وتلتقط ملف تعريف ارتباط المصادقة من الاستجابة.ستضيف الكتلة الثانية الرأس إلى الطلب قبل استدعاء طريقة الخدمة "GetDives".

لست سعيدًا بهذا الرمز على الإطلاق، وأعتقد أن البديل الأفضل قد يكون استخدام "مرجع الويب" بدلاً من "مرجع الخدمة" واستخدام مكدس .NET 2.0 بدلاً من ذلك.

نصائح أخرى

خدمات الويب، مثل تلك التي تم إنشاؤها بواسطة WCF، غالبًا ما يتم استخدامها بشكل أفضل بطريقة "عديمة الحالة"، لذلك يبدأ كل اتصال بخدمة ويب من جديد.يؤدي هذا إلى تبسيط رمز الخادم، حيث لا توجد حاجة إلى "جلسة" تستدعي حالة العميل.كما أنه يبسط رمز العميل حيث ليست هناك حاجة للاحتفاظ بالتذاكر أو ملفات تعريف الارتباط أو غيرها من الأجهزة التي تفترض شيئًا ما عن حالة الخادم.

يؤدي إنشاء خدمتين بالطريقة الموضحة إلى تقديم الحالة.العميل إما "تمت مصادقته" أو "لم تتم مصادقته"، ويجب على MyDataService.svc معرفة أيهما.

كما حدث، وجدت أن WCF يعمل بشكل جيد عند استخدام موفر العضوية للمصادقة كل اتصل بالخدمة.لذلك، في المثال الموضح، قد ترغب في إضافة gubbins مصادقة موفر العضوية إلى تكوين الخدمة لـ MyDataService، وليس لديك خدمة مصادقة منفصلة على الإطلاق.

للحصول على التفاصيل، راجع مقالة MSDN هنا.

[الأمر الجذاب جدًا في هذا بالنسبة لي، لأنني كسول، هو أن هذا تصريحي تمامًا.أنا ببساطة أقوم بتوزيع إدخالات التكوين الصحيحة لـ MembershipProvider الخاص بي في app.config للتطبيق و!البنغو!تتم مصادقة جميع المكالمات لكل عقد في الخدمة.]

من العدل أن نلاحظ أن هذا لن يكون سريعًا بشكل خاص.إذا كنت تستخدم SQL Server لقاعدة بيانات المصادقة الخاصة بك، فسيكون لديك استدعاء واحد على الأقل، وربما اثنين من استدعاءات الإجراءات المخزنة لكل استدعاء خدمة.في العديد من الحالات (خصوصًا بالنسبة لروابط HTTP)، سيكون الحمل الزائد لاستدعاء الخدمة نفسه أكبر؛إذا لم يكن الأمر كذلك، ففكر في تنفيذ التنفيذ الخاص بك لموفر العضوية الذي يقوم بتخزين طلبات المصادقة مؤقتًا.

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

على العميل، قم بتعديل علامة <binding> الخاصة بالخدمة (داخل <system.serviceModel>) لتشمل:السماح بملفات تعريف الارتباط = "صحيح"

يجب أن يحتفظ التطبيق الآن بملف تعريف الارتباط ويستخدمه.ستلاحظ أن IsLoggedIn يعود الآن صحيحًا بعد تسجيل الدخول - ويعرض خطأ إذا كنت لا تسمح بملفات تعريف الارتباط.

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

سأحاول أن أسخر من شيء ما لاحقًا وأرسله إليك.

--larsw

يجب عليك إلقاء نظرة على CookieContainer كائن في System.Net.يسمح هذا الكائن للعميل غير المستعرض بالتمسك بملفات تعريف الارتباط.هذا هو ما استخدمه فريقي في آخر مرة واجهنا فيها هذه المشكلة.

هنا مقالة مختصرة حول كيفية المضي قدمًا في استخدامه.قد يكون هناك أفضل منها، ولكن هذا يجب أن يبدأ.

لقد سلكنا طريق عديمي الجنسية لمجموعتنا الحالية من خدمات WCF وتطبيق Silverlight 2.من الممكن جعل Silverlight 2 يعمل مع الخدمات المرتبطة بأمان TransportWithMessageCredential، على الرغم من أن الأمر يتطلب بعض رموز الأمان المخصصة على جانب Silverlight.والنتيجة هي أن أي تطبيق يمكنه الوصول إلى الخدمات ببساطة عن طريق تعيين اسم المستخدم وكلمة المرور في رؤوس الرسائل.يمكن القيام بذلك مرة واحدة في تطبيق IRequestChannel المخصص بحيث لا يحتاج المطورون أبدًا إلى القلق بشأن تعيين القيم بأنفسهم.على الرغم من أن WCF لديه طريقة سهلة للمطورين للقيام بذلك والتي أعتقد أنها ServiceProxy.Security.Username وserviceProxy.Security.Password أو شيء بسيط بنفس القدر.

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

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