مقدمة أمن الربيع الأساسية
لن أعطي الكثير من المقدمة لأمن الربيع هنا. للحصول على التفاصيل ، يرجى الرجوع إلى الوثائق الرسمية.
سأتحدث فقط عن الوظائف الأساسية لـ SpringSecurity:
بناء البيئة الأساسية
هنا نستخدم Springboot كإطار أساسي للمشروع. أنا أستخدم طريقة Maven لإدارة الحزم ، لذلك نقدم هنا أولاً طريقة دمج أمان الربيع.
<ependencies> ... <ERPEMENCED> <GORELID> ORG.SPRINGFRAMEWORK.BOOT </GroupID> <STIFACTID> Spring-Boot-Starter-Security </stifactid> </sependency> ... </reperencies>
ثم قم بإنشاء واجهة طلب طبقة الويب
@restController @requestMapping ("/user") الفئة العامة USERCONTROLLER {getMapping public string getUsers () {return "Hello Spring Security" ؛ }}بعد ذلك ، يمكنك تشغيل المشروع مباشرة والاتصال بالواجهة لرؤية التأثير.
الاتصال من خلال صفحة الويب
نقوم أولاً بإجراء مكالمة الواجهة عبر المتصفح والوصول مباشرة إلى http: // localhost: 8080/user. إذا كان من الممكن الوصول إلى الواجهة بشكل طبيعي ، فيجب عرض "Hello Spring Security".
لكن لا يمكننا الوصول إليه بشكل طبيعي ، ويظهر مربع إدخال المصادقة في الشكل أدناه
هذا لأنه في Springboot ، يكون أمان الربيع الافتراضي فعالًا. في هذا الوقت ، تكون الواجهات محمية ونحتاج إلى تمرير التحقق من الوصول إليها بشكل طبيعي. يوفر Spring Security مستخدمًا افتراضيًا ، واسم المستخدم هو مستخدم ، ويتم إنشاء كلمة المرور تلقائيًا عند بدء تشغيل المشروع.
عندما نتحقق من سجل بدء تشغيل المشروع ، سنجد السجل التالي
باستخدام كلمة مرور الأمان الافتراضية: 62CCF9CA-9FBE-4993-8566-8468CC33C28C
بالطبع ، يجب أن تكون كلمة المرور التي تراها مختلفة عن لي. نقوم بتسجيل الدخول مباشرة مع المستخدم وكلمة المرور في سجل بدء التشغيل.
بعد تسجيل الدخول بنجاح ، تقفز إلى الصفحة التي تسمى الواجهة بشكل طبيعي.
إذا كنت لا ترغب في تمكين أمان الربيع من البداية ، فيمكنك تكوين ما يلي في ملف التكوين:
# الأمن تمكين الأمان.
تم توفير مربع تسجيل الدخول الذي رأيته للتو بواسطة SpringSecurity ، والذي يسمى httpbasiclogin. هذا ليس ما نريده على منتجاتنا. أداء الواجهة الأمامية بشكل عام يؤدي التحقق من تسجيل الدخول إلى المستخدم من خلال تقديم النموذج ، لذلك نحتاج إلى تخصيص منطق المصادقة الخاص بنا.
تخصيص منطق مصادقة المستخدم
يجب أن يكون لكل نظام مجموعة من أنظمة المستخدم الخاصة به ، لذلك نحتاج إلى تخصيص منطق المصادقة الخاص بنا وواجهة تسجيل الدخول.
هنا نحتاج إلى تكوين SpringSecurity وفقًا لذلك
ConfigurationPublic Class BrowersecurityConfig يمتد WebSecurityConfigureRadapter {override تكوين الفراغ المحمي المحمي (httpsecurity http) يلقي الاستثناء {http.formlogin () // define صفحة تسجيل الدخول التي يتم نقلها عند الحاجة إلى تسجيل الدخول. التي لا تحتاج إلى حماية. anyrequest () // لأي طلب ، يمكنك الوصول إلى .Anuenticated () ؛ }}بعد ذلك ، قم بتكوين منطق مصادقة المستخدم ، لأن لدينا نظام المستخدم الخاص بنا.
ComponentPublic Class MyUserDetailsService تنفذ userDetailsService {private logger logger = loggerfactory.getLogger (getClass ()) ؛ Override public userDetails loadUserByUserName (اسم المستخدم username) يرمي usernamenotfoundException {logger.info ("اسم المستخدم المستخدم: {}" ، اسم المستخدم) ؛ // TODO وفقًا لاسم المستخدم ، ابحث عن كلمة المرور المقابلة ، وقم بتغليف معلومات المستخدم والعودة. المعلمات هي: اسم المستخدم ، كلمة المرور ، أذونات المستخدم مستخدم المستخدم = مستخدم جديد (اسم المستخدم ، "123456" ، AuthoritUtils.CommaseParatedStringToAuthorityList ("Admin")) ؛ إرجاع المستخدم ؛ }} لم نؤدي الكثير من التحقق هنا. يمكن ملء اسم المستخدم في الإرادة ، ولكن يجب أن تكون كلمة المرور "123456" حتى نتمكن من تسجيل الدخول بنجاح.
في الوقت نفسه ، يمكننا أن نرى أن المعلمة الثالثة لكائن المستخدم هنا تمثل أذونات المستخدم الحالي ، وقمنا بتعيينها على "المسؤول".
قم بتشغيل البرنامج لاختباره ، وسوف تجد أن واجهة تسجيل الدخول قد تغيرت.
هذا لأننا قمنا بتكوين http.formLogin() في ملف التكوين
دعنا فقط نملأ مستخدم هنا ، ثم نملأ إصدارًا خاطئًا (غير 123456). سيؤدي هذا إلى حث خطأ التحقق:
في الوقت نفسه ، على وحدة التحكم ، سيتم أيضًا طباعة المستخدم الذي تملأه للتو عند تسجيل الدخول.
الآن دعنا نحاول تسجيل الدخول بكلمة المرور الصحيحة. يمكنك أن تجد أنه سيمرر التحقق ويقفز إلى صفحة استدعاء الواجهة الصحيحة.
userDetails
الآن فقط ، عندما كنا نكتب MyUserDetailsService ، قمنا بتنفيذ طريقة وأعادنا UserDetails . هذا userDetails هو كائن يلف معلومات المستخدم ، والذي يحتوي على سبع طرق
الواجهة العامة userDetails يمتد مسلسل {// مجموعة معلومات الإذن المغلفة <؟ يمتد GrantedAuthority> getAuthorities () ؛ // معلومات كلمة المرور getPassword () ؛ // login username string getUserName () ؛ // ما إذا كان الحساب ينتهي صلاحية isAccAckountNonexPired () ؛ // ما إذا كان الحساب متجمدًا منطقيًا iSaccountnonlocked () ؛ // ما إذا كانت كلمة مرور الحساب تنتهي صلاحيتها ، فإن بعض الأنظمة التي لديها متطلبات كلمة مرور عالية ستستخدمها. بالمقارنة مع المستخدم مطلوب لإعادة تعيين كلمة المرور كل مرة واحدة من حين لآخر iscredentialsnonexpired () ؛ // هل الحساب متاح؟ منطقية isenabled () ؛}عندما نعيد مستخدم فئة تطبيق userDetails ، يمكننا تعيين المعلمات المقابلة من خلال طريقة منشئ المستخدم
تشفير كلمة المرور وفك التشفير
هناك واجهة PasswordEncoder في SpringSecurity
الواجهة العامة PasswordErcoder {// تشفير سلسلة كلمة المرور encode (charsevenence var1) ؛ // حدد كلمة المرور لمطابقة مطابقات منطقية (charsepress var1 ، string var2) ؛} نحتاج فقط إلى تنفيذ هذه الواجهة بأنفسنا وتكوينها في ملف التكوين.
هنا سأختبرها مؤقتًا مع فئة تنفيذ مقدمة بشكل افتراضي
// BrowerSecurityConfig @beanpublic passwordencoder passworkoder () {return new bcryptpasswordencoder () ؛ }استخدام التشفير:
ComponentPublic Class MyUserDetailsService تنفذ userDetailsService {private logger logger = loggerfactory.getLogger (getClass ()) ؛ Autowired passwordercoder passwordencoder ؛ Override public userDetails loadUserByUserName (اسم المستخدم username) يرمي usernamenotfoundException {logger.info ("اسم المستخدم المستخدم: {}" ، اسم المستخدم) ؛ سلسلة كلمة المرور = passwordencoder.encode ("123456") ؛ logger.info ("كلمة المرور: {}" ، كلمة المرور) ؛ . إرجاع المستخدم ؛ }}نحن هنا ببساطة تشفير 123456. يمكننا إجراء اختبارات وتجد أن كلمة المرور المطبوعة في كل مرة مختلفة. هذا هو دور bcryptpasswordencoder المكونة.
منطق مصادقة المستخدم المخصص
صفحة تسجيل الدخول المخصصة
في الاختبارات السابقة ، تم دائمًا استخدام واجهة تسجيل الدخول الافتراضية. أعتقد أن كل منتج لديه تصميم واجهة تسجيل الدخول الخاصة به ، لذلك سوف نتعرف على كيفية تخصيص صفحة تسجيل الدخول في هذا القسم.
لنكتب صفحة تسجيل دخول بسيطة أولاً
<! doctype html> <html lang = "en"> <head> <meta charset = "utf-8" <title> صفحة تسجيل الدخول </title> </head> <body> <h2> صفحة تسجيل الدخول المخصصة </h2> <form action = "/user/login" type = "text" name = "username"> </td> </tr> <tr> <td> كلمة المرور: </td> <td> <type type = "password" name = "password"> </td> </td> <tr> <td colspan = "2"
بعد الانتهاء من صفحة تسجيل الدخول ، تحتاج إلى تكوينها للأمن
// browersecurityconfig.java@overrideprotected configive (httpsecurity http) يلقي استثناء {http.formlogin () // تحديد صفحة تسجيل الدخول المراد نقلها إلى عندما يحتاج المستخدم إلى تسجيل الدخول. page.loginprocessingurl ("/user/login") // واجهة تسجيل الدخول المخصصة. . // قم بإيقاف تشغيل حماية CSRF}وبهذه الطريقة ، كلما وصلنا إلى الواجهة المحمية ، سيتم نقلنا إلى صفحة login.html
التعامل مع أنواع مختلفة من الطلبات
لأنه الآن ، يتم فصل النهايات الأمامية والخلفية بشكل عام ، توفر النهاية الخلفية واجهات للاتصال الأمامي للاتصال وإرجاع بيانات تنسيق JSON إلى الواجهة الأمامية. كما كان من قبل ، تم استدعاء الواجهة المحمية وتم إعادة توجيه قفزة الصفحة مباشرة. إنه مقبول على جانب الويب ، لكنه غير ممكن على جانب التطبيق ، لذلك نحن بحاجة إلى إجراء مزيد من المعالجة.
هذه فكرة بسيطة في الفرز
أولاً ، اكتب وحدة تحكم مخصصة وقفز إليها عندما تكون مصادقة الهوية مطلوبة.
RestControllerPublic prowsersecurityController {private logger logger = loggerFactory.getLogger (getClass ()) ؛ // التخزين المؤقت واسترداد معلومات الطلب الأصلي requestCache requestCache = جديد httpsessionrequestcache () ؛ // المستخدمة لإعادة توجيه إعادة توجيه redirectstrategratgy الخاصة = جديد defaultRedirectStrategy () ؛ /** * عندما تكون مصادقة الهوية مطلوبة ، قفز فوق * param request * @param response * regurn */ @requestmapping ("/anithing/require SaveDrequest = requestCache.getRequest (طلب ، استجابة) ؛ if (SaveDrequest! = null) {String TargetUrl = saveDrequest.getRedirecturl () ؛ logger.info ("طلب تشغيل القفزة هو:" + targeturl) ؛ if (stringUtils.endswithignoreCase (targeturl ، ".html")) {redirectStrategy.SendRedirect (طلب ، استجابة ، "/login.html") ؛ }} إرجاع BaserSponse الجديد ("تتطلب الخدمة التي تم الوصول إليها مصادقة الهوية ، يرجى توجيه المستخدم إلى صفحة تسجيل الدخول") ؛ }}بالطبع ، يجب تعديل ملف التكوين وفقًا لذلك ، لذلك لن أقوم بنشر الكود هنا. إنه لفتح الواجهة.
الامتدادات:
هنا نكتب الواجهة التي يتم الوصول إليها من صفحة ويب ، ثم نقفز إلى صفحة "/login.html". في الواقع ، يمكننا توسيعه وتكوين عنوان القفز إلى ملف التكوين ، والذي سيكون أكثر ملاءمة.
تسجيل دخول المعالجة المخصصة ناجحة/فشل
في الاختبارات السابقة ، تم تنفيذ إعادة توجيه الصفحة بعد تسجيل الدخول الناجح.
في حالة فصل النهايات الأمامية والخلفية ، إذا قامنا بتسجيل الدخول بنجاح ، فقد نحتاج إلى إعادة المعلومات الشخصية للمستخدم إلى الواجهة الأمامية بدلاً من القفز مباشرة. وينطبق الشيء نفسه على تسجيل الدخول الفاشل.
يتضمن ذلك اثنين من واجهتين في AuthenticationSuccessHandler و AuthenticationFailureHandler المصادقة. يمكننا تنفيذ هذه الواجهة وتكوينها وفقًا لذلك. بالطبع ، يكون للإطار فئة تنفيذ افتراضية. يمكننا أن نرث فئة التنفيذ هذه وتخصيص أعمالنا
component ("myauthenctiationsuccesshandler") الطبقة العامة myauthenctiationsuccessHandler تمتد simplyurlauthenticationsuccessHandler {private logger logger = loggerfactory.getLogger (getClass ()) ؛ @autowired objectMapper ObjectMapper ؛ Override public void onauthenticationationsuccess (طلب httpservletrequest ، استجابة httpservletresponse ، مصادقة المصادقة) يلقي ioException ، servletexception {logger.info ("تسجيل الدخول الناجح") ؛ Response.setContentType ("application/json ؛ charset = utf-8") ؛ استجابة. }} هنا نعيد سلسلة JSON من خلال الرد.
المعلمة الثالثة في هذه الطريقة ، Authentication ، تحتوي على معلومات مستخدم تسجيل الدخول (userDetails) ، معلومات الجلسة ، معلومات تسجيل الدخول ، إلخ.
component ("myauthenctiationFailureHandler") الطبقة العامة myauthenctiationFailureHandler تمديد SimpleUrlauthenticationFailureHandler {private logger logger = loggerfactory.getLogger (getClass ()) ؛ @autowired objectMapper ObjectMapper ؛ Override public void onauthenticationFailure (طلب httpservletrequest ، استجابة httpservletresponse ، استثناء المصادقة) يلقي iOexception ، servletexception {logger.info ("فشل تسجيل الدخول") ؛ Response.setStatus (httpstatus.internal_server_error.value ()) ؛ Response.setContentType ("application/json ؛ charset = utf-8") ؛ desponse.getWriter (). الكتابة (ObjectMapper.WriteValueAsString (new baseresponse (استثناء. getMessage ()))) ؛ }} المعلمة الثالثة في هذه الطريقة AuthenticationException ، تتضمن معلومات حول فشل تسجيل الدخول.
وبالمثل ، لا يزال من الضروري تكوينه في ملف التكوين. لن أقوم بنشر جميع الكود هنا ، يتم نشر العبارات المقابلة فقط.
.sugcessHandler (myAuthenticationationsuccessHandler) // تسجيل الدخول المخصص بنجاح.
شفرة
يمكنك النقر علي لعرض الرمز الكامل
ما سبق هو كل محتوى هذه المقالة. آمل أن يكون ذلك مفيدًا لتعلم الجميع وآمل أن يدعم الجميع wulin.com أكثر.