تتفهم هذه المقالة كيف تعمل المرشحات والاعتراضات من خلال ممارسة تطوير شهادة الأمان البسيطة.
تربط العديد من المقالات المرشحات والاعتراضات والمستمعين مع الربيع لشرح ، والاعتقاد بأن المرشحات والاعتراضات والمستمعين تستخدم على نطاق واسع وظائف المكونات التي توفرها الربيع.
ولكن بالمعنى الدقيق للكلمة ، تنتمي المرشحات والمستمعين إلى واجهة برمجة تطبيقات Servlet ولا علاقة لها بالربيع.
نظرًا لأن المرشح يرث من واجهة javax.servlet.filter والمستمع يرثون من واجهة javax.servlet.servletcontextlistener ، يرث التقاطع فقط واجهة org.springframework.web.servlet.handlerNinterceptor.
تتم الرجوع إلى المخطط الانسيابي أعلاه من المعلومات عبر الإنترنت ، وصورة واحدة تساوي ألف كلمة. بعد قراءة هذه المقالة ، سيكون لديك فهم أعمق لعملية استدعاء المرشحات والاعتراضات.
1. أفكار تصميم شهادة السلامة
في بعض الأحيان ، عندما تتصل الشبكات الداخلية والخارجية واجهات برمجة التطبيقات ، فإن متطلبات الأمان لمتطلبات مختلفة. في كثير من الحالات ، فإن القيود المختلفة على الشبكات الخارجية لاتصالات واجهات برمجة التطبيقات ليست ضرورية في إنترانت. ومع ذلك ، عند نشر بوابات ، يمكن نشر واجهات برمجة التطبيقات التي سيتم استدعاؤها بواسطة الشبكات الداخلية والخارجية معًا بسبب مشكلات التكلفة والتعقيد.
لإدراك أمان واجهة الراحة ، يمكن القيام به من خلال الأطر الناضجة مثل Spring Security أو Shiro.
ومع ذلك ، نظرًا لأن أطر الأمان غالبًا ما تكون معقدة (لقد قمت بحساب أمن الربيع ، هناك حوالي 11 وحدة أساسية ، وكمية رمز المصدر لشيرو مدهشة أيضًا). في الوقت نفسه ، قد يتم تقديم تكوينات معقدة (هل يمكن أن تجعل الناس يشعرون بمزيد من المتعة) ، وهو ما لا يفضي إلى التطوير المرن والسريع والنشر والتحقيق في المشكلات في الفرق الصغيرة والمتوسطة الحجم.
العديد من الفرق تبني عجلات خاصة بها لتحقيق شهادة السلامة. يشير مثال الشهادة البسيط في هذه المقالة إلى فريق تطوير المصنع السابق حيث أنا ، ويمكن اعتباره خدمة شهادة أمنية تعتمد على الرمز المميز.
فكرة التصميم العامة هي كما يلي:
1. تخصيص رأس طلب HTTP. في كل مرة يتم استدعاء API ، يتم تمرير قيمة رمزية في رأس الطلب.
2. ضع الرمز المميز في ذاكرة التخزين المؤقت (مثل redis) ، وضبط وقت انتهاء الصلاحية للسياسات المختلفة وفقًا لمختلف الأعمال واجهات برمجة التطبيقات.
3. يمكن أن يضع الرمز المميز القوائم البيضاء والطوائم السوداء ، والتي يمكن أن تحد من تواتر مكالمات API ، وتسهيل التطوير والاختبار ، وتسهيل معالجة حالات الطوارئ ، وحتى إغلاق API مؤقتًا.
4. يجب إرسال رمز الشبكة الخارجية. يمكن أن يرتبط الرمز المميز بالمستخدم ، مثل كل مرة تقوم فيها بفتح الصفحة أو تسجيل الدخول لإنشاء رأس طلب كتابة رمزي ، و Page تحدد صحة ملفات تعريف الارتباط والرموز ، إلخ.
هناك مفهومين في إطار أمن الربيع ، وهما المصادقة والترخيص . تشير المصادقة إلى المستخدمين الذين يمكنهم الوصول إلى النظام ، في حين أن التفويض هو مورد يمكن للمستخدمين الوصول إليه.
لتحقيق متطلبات مصادقة الأمان البسيطة أعلاه ، قد تحتاج إلى إنشاء خدمة رمزية بشكل مستقل للتأكد من أن الرمز المميز فريد من نوعه على مستوى العالم. الوحدات النمطية التي قد تتضمن مولدات التدفق المخصصة ، CRM ، التشفير والتشفير ، السجلات ، إحصائيات API ، ذاكرة التخزين المؤقت ، وما إلى ذلك ، لكنها في الواقع مرتبطة بالمستخدمين (CRM). يمكن لبعض الخدمات العامة المرتبطة بالمستخدمين ، مثل الرسائل القصيرة وخدمات البريد الإلكتروني التي نستخدمها في كثير من الأحيان ، حل المكالمات الأمنية من خلال آلية الرمز المميز.
باختصار ، تختلف شهادة الأمان البسيطة في هذه المقالة في الواقع قليلاً عن المصادقة والترخيص المقدم من إطار أمان الربيع. بالطبع ، هذه طريقة علاج "السلامة" ليست جديدة على المهنيين ، ولكنها يمكن أن تمنع عددًا كبيرًا من المستخدمين المبتدئين من الخارج.
2. تخصيص مرشح
على غرار Spring MVC ، يوفر Boot Spring العديد من مرشحات Servlet (المرشحات) للاستخدام ، ويضيف تلقائيًا بعض المرشحات شائعة الاستخدام ، مثل distaryencodingFilter (المستخدم للتعامل مع مشكلات الترميز) ، HiddenHttpMethodFilter (request http) ، httpputformcontentfilter (request request). قم بتنفيذ بعض الوظائف الشائعة ، مثل سجلات التسجيل ، وتحديد ما إذا كان سيتم تسجيل الدخول ، أو التحقق من الإذن ، وما إلى ذلك.
1. رأس طلب مخصص
إنه بسيط للغاية ، أضف رأس طلب مخصص في رأس الطلب:
requestmapping (value = "/getInfobyId" ، method = requestMethod.post) apiOperation ("معلومات عن منتجات المنتج استنادًا إلى معرف المنتج") apiImplicitParams ({apiimplicitparam (paramtype = "header" ، name = "upittoken" ، required = "value =" getGoodsBygoodSidResponse getGoodsBygoodsId (requestheader سلسلة AuthToken ، requestbody getGoodsBygoodSidRequest طلب) {return _goodsapiservice.getgoodsbygoodsid (request) ؛ } getGoodsbygoodsidيمكن عرض حقل AuthToken المعدل بواسطة requestheader بموجب إطار مثل Swagger.
بعد الاتصال ، يمكنك رؤية رأس الطلب وفقًا لأداة HTTP. المثال في هذه المقالة هو Authtoken (يختلف عن رمز بعض الأطر):
ملاحظة: تدعم العديد من أدوات HTTPClient رؤوس طلب الإرسال الديناميكي ، مثل RestTemplate.
2. تنفيذ مرشح
هناك ثلاث طرق في واجهة التصفية ، وهي DISP و DOFILTER و DESTORY. عندما ترى الاسم ، ستعرف على الأرجح استخداماتها الرئيسية. عادة ، نحتاج فقط إلى معالجة طلبات HTTP داخل طريقة Dofilter:
package com.power.demo.controller.filter ؛ import com.power.demo.common.appconst ؛ import com.power.demo.common.bizresult ؛ import com.power.demo.cervice.contract.authtokenservice ؛ isport com.power.demo.util.power. com.power.demo.util.SerializeUtil ؛ استيراد org.springframework.beans.factory.annotation.autowired ؛ استيراد org.springframework.stereotype.component ؛ import javax.servlet.*؛ java.io.ioException ؛ componentpublic class authtokenfilter تنفذ filter {autowired private authtokenservice authtokenservice ؛ Override public void init (filterConfig var1) يلقي servletexception {} override public void dofilter (servletRequest request ، servletResponse ، سلسلة filterchain) يلقي iOexception ، servlexception {httpservletrequest req = (httpletrequest) طلب ؛ TRING TOKEN = req.getheader (AppConst.auth_token) ؛ bizresult <string> bizresult = authtokenservice.powerCheck (token) ؛ System.out.println (SerializeUtil.Serialize (bizresult)) ؛ if (bizresult.getisok () == true) {powerlogger.info ("تم تمرير مرشح الرمز المميز") ؛ Chain.dofilter (طلب ، استجابة) ؛ } آخر {رمي servleTexception جديد (bizresult.getMessage ()) ؛ }} Override public void Dorner () {}} authtokenfilterلاحظ أنه من وجهة نظر التسلسل الهرمي الفعلي ، تتم معالجة معظم الأشياء التي تعالج المزيد من طبقات التعبير. لا ينصح باستخدام طبقة الوصول إلى البيانات مباشرة في التصفية. على الرغم من أنني رأيت مثل هذه الرمز عدة مرات في العديد من المشاريع القديمة القديمة منذ عام أو عامين ، وهناك سوابق للكتابة بهذه الطريقة في الكتاب << Spring Smortical >>.
3. خدمة الشهادات
هذا هو منطق العمل الرئيسي. رمز العينة هو مجرد طريقة بسيطة لكتابة الأفكار ، ويجب عدم استخدامها بسهولة في بيئات الإنتاج:
package com.power.demo.service.impl ؛ import com.power.demo.cache.powercachebuilder ؛ import com.power.demo.common.bizresult ؛ import com.power.demo.service.contract.authtokenservice ؛ org.springframework.stereotype.component ؛ استيراد org.springframework.util.stringutils ؛ componentpublic class authtokenserviceimpl تنفذ AuthTokenService {autowired powercachebuilder cachebuilder ؛ / * * تحقق مما إذا كان رمز رأس الطلب هو قانوني * */ Override Public BizResult <String> powercheck (سلسلة الرمز المميز) {bizresult <string> bizresult = new bizresult <> (صواب ، "تم تمرير التحقق") ؛ System.out.println ("قيمة الرمز المميز هي:" + token) ؛ if (stringUtils.isempty (token) == true) {bizresult.setFail ("AuthToken فارغ") ؛ إرجاع bizresult. } // معالجة القائمة السوداء bizresult = checkforbidlist (token) ؛ if (bizresult.getisok () == false) {return bizresult ؛ } // معالجة القائمة البيضاء bizresult = checkallowlist (رمز) ؛ if (bizresult.getisok () == false) {return bizresult ؛ } string key = string.format ("power.authtokenservice. ٪ s" ، token) ؛ //cachebuilder.set(key ، token) ؛ //cachebuilder.set(key ، token.toupperCase ()) ؛ // جلب سلسلة stibtoken من ذاكرة التخزين المؤقت = cacheBuilder.get (المفتاح) ؛ if (stringUtils.isempty (nuphtoken) == true) {bizresult.setFail (string.format ("this authtoken: ٪ s" ، token)) ؛ إرجاع bizresult. } // قارن ما إذا كان الرمز المميز هو نفسه منطقي isequal = token.equals (thattoken) ؛ if (isequal == false) {bizresult.setFail (string.format ("upittoken غير القانوني: ٪ s" ، رمز)) ؛ إرجاع bizresult. } // افعل شيئًا ما يعيد bizresult ؛ }} authtokenserviceimplيمكنك الرجوع إلى خدمة ذاكرة التخزين المؤقت التي تستخدمها هنا ، والتي تعد أيضًا ملخصًا لتجربتي في المصنع السابق.
4. تسجيل مرشح
هناك طريقتان شائعتان للكتابة:
(1) استخدم تعليق توضيحي @webfilter لتحديد المرشح
order (1) webfilter (urlpatterns = {"/api/v1/gouds/*" ، "/api/v1/userinfo/*"}) فئة عامة upertokenfilter تنفذ filter {باستخدام @WebFilter التعليق التوضيحي ، يمكنك أيضًا استخدام التعليق التوضيحي order بالتزامن مع التعليق التوضيحي. يمثل التعليق التوضيحي order ترتيب التصفية. كلما كانت القيمة أصغر ، كلما قمت بتنفيذها أولاً. حجم الطلب هذا مفيد مثل معالجة دورة حياة طلبات HTTP أثناء عملية البرمجة الخاصة بنا. بالطبع ، إذا لم يتم تحديد الطلب ، فإن ترتيب المرشح يسمى عكس ترتيب المرشحات المضافة ، وتنفيذ المرشح هو نمط سلسلة المسؤولية.
أخيرًا ، أضف ServletComponentscan enoutation إلى فئة بدء التشغيل لاستخدام المرشح المخصص بشكل طبيعي.
(2) استخدام FilterRegistrationBean لتخصيص تسجيل المرشح
تستخدم هذه المقالة التنفيذ الثاني لتنفيذ تسجيل مرشح مخصص:
package com.power.demo.controller.filter ؛ import com.google.common.collect.lists org.springframework.context.annotation.bean ؛ استيراد org.springframework.context.Antation.Configuration ؛ استيراد org.springframework.stereotype.component ؛ import java.util.list bean publicregistrationbean filterregistrationBean () {filterRegistrationBean registrationBean = new filterregistrationbean () ؛ التسجيل. // SET (FUZZY) MATTING URL LIST <TRING> urlpatterns = lists.newarrayList () ؛ urlpatterns.add ("/api/v1/goods/*") ؛ urlpatterns.add ("/api/v1/userInfo/*") ؛ التسجيل. التسجيل. التسجيل. إعادة التسجيل ؛ }} RESTFILTERCONFIGيرجى إيلاء اهتمام خاص إلى urlpatterns. يحدد urlpatterns السمة نمط عنوان URL المراد ترشيحه. هذه المعلمة ذات أهمية كبيرة بالنسبة لمجال التصفية للعمل.
سجل مرشح ، وعندما يبدأ SPRING BOOT ، سيضيف تلقائيًا سلسلة اتصالات الاتصال Filter ApplicationFilterchain عند اكتشاف حبة مع javax.servlet.filter.
استدعاء واجهة برمجة التطبيقات لتجربة التأثير:
عادةً ما نقوم بتخصيص GlobalExceptionHandler GlobalExceptionler GlobaleRler Globalerler Globaller Globalerler Globalerner Uniped Unified (سيكون مختلفًا قليلاً عن ما سبق).
وفقًا لممارستي ، لن يتم القبض على الاستثناءات التي تم طرحها في المرشح ومعالجتها من خلال تحسين إدارة الاستثناءات الفريدة عالميًا. هذا يختلف عن مستقبل Interceptor واعتراض AOP المخصص الذي تم تقديمه في المقالة التالية.
في هذه المرحلة ، يتم تنفيذ خدمة مصادقة أمان بسيطة يتم تنفيذها من خلال مرشح مخصص.
3. اعتراض مخصص
1. تنفيذ المعترض
ورث مقبول معالج الواجهة وتنفيذ المعترض. طرق الواجهة هي كما يلي:
يتم تنفيذ prehandle قبل تنفيذ الطلب
Posthandle هي نهاية تنفيذ الطلب
يتم تنفيذ Aftercompletion بعد اكتمال عرض العرض
package com.power.demo.controller.Interceptor ؛ import com.power.demo.common.appconst ؛ import com.power.demo.common.bizresult ؛ import com.power.demo.cervice.contract.authtokenservice ؛ import com.power.demo.util.power. com.power.demo.util.serializeutil ؛ استيراد org.springframework.beans.factory.annotation.autowired ؛ استيراد org.springframework javax.servlet.http.httpservletrequest ؛ استيراد javax.servlet.http.httpservletresponse ؛/ * * مصادقة Token Interceptor * */ @componentpublic class AuthTokenInterceptor تنفذ المعالج / * * تنفيذ قبل طلب التنفيذ * */ Override Public Boolean Prehandle (HttPservletRequest request ، httpservletresponse ، معالج الكائن) يلقي استثناء {boolean Handleresult = false ؛ string token = request.getheader (AppConst.auth_token) ؛ bizresult <string> bizresult = authtokenservice.powerCheck (token) ؛ System.out.println (SerializeUtil.Serialize (bizresult)) ؛ معالجات = bizresult.getisok () ؛ powerlogger.info ("تم تمرير اعتراض اعتراض اعتراض اعتراض اعتراض اعتراض اعتراض اعتراض اعتراض اعتراض اعتراضية") ؛ } آخر {رمي استثناء جديد (bizresult.getMessage ()) ؛ } معالجات العودة ؛ } / * * ينتهي الطلب من التنفيذ * * / Override public void posthandle (httpservletrequest request ، httpservletresponse ، معالج الكائنات ، modelandview modelandview) يلقي استثناء {} / * معالج ، استثناء EX) يلقي الاستثناء {}} AuthTokenInterceptorفي المثال ، نختار إجراء مصادقة أمان رمزية قبل تنفيذ الطلب.
خدمة المصادقة هي AuthTokenService المقدمة في المرشح ، ويتم إعادة استخدام طبقة منطق الأعمال.
2. تسجيل المعترض
تحديد فئة InterceptorConfig ، الموروثة من WebMVCConfigurationSupport ، و WebMVCConfigurerAdapter عفا عليها الزمن.
حقن AuthTokenInterceptor كحبة ، فإن عناوين URL والمرشحات التي يعترض اعتراض الإعدادات الأخرى متشابهة للغاية:
package com.power.demo.controller.Interceptor ؛ استيراد com.google.common.collect.lists ؛ استيراد org.springframework.context.annotation.bean ؛ استيراد org.springframework.context.annotation. org.springframework.web.servlet.config.annotation.defaultservlethandlerconfigurer ؛ استيراد org.springframework.web.servlet.config.annotation.interceptorregistry org.springframework.web.servlet.config.annotation.webmvcConfigurationSupport ؛ import java.util.list ؛@configuration@componentpublic class interceptorConfig تمتد webmvcconfigurationsupport {// webmvcconfigurer "/favicon.ico" ؛ /*** وجدت أنه إذا كان WebMVCConfigurationSupport موروثة ، فإن المحتوى ذي الصلة التي تم تكوينها في YML سيكون غير صالح. * * @param registry */Override public void addresourceHandlers (ResourceHandlerRegistry Recistry) {registry.addresourceHandler ("/"). addresourcelocations ("/**") ؛ registry.addresourceHandler ("/static/**"). addresourcelocations ("classpath:/static/") ؛ } / *** تكوين Servlet Processing* / Override public void configaureDefaultServleThandling (DefaultServleThandLerConfigurer configure) {configurer.enable () ؛ } Override public void addInterceptors (Repinceptorregistry Registry) {// set (fuzzy) matching url list <string> urlpatterns = lists.newarraylist () ؛ urlpatterns.add ("/api/v1/goods/*") ؛ urlpatterns.add ("/api/v1/userInfo/*") ؛ registry.addInterceptor (AuthTokenInterceptor ()). addathpatterns (urlpatterns) .excludepathpatterns (favicon_url) ؛ Super.AddInterceptors (السجل) ؛ } // اكتب التقاطع كحبة في التكوين @bean public authTokenInterceptor authTokenInterceptor () {return new AuthTokenInterceptor () ؛ }} InterceptorConfigبعد بدء التطبيق ، يمكنك رؤية تأثير اعتراض التقاطع عن طريق استدعاء الواجهة. Global Unified Investment Management تعالج GlobalExceptionhandler الاستثناءات التالية بعد اصطيادها:
إنها تقريبًا مثل رسالة الخطأ الرئيسية التي يتم عرضها بواسطة المرشح ، لكن معلومات المكدس أكثر ثراءً.
4. الفرق بين المرشح والتقاطع
الاختلافات الرئيسية هي على النحو التالي:
1. تعتمد المقاطعات بشكل أساسي على آلية انعكاس Java ، بينما تستند المرشحات
2. Interceptor لا يعتمد على حاوية servlet ، تعتمد المرشحات على حاوية servlet
3. لا يمكن للاعتراضات العمل إلا على طلبات الإجراءات ، بينما يمكن للمرشحات العمل على جميع الطلبات تقريبًا.
4. يمكن للمعتترض الوصول إلى الكائن في سياق الإجراء ومكدس القيمة ، ولكن لا يمكن للمرشح الوصول إليه.
5. خلال دورة حياة الإجراء ، يمكن استدعاء التقاطع عدة مرات ، في حين لا يمكن استدعاء المرشح إلا مرة واحدة عند تهيئة الحاوية.
وقالت بعض المقالات التي أشرت إليها إن "المقاطع يمكن أن تحصل على فاصوليا مختلفة في حاوية IOC ، لكن الفلتر لا يمكن. هذا أمر مهم للغاية. حقن الخدمة في المعترض يمكن أن يطلق على منطق العمل." بعد التحقق الفعلي ، هذا خطأ.
ملاحظة: يكون وقت التشغيل للمرشح بعد الحاوية وقبل servlet ، وبالتالي فإن معلمة الإدخال من dofilter filter (طلب servletRequest ، استجابة servletResponse ، سلسلة المرشحات) هي servletrequest ، وليس httpservletrequest ، لأن المرشح هو قبل httpservlet. يمكن أن يمنحك الشكل التالي فهمًا أكثر سهولة لتوقيت تنفيذ المرشح والتقاطع:
فقط الطلبات التي تم تمريرها بواسطة Dispatcherservlet ستتبعها سلسلة التقاطع. لن يتم اعتراض طلبات Servlet المخصصة. على سبيل المثال ، لن يتم اعتراض عنوان Servlet المخصص http: // localhost: 9090/TestServlet بواسطة التقاطع. ولكن بغض النظر عن أي Servlet الذي ينتمي إليه ، سيتم تنفيذ المرشح طالما أنه يتوافق مع قواعد مرشح المرشح.
وفقًا للتحليل أعلاه ، سيكون فهم المبدأ بسيطًا ، حتى مرشحات ASP.NET سيكون هو نفسه.
المشكلة: تحقيق مصادقة أمان أكثر مرونة
تحت شبكة Java ، من خلال مرشح المرشح المخصص أو اعتراض التقاطع ، يمكن تحقيق المصادقة الآمنة لواجهة برمجة تطبيقات مطابقة محددة ، مثل مطابقة جميع واجهات برمجة التطبيقات ، مطابقة واجهة برمجة التطبيقات أو عدة واجهات برمجة التطبيقات ، ولكن في بعض الأحيان لا يكون هذا النمط المطابق ودودًا نسبيًا للمطورين.
يمكننا الرجوع إلى أمن الربيع لتحقيق وظائف قوية من خلال التعليق التوضيحي + spel.
على سبيل المثال ، في ASP.NET ، غالبًا ما نستخدم الميزة المعتمدة ، والتي يمكن إضافتها إلى الفئات أو المطبق على الأساليب ، ويمكننا التحكم في مصادقة الأمان بشكل أكثر ديناميكية ومرونة.
لم نختار أمان الربيع ، حتى نتمكن من تنفيذ شهادة أمنية مرنة مماثلة لمرخصها. تقنية التنفيذ الرئيسية هي AOP التي نعرفها.
لن يتم ذكر المعرفة الأساسية لتحقيق اعتراض أكثر مرونة من خلال طريقة AOP في هذه المقالة. سيتم مشاركة المزيد من الموضوعات حول AOP في المقالة التالية.
لخص
ما سبق هو ما قدمه لك المحرر. يستخدم SPRING BOOT المرشحات والتقاطعات لتحقيق مصادقة بسيطة وآمنة لواجهات الراحة. آمل أن يكون ذلك مفيدًا للجميع. إذا كان لديك أي أسئلة ، فيرجى ترك رسالة لي وسوف يرد المحرر على الجميع في الوقت المناسب. شكرا جزيلا لدعمكم لموقع wulin.com!