لقد تم تطبيق أمان الوصول في Java لفترة طويلة وتسمى بنية توفير هذا الأمان JAAS - خدمة مصادقة وتفويض Java. ستحاول هذه المراجعة كشف سر ماهية المصادقة والترخيص وما علاقة JAAS به. كيف تكون JAAS صديقة لـ Servlet API، وأين توجد مشاكل في علاقتهما.
أي أن المكون الإضافي سيأخذ في الاعتبار الملفات من هذا الموقع عند إنشاء أرشيف WAR لتطبيق الويب الخاص بنا. بالإضافة إلى ذلك، تشير وثائق Gradle War Plugin إلى أن هذا الدليل سيكون "جذر الأرشيف". وبالفعل يمكننا إنشاء دليل WEB-INF وإضافة ملف web.xml هناك. أي نوع من الملف هذا؟
من المهم التحقق من تحديد حاوية servlet بواسطة Tomcat (انظر رقم 1) والتحقق من العنوان الذي يتوفر فيه تطبيق الويب الخاص بنا (انظر رقم 2).
وهذا يعني أنه يمكننا وضع إعداد تكوين تسجيل الدخول JAAS في موارد تطبيق الويب الخاص بنا وبفضل Tomcat context سنكون قادرين على استخدامه. يجب أن يكون هذا الملف متاحًا كمورد لـ ClassLoader، لذا يجب أن يكون مساره كما يلي:
مقدمة
في هذه المراجعة أود مناقشة موضوع مثل أمان تطبيقات الويب. لدى Java العديد من التقنيات التي توفر الأمان:-
" بنية أمان منصة Java SE "، يمكن قراءة المزيد من التفاصيل حول ذلك في الدليل من Oracle: " بنية أمان منصة JavaTM SE ". تصف هذه البنية مدى حاجتنا إلى تأمين تطبيقات Java الخاصة بنا في بيئة تشغيل Java SE. لكن هذا ليس موضوع حديثنا اليوم.
-
" Java Cryptography Architecture " هو امتداد Java الذي يصف تشفير البيانات. يمكنك قراءة المزيد عن هذا الامتداد على JavaRush في المراجعة " بنية تشفير Java: التعارف الأول " أو في الدليل من Oracle: " الدليل المرجعي لهندسة تشفير Java (JCA) ".
جاس
يعد JAAS امتدادًا لـ Java SE ويتم وصفه في الدليل المرجعي لخدمة مصادقة Java وتفويضها (JAAS) . وكما يوحي اسم التقنية، يصف JAAS كيفية إجراء المصادقة والترخيص:-
" المصادقة ": مترجمة من اليونانية، تعني كلمة "authentikos" "حقيقي، حقيقي". أي أن المصادقة هي اختبار للأصالة. أن كل من يتم المصادقة عليه هو حقًا ما يقولونه.
-
" الترخيص ": مترجم من الإنجليزية يعني "الإذن". أي أن التفويض هو التحكم في الوصول الذي يتم إجراؤه بعد المصادقة الناجحة.
- رخصة قيادته بمثابة تمثيل للشخص كمستخدم للطريق
- جواز سفره، باعتباره تمثيلاً للشخص كمواطن في بلده
- جواز سفره الأجنبي، كتمثيل للشخص كمشارك في العلاقات الدولية
- بطاقة مكتبته في المكتبة، باعتبارها تمثيلاً للشخص كقارئ ملحق بالمكتبة
تطبيق ويب
لذلك، نحن بحاجة إلى تطبيق ويب. سيساعدنا نظام بناء المشروع التلقائي Gradle في إنشائه. بفضل استخدام Gradle، يمكننا، من خلال تنفيذ أوامر صغيرة، تجميع مشروع Java بالتنسيق الذي نحتاجه، وإنشاء بنية الدليل الضرورية تلقائيًا، وغير ذلك الكثير. يمكنك قراءة المزيد عن Gradle في النظرة العامة القصيرة: " مقدمة موجزة عن Gradle " أو في الوثائق الرسمية " Gradle Getting Started ". نحن بحاجة إلى تهيئة المشروع (التهيئة)، ولهذا الغرض، يحتوي Gradle على مكون إضافي خاص: " Gradle Init Plugin " (Init هو اختصار للتهيئة، وسهل التذكر). لاستخدام هذا البرنامج المساعد، قم بتشغيل الأمر في سطر الأوامر:gradle init --type java-application
بعد الانتهاء بنجاح، سيكون لدينا مشروع جافا. دعونا الآن نفتح البرنامج النصي لبناء مشروعنا للتحرير. البرنامج النصي للبناء هو ملف يسمى build.gradle
، والذي يصف الفروق الدقيقة في بناء التطبيق. ومن هنا الاسم، بناء البرنامج النصي. يمكننا القول أن هذا هو برنامج نصي لبناء المشروع. Gradle هي أداة متعددة الاستخدامات، حيث يتم توسيع إمكانياتها الأساسية باستخدام المكونات الإضافية. لذلك، أولاً وقبل كل شيء، دعونا ننتبه إلى كتلة "المكونات الإضافية":
plugins {
id 'java'
id 'application'
}
افتراضيًا، قام Gradle، وفقًا لما حددناه " --type java-application
"، بإعداد مجموعة من بعض المكونات الإضافية الأساسية، أي تلك المكونات الإضافية المضمنة في توزيع Gradle نفسه. إذا ذهبت إلى قسم "المستندات" (أي الوثائق) على موقع الويب gradle.org ، فعندئذ على اليسار في قائمة المواضيع في قسم "المرجع"، نرى قسم " المكونات الإضافية الأساسية "، أي. قسم يحتوي على وصف لهذه المكونات الإضافية الأساسية جدًا. دعنا نختار المكونات الإضافية التي نحتاجها بالضبط، وليس تلك التي أنشأها Gradle لنا. وفقًا للوثائق، يوفر " Gradle Java Plugin " العمليات الأساسية باستخدام كود Java، مثل تجميع التعليمات البرمجية المصدر. أيضًا، وفقًا للوثائق، يوفر لنا " البرنامج المساعد لتطبيق Gradle " أدوات للعمل مع "تطبيق JVM القابل للتنفيذ"، أي. باستخدام تطبيق Java الذي يمكن تشغيله كتطبيق مستقل (على سبيل المثال، تطبيق وحدة تحكم أو تطبيق بواجهة مستخدم خاصة به). اتضح أننا لسنا بحاجة إلى البرنامج المساعد "التطبيق"، لأن... لا نحتاج إلى تطبيق مستقل، بل نحتاج إلى تطبيق ويب. دعونا حذفه. بالإضافة إلى إعداد "mainClassName" المعروف فقط لهذا البرنامج المساعد. علاوة على ذلك، في نفس قسم " التعبئة والتوزيع " حيث تم توفير الرابط إلى وثائق البرنامج الإضافي للتطبيق، يوجد رابط إلى البرنامج الإضافي Gradle War. يوفر Gradle War Plugin ، كما هو مذكور في الوثائق، الدعم لإنشاء تطبيقات ويب Java بتنسيق الحرب. يعني تنسيق WAR أنه بدلاً من أرشيف JAR، سيتم إنشاء أرشيف WAR. ويبدو أن هذا هو ما نحتاجه. أيضًا، كما تقول الوثائق، "يعمل المكون الإضافي War على توسيع مكون Java الإضافي". أي أنه يمكننا استبدال مكون Java الإضافي بملحق الحرب. لذلك، ستبدو كتلة المكونات الإضافية الخاصة بنا في النهاية كما يلي:
plugins {
id 'war'
}
يُقال أيضًا في وثائق "Gradle War Plugin" أن المكون الإضافي يستخدم "تخطيط مشروع" إضافي. تتم ترجمة التخطيط من اللغة الإنجليزية كموقع. أي أن ملحق الحرب يتوقع بشكل افتراضي وجود موقع معين من الملفات التي سيستخدمها في مهامه. وسوف يستخدم الدليل التالي لتخزين ملفات تطبيق الويب: src/main/webapp
يتم وصف سلوك البرنامج المساعد على النحو التالي:
web.xml
- هذا هو "واصف النشر" أو "واصف النشر". هذا ملف يصف كيفية تكوين تطبيق الويب الخاص بنا للعمل. يحدد هذا الملف الطلبات التي سيتعامل معها تطبيقنا وإعدادات الأمان وغير ذلك الكثير. يشبه في جوهره إلى حد ما ملف البيان من ملف JAR (راجع " العمل مع ملفات البيان: الأساسيات "). يخبرك ملف Manifest عن كيفية العمل مع تطبيق Java (أي أرشيف JAR)، ويخبرك ملف web.xml عن كيفية العمل مع تطبيق Java Web (أي أرشيف WAR). لم ينشأ مفهوم "واصف النشر" من تلقاء نفسه، ولكن تم وصفه في المستند " مواصفات Servlet API"". يعتمد أي تطبيق ويب Java على "Servlet API". من المهم أن نفهم أن هذه واجهة برمجة تطبيقات - أي أنها وصف لبعض عقود التفاعل. تطبيقات الويب ليست تطبيقات مستقلة. فهي تعمل على خادم ويب. ، الذي يوفر اتصالات الشبكة مع المستخدمين. أي أن خادم الويب هو نوع من "الحاوية" لتطبيقات الويب. وهذا أمر منطقي، لأننا نريد كتابة منطق تطبيق الويب، أي ما هي الصفحات التي سيراها المستخدم وكيف يجب أن يتفاعلوا مع تصرفات المستخدم. ونحن لا نريد أن نكتب تعليمات برمجية لكيفية إرسال الرسالة إلى المستخدم، وكيف سيتم نقل بايت من المعلومات وغيرها من الأشياء ذات المستوى المنخفض والتي تتطلب جودة كبيرة. بالإضافة إلى ذلك، اتضح أن تطبيقات الويب كلها مختلفة، لكن نقل البيانات هو نفسه، أي أنه سيتعين على مليون مبرمج كتابة تعليمات برمجية لنفس الغرض مرارًا وتكرارًا، لذا فإن خادم الويب مسؤول عن بعض تفاعلات المستخدم وتبادل البيانات، ويكون تطبيق الويب والمطور مسؤولين عن إنشاء تلك البيانات. ومن أجل ربط هذين الجزأين، أي. خادم الويب وتطبيق الويب، فأنت بحاجة إلى عقد للتفاعل بينهما، أي. ما هي القواعد التي سيتبعونها للقيام بذلك؟ من أجل وصف العقد بطريقة أو بأخرى، وكيف يجب أن يبدو التفاعل بين تطبيق الويب وخادم الويب، تم اختراع Servlet API. ومن المثير للاهتمام، حتى إذا كنت تستخدم أطر عمل مثل Spring، فلا تزال هناك واجهة برمجة تطبيقات Servlet تعمل تحت الغطاء. أي أنك تستخدم Spring، ويعمل Spring مع Servlet API نيابةً عنك. اتضح أن مشروع تطبيق الويب الخاص بنا يجب أن يعتمد على Servlet API. في هذه الحالة، ستكون واجهة برمجة تطبيقات Servlet تابعة. كما نعلم، يسمح لك Gradle أيضًا بوصف تبعيات المشروع بطريقة تعريفية. تصف المكونات الإضافية كيفية إدارة التبعيات. على سبيل المثال، يقدم Java Gradle Plugin طريقة إدارة التبعية "testImplementation"، والتي تنص على أن مثل هذه التبعية مطلوبة فقط للاختبارات. لكن البرنامج المساعد Gradle War يضيف طريقة لإدارة التبعية "providedCompile"، والتي تنص على أن مثل هذه التبعية لن يتم تضمينها في أرشيف WAR لتطبيق الويب الخاص بنا. لماذا لا نقوم بتضمين Servlet API في أرشيف WAR الخاص بنا؟ لأنه سيتم توفير واجهة برمجة تطبيقات Servlet لتطبيق الويب الخاص بنا بواسطة خادم الويب نفسه. إذا كان خادم الويب يوفر واجهة برمجة تطبيقات Servlet، فإن الخادم يسمى حاوية servlet. لذلك، تقع على عاتق خادم الويب مسؤولية تزويدنا بـ Servlet API، وتقع على عاتقنا مسؤولية توفير ServletAPI فقط في وقت تجميع التعليمات البرمجية. لهذا providedCompile
. وبالتالي، ستبدو كتلة التبعيات كما يلي:
dependencies {
providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
testImplementation 'junit:junit:4.12'
}
لذلك، دعونا نعود إلى ملف web.xml. افتراضيًا، لا يقوم Gradle بإنشاء أي واصف نشر، لذلك نحتاج إلى القيام بذلك بأنفسنا. لنقم بإنشاء دليل src/main/webapp/WEB-INF
، وسنقوم فيه بإنشاء ملف XML يسمى web.xml
. الآن دعونا نفتح "مواصفات Java Servlet" نفسها والفصل " الفصل 14 واصف النشر ". كما هو مذكور في "14.3 واصف النشر"، يتم وصف مستند XML الخاص بواصف النشر بواسطة المخطط http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd . يصف مخطط XML العناصر التي يمكن أن تتكون منها الوثيقة وبأي ترتيب يجب أن تظهر. ما هي إلزامية والتي ليست كذلك. بشكل عام، فهو يصف بنية المستند ويسمح لك بالتحقق مما إذا كان مستند XML مكونًا بشكل صحيح. الآن دعونا نستخدم المثال من الفصل " 14.5 أمثلة "، ولكن يجب تحديد المخطط للإصدار 3.1، أي.
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd
سوف تبدو فارغة لدينا web.xml
مثل هذا:
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<display-name>JAAS Example</display-name>
</web-app>
دعونا الآن نصف servlet الذي سنحميه باستخدام JAAS. في السابق، أنشأ Gradle فئة التطبيق لنا. دعونا نحوله إلى servlet. كما هو مذكور في المواصفات الواردة في " الفصل 2 واجهة Servlet "، أنه " بالنسبة لمعظم الأغراض، سيقوم المطورون بتوسيع HttpServlet لتنفيذ servlet الخاصة بهم "، أي لجعل فئة ما servlet، تحتاج إلى وراثة هذه الفئة من HttpServlet
:
public class App extends HttpServlet {
public String getGreeting() {
return "Secret!";
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().print(getGreeting());
}
}
كما قلنا، فإن Servlet API عبارة عن عقد بين الخادم وتطبيق الويب الخاص بنا. يسمح لنا هذا العقد بوصف أنه عندما يتصل مستخدم بالخادم، سيقوم الخادم بإنشاء طلب من المستخدم في شكل كائن HttpServletRequest
وتمريره إلى servlet. كما سيزود servlet بكائن HttpServletResponse
حتى يتمكن servlet من كتابة رد عليه للمستخدم. بمجرد الانتهاء من تشغيل servlet، سيكون الخادم قادرًا على تزويد المستخدم باستجابة بناءً عليه HttpServletResponse
. أي أن servlet لا يتواصل مباشرة مع المستخدم، بل مع الخادم فقط. لكي يعرف الخادم أن لدينا servlet وما هي الطلبات التي يجب استخدامها، نحتاج إلى إخبار الخادم بذلك في واصف النشر:
<servlet>
<servlet-name>app</servlet-name>
<servlet-class>jaas.App</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/secret</url-pattern>
</servlet-mapping>
في هذه الحالة، /secret
لن يتم توجيه جميع الطلبات إلى servlet الخاص بنا بالاسم app
، والذي يتوافق مع الفئة jaas.App
. كما قلنا سابقًا، لا يمكن نشر تطبيق الويب إلا على خادم الويب. يمكن تثبيت خادم الويب بشكل منفصل (مستقل). ولكن لأغراض هذه المراجعة، فإن الخيار البديل مناسب - يعمل على خادم مضمن. هذا يعني أنه سيتم إنشاء الخادم وتشغيله برمجيًا (سيقوم البرنامج الإضافي بذلك نيابةً عنا)، وفي نفس الوقت سيتم نشر تطبيق الويب الخاص بنا عليه. يتيح لك نظام بناء Gradle استخدام المكوّن الإضافي " Gradle Gretty Plugin " لهذه الأغراض:
plugins {
id 'war'
id 'org.gretty' version '2.2.0'
}
بالإضافة إلى ذلك، يحتوي البرنامج المساعد Gretty على وثائق جيدة . لنبدأ بحقيقة أن المكون الإضافي Gretty يسمح لك بالتبديل بين خوادم الويب المختلفة. تم توضيح ذلك بمزيد من التفصيل في الوثائق: " التبديل بين حاويات servlet ". فلننتقل إلى Tomcat، لأن... وهو من الأكثر استخدامًا، كما أنه يحتوي على توثيق جيد والعديد من الأمثلة والمشكلات التي تم تحليلها:
gretty {
// Переключаемся с дефолтного Jetty на Tomcat
servletContainer = 'tomcat8'
// Укажем Context Path, он же Context Root
contextPath = '/jaas'
}
يمكننا الآن تشغيل "gradle appRun" ومن ثم سيكون تطبيق الويب الخاص بنا متاحًا على http://localhost:8080/jaas/secret
المصادقة
تتكون إعدادات المصادقة غالبًا من جزأين: الإعدادات على جانب الخادم والإعدادات على جانب تطبيق الويب الذي يتم تشغيله على هذا الخادم. لا يمكن لإعدادات الأمان لتطبيق الويب إلا أن تتفاعل مع إعدادات الأمان لخادم الويب، إذا لم يكن هناك سبب آخر غير أن تطبيق الويب لا يمكنه إلا أن يتفاعل مع خادم الويب. لم يكن عبثًا أن تحولنا إلى Tomcat، لأن... يتمتع Tomcat ببنية موصوفة جيدًا (راجع " Apache Tomcat 8 Architecture "). من وصف هذه البنية يتضح أن Tomcat، كخادم ويب، يمثل تطبيق الويب كسياق معين، وهو ما يسمى " سياق Tomcat ". يتيح هذا السياق لكل تطبيق ويب أن يكون له إعداداته الخاصة، معزولة عن تطبيقات الويب الأخرى. بالإضافة إلى ذلك، يمكن لتطبيق الويب التأثير على إعدادات هذا السياق. مرنة ومريحة. للحصول على فهم أعمق، نوصي بقراءة المقالة " فهم حاويات سياق Tomcat " وقسم وثائق Tomcat " حاوية السياق ". كما هو مذكور أعلاه، يمكن لتطبيق الويب الخاص بنا التأثير على سياق Tomcat الخاص بتطبيقنا باستخدام ملف/META-INF/context.xml
. وأحد الإعدادات المهمة جدًا التي يمكننا التأثير عليها هي عوالم الأمان. العوالم الأمنية هي نوع من "المنطقة الأمنية". المنطقة التي تم تحديد إعدادات أمان محددة لها. وبناء على ذلك، عند استخدام مجال الأمان، فإننا نطبق إعدادات الأمان المحددة لهذا المجال. تتم إدارة عوالم الأمان بواسطة حاوية، أي. خادم الويب، وليس تطبيق الويب الخاص بنا. يمكننا فقط إخبار الخادم بنطاق الأمان الذي يجب توسيعه ليشمل تطبيقنا. تصف وثائق Tomcat في القسم " مكون المجال " المجال كمجموعة من البيانات حول المستخدمين وأدوارهم في إجراء المصادقة. يوفر Tomcat مجموعة من تطبيقات عالم الأمان المختلفة، أحدها هو " Jaas Realm ". بعد أن فهمنا القليل من المصطلحات، دعنا نصف سياق Tomcat في الملف /META-INF/context.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Realm className="org.apache.catalina.realm.JAASRealm"
appName="JaasLogin"
userClassNames="jaas.login.UserPrincipal"
roleClassNames="jaas.login.RolePrincipal"
configFile="jaas.config" />
</Context>
appName
- اسم التطبيق. سيحاول Tomcat مطابقة هذا الاسم مع الأسماء المحددة في ملف configFile
. configFile
- هذا هو "ملف تكوين تسجيل الدخول". يمكن رؤية مثال على ذلك في وثائق JAAS: " الملحق ب: مثال لتكوينات تسجيل الدخول ". بالإضافة إلى ذلك، من المهم أن يتم البحث في هذا الملف أولاً في الموارد. لذلك، يمكن لتطبيق الويب الخاص بنا توفير هذا الملف نفسه. السمات userClassNames
وتحتوي roleClassNames
على إشارة إلى الفئات التي تمثل مدير المستخدم. يفصل JAAS بين مفهومي "المستخدم" و"الدور" كمفهومين مختلفين java.security.Principal
. دعونا تصف الطبقات المذكورة أعلاه. لنقم بإنشاء أبسط تطبيق لمبدأ المستخدم:
public class UserPrincipal implements Principal {
private String name;
public UserPrincipal(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
}
سنكرر نفس التنفيذ تمامًا لـ RolePrincipal
. كما ترون من الواجهة، فإن الشيء الرئيسي بالنسبة للمدير هو تخزين وإرجاع بعض الاسم (أو المعرف) الذي يمثل المدير. الآن، لدينا عالم أمني، لدينا فئات رئيسية. يبقى ملء الملف من configFile
السمة " "، المعروفة أيضًا باسم login configuration file
. يمكن العثور على وصفه في وثائق Tomcat: " The Realm Component ".
\src\main\resources\jaas.config
لنقم بتعيين محتويات هذا الملف:
JaasLogin {
jaas.login.JaasLoginModule required debug=true;
};
ومن الجدير بالذكر أن context.xml
نفس الاسم يستخدم هنا وفي. يؤدي هذا إلى تعيين عالم الأمان إلى LoginModule. لذلك، أخبرنا سياق Tomcat بالفئات التي تمثل المبادئ الأساسية، بالإضافة إلى وحدة تسجيل الدخول التي يجب استخدامها. كل ما يتعين علينا القيام به هو تنفيذ وحدة تسجيل الدخول هذه. ربما يكون LoginModule أحد أكثر الأشياء إثارة للاهتمام في JAAS. ستساعدنا الوثائق الرسمية في تطوير LoginModule: " خدمة مصادقة وتفويض Java (JAAS): دليل مطور LoginModule ". دعونا ننفذ وحدة تسجيل الدخول. لنقم بإنشاء فئة تنفذ الواجهة LoginModule
:
public class JaasLoginModule implements LoginModule {
}
أولاً نوضح طريقة التهيئة LoginModule
:
private CallbackHandler handler;
private Subject subject;
@Override
public void initialize(Subject subject, CallbackHandler callbackHandler, <String, ?> sharedState, Map<String, ?> options) {
handler = callbackHandler;
this.subject = subject;
}
ستوفر هذه الطريقة Subject
، وسنقوم بمراجعتها وملئها بالمعلومات حول المبادئ الأساسية. سنقوم أيضًا بحفظه للاستخدام المستقبلي CallbackHandler
، وهو ما تم تقديمه لنا. وبمساعدة، CallbackHandler
يمكننا طلب معلومات مختلفة حول موضوع المصادقة بعد قليل. يمكنك قراءة المزيد عنها CallbackHandler
في القسم المقابل من الوثائق: " الدليل المرجعي لـ JAAS: CallbackHandler ". بعد ذلك، يتم تنفيذ طريقة login
المصادقة Subject
. هذه هي المرحلة الأولى من المصادقة:
@Override
public boolean login() throws LoginException {
// Добавляем колбэки
Callback[] callbacks = new Callback[2];
callbacks[0] = new NameCallback("login");
callbacks[1] = new PasswordCallback("password", true);
// При помощи колбэков получаем через CallbackHandler логин и пароль
try {
handler.handle(callbacks);
String name = ((NameCallback) callbacks[0]).getName();
String password = String.valueOf(((PasswordCallback) callbacks[1]).getPassword());
// Далее выполняем валидацию.
// Тут просто для примера проверяем определённые значения
if (name != null && name.equals("user123") && password != null && password.equals("pass123")) {
// Сохраняем информацию, которая будет использована в методе commit
// Не "пачкаем" Subject, т.к. не факт, что commit выполнится
// Для примера проставим группы вручную, "хардcodeно".
login = name;
userGroups = new ArrayList<String>();
userGroups.add("admin");
return true;
} else {
throw new LoginException("Authentication failed");
}
} catch (IOException | UnsupportedCallbackException e) {
throw new LoginException(e.getMessage());
}
}
ومن المهم login
ألا نغير Subject
. يجب أن تحدث مثل هذه التغييرات فقط في طريقة التأكيد commit
. بعد ذلك، يجب علينا وصف طريقة تأكيد المصادقة الناجحة:
@Override
public boolean commit() throws LoginException {
userPrincipal = new UserPrincipal(login);
subject.getPrincipals().add(userPrincipal);
if (userGroups != null && userGroups.size() > 0) {
for (String groupName : userGroups) {
rolePrincipal = new RolePrincipal(groupName);
subject.getPrincipals().add(rolePrincipal);
}
}
return true;
}
قد يبدو غريباً الفصل بين الطريقة login
و commit
. لكن النقطة المهمة هي أنه يمكن دمج وحدات تسجيل الدخول. ومن أجل المصادقة الناجحة، قد يكون من الضروري أن تعمل العديد من وحدات تسجيل الدخول بنجاح. وفقط إذا عملت جميع الوحدات الضرورية، فاحفظ التغييرات. هذه هي المرحلة الثانية من المصادقة. لننتهي من الطرق abort
والطرق logout
:
@Override
public boolean abort() throws LoginException {
return false;
}
@Override
public boolean logout() throws LoginException {
subject.getPrincipals().remove(userPrincipal);
subject.getPrincipals().remove(rolePrincipal);
return true;
}
يتم استدعاء الأسلوب abort
عند فشل المرحلة الأولى من المصادقة. يتم استدعاء الطريقة logout
عند تسجيل خروج النظام. بعد تنفيذنا Login Module
وتكوينه Security Realm
، نحتاج الآن إلى الإشارة إلى web.xml
حقيقة أننا نريد استخدام واحد محدد Login Config
:
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>JaasLogin</realm-name>
</login-config>
لقد حددنا اسم مجال الأمان الخاص بنا وحددنا طريقة المصادقة - BASIC. يعد هذا أحد أنواع المصادقة الموضحة في Servlet API في القسم " 13.6 المصادقة ". بقي ن
GO TO FULL VERSION