مقدمة إلى CSRF
CSRF (تزوير طلب المواقع المتقاطعة) ، الاسم الصيني: التزوير المتقاطع في الموقع ، المعروف أيضًا باسم: One Click Attack/Session Riding ، الاختصار: CSRF/XSRF.
للحصول على مقدمات محددة وطرق الهجوم لـ SCRF ، يرجى الرجوع إلى مقدمة موسوعة Baidu وتحليل رجل كبير:
يناقش موسوعة CSRF BAIDU لفترة وجيزة أساليب هجوم CSRF
خطوات التكوين
1. تعتمد على حزمة جرة
<Pretteries> <pring.security.version> 4.2.2. <roupl> org.springframework.security </groupId> <sntifactid> Spring-Security-Web </shintifactid> <sophy> $ {spring.security.version} </version> </reperency> <sperence> <roupend> org.springframewwork.security </rouc <splect> $ {spring.security.version} </version> </sependency> 2.web.xml التكوين
<lipter> <ilter-name> springsecurityfilterchain </filter-name> <filter-class> org.springframework.web.filter.delegatingfilterproxy </filter-class> </filter> <filter-mapping> </filter mapping>
3. تكوين ملف تكوين الربيع
<bean id = "csrfsecurityRequestMatcher"> </bean> <security: http auto-config = "true" use-expressions = "true"> <security: headers> </الأمان: http>
4. تخصيص فئة تنفيذ طلب CSRFSecurityRequestMatcher
يتم استخدام هذه الفئة لتخصيص الطلبات التي لا تتطلب اعتراضًا وتصفية. إذا تم تكوين CSRF ، يتم اعتراض جميع طلبات HTTP بواسطة CSRFFilter ، وهناك فئة خاصة defaultRequiresCsrfmatcher في csrffilter.
رمز المصدر 1: فئة DefaultRequiresCsrfmatcher
الفئة النهائية الثابتة الخاصة plightrequirescsrfmatcher تنفذ requestMatcher {private final hashset <string> المسموح بها ؛ private defaultrequirescsrfmatcher () {this.allowedMethods = new hashset (arrays.aslist (new string [] {"get" ، "head" ، "trace" ، "reports"})) ؛ } مباريات منطقية عامة (طلب httpservletrequest) {return! this.allowedMethods.Contains (request.getMethod ()) ؛ }} من هذا الكود المصدر ، يمكننا أن نجد أن طريقة البريد مستبعدة ، أي فقط الأنواع الأربعة من الأساليب مثل Get | Head | Trace | Options. يجب أن تتحقق طلبات HTTP للطرق الأخرى ما إذا كان رمز _CSRF صحيحًا. عادة ، عند استدعاء خدمة واجهة REST في طريقة النشر ، لا يوجد رمز _CSRF ، مما سيؤدي إلى فشل واجهة الراحة لدينا. نحن بحاجة إلى تخصيص فئة لإصدار واجهة هذا النوع. دعونا نلقي نظرة على مرشحاتنا المخصصة:
رمز المصدر 2: CSRFSecurityRequestMatcher فئة
الطبقة العامة csrfsecurityRequestMatcher تنفذ requestMatcher {private patternmethods = pattern.compile ("^(Get | Head | Trace | Options) $") ؛ regexRequestMatcher الخاص غير محمي = جديد regexRequestMatcher ("^/rest /.*" ، null) ؛ Override Public Boolean Matches (HttPservletRequest request) {if (المسموح بهميثود. } العودة! غير محمي matcher.matches (طلب) ؛ }} ملاحظة: عمومًا ، تكون خدمات واجهة REST التي نحددها كلها مع /REST /، لذلك إذا لم يتم استخدام مشروعك ، أو لا توجد خدمة REST في المشروع ، يمكن حذف هذه الفئة تمامًا.
5. تكوين الطلب
بشكل عام ، يوجد ملف JSP شائع في مشروعنا ، والذي يشير إليه كل صفحة ، حتى نتمكن من عمل التكوين التالي في الملف المشترك:
<meta name = "_ csrf" content = "$ {_ csrf.token}"/> <meta name = "_ csrf_header" content = "$ {_ csrf.headername}"/> <script> var token = $ ("meta [name = '_ csrf']"). var header = $ ("meta [name = '_ csrf_header']"). attr ("content") ؛ $ .ajaxsetup ({be ForsEnd: function (xhr) {if (header && token) {xhr.setRequestHeader (header ، token) ؛}}}) ؛ </script> $ .AJaxSetup يعني إضافة هذا الرأس والرمز إلى جميع طلباتنا ، أو وضعه في النموذج. لاحظ أن _CSRF يجب أن يتطابق مع التكوين في ملف تكوين أمان الربيع ، والافتراضي هو _CSRF.
تحليل رمز المصدر
نحن نعلم أنه نظرًا لتكوين CSRF ، سيتم اعتراض جميع طلبات HTTP بواسطة CSRFFILTER ، لذلك بعد النظر في رمز المصدر لـ CSRFFILTER ، سوف تكون واضحًا بشأن المبدأ في لمحة. هنا ننظر فقط إلى طريقة التصفية المحددة:
رمز المصدر 3: طريقة dofilterinternal من CSRFFILTER
dofilterinternal void المحمي (طلب httpservletrequest ، httpservletresponse ، filterchain filterchain) يلقي servletexception ، ioException {request.setAttribute (httpservletresponse.class.getname () ، استجابة) ؛ csrftoken csrftoken = this.tokenRepository.LoadToken (request) ؛ Boolean MissingToken = csrftoken == null ؛ إذا كان (MissingToken) {// إذا كان الرمز مميزًا فارغًا ، فهذا يعني أنه في المرة الأولى التي تصل إليها ، قم بإنشاء كائن رمزي csrftoken = this.tokenRepository.generateToken (request) ؛ this.tokenRepository.savetoken (csrftoken ، طلب ، الرد) ؛ } request.setattribute (csrftoken.class.getName () ، csrftoken) ؛ // ضع الكائن الرمزي في الطلب ، لاحظ أن المفتاح هنا هو csrftoken.getParameterName () = _csrf ، لذلك نكتبه حتى الموت على الصفحة. request.setattribute (csrftoken.getParameterName () ، csrftoken) ؛ . } آخر {string actualToken = request.getheader (csrftoken.getheadername ()) ؛ if (actualToken == null) {actualToken = request.getParameter (csrftoken.getParameterName ()) ؛ } if (! csrftoken.getToken (). equals (actualToken)) {if (this.logger.isdeBugenabled ()) {this.logger.debug ("رمز CSRF غير صالح لـ" + urlutils.buildfullrequesturl (request)) ؛ } if (missingtoken) {this.accessdeniedhandler.handle (request ، response ، new MissetCsrftokenXception (actualToken)) ؛ } آخر {this.accessdeniedhandler.handle (طلب ، استجابة ، invalidcsrftokenexception جديد (csrftoken ، actualToken)) ؛ }} آخر {filterchain.dofilter (طلب ، استجابة) ؛ }}}كما يتضح من الكود المصدري ، تتطلب طلبات النشر غير المرشحات المخصصة لدينا التحقق المميز.
في الأصل ، أردت التقاط لقطة شاشة للحصول على حالة ، ثم استخدم نقطة الإيقاف لرؤية حالة نقل القيمة للصفحة والخلفية ... ومع ذلك ، لا يمكنني تحميل الصور هنا والجنون. حسنا ، الكثير لتلخيص! إذا كان لديك أي كتابة خاطئة أو لديك أسئلة أخرى ، فيمكنك ترك رسالة للتواصل.
ما سبق هو كل محتوى هذه المقالة. آمل أن يكون ذلك مفيدًا لتعلم الجميع وآمل أن يدعم الجميع wulin.com أكثر.