รู้เบื้องต้นเกี่ยวกับ CSRF
CSRF (การปลอมแปลงคำขอข้ามไซต์), ชื่อภาษาจีน: การปลอมแปลงคำขอข้ามไซต์หรือที่รู้จักกันในชื่อ: การคลิกโจมตีครั้งเดียว/การขี่เซสชันตัวย่อ: CSRF/XSRF
สำหรับการแนะนำเฉพาะและวิธีการโจมตีของ SCRF โปรดดูการแนะนำของสารานุกรม Baidu และการวิเคราะห์ของชายร่างใหญ่:
สารานุกรม CSRF Baidu กล่าวถึงวิธีการโจมตี CSRF สั้น ๆ
ขั้นตอนการกำหนดค่า
1. ขึ้นอยู่กับแพ็คเกจ JAR
<properties> <Spring.Security.Version> 4.2.2.Release </spring.security.version> </premerties> <การพึ่งพา> <roupId> org.springframework.Security </GroupId> <RoupID> org.springframework.security </groupId> <ratifactId> ฤดูใบไม้ผลิความปลอดภัย-ความปลอดภัย </artifactid> <persion> $ {spring.security.version} </เวอร์ชัน> </การพึ่งพา> <cerson> $ {spring.security.version} </version> </predency> 2. การกำหนดค่า web.xml
<silter> <melter-Name> SpringsecurityFilterChain </filter-name> <filter-class> org.springframework.web.filter.delegatingFilterproxy </filter-class> </filter> </ตัวกรองการทำแผนที่>
3. การกำหนดค่าไฟล์การกำหนดค่าสปริง
<bean id = "csrfsecurityRequestMatcher"> </ebean> <ความปลอดภัย: http auto-config = "true" use-expressions = "true"> <ความปลอดภัย: ส่วนหัว> <ความปลอดภัย: frame-options disabled = "true"/> </ความปลอดภัย: </ความปลอดภัย: http>
4. ปรับแต่งคลาสการใช้งานของ requestmatcher csrfsecurityRequestMatcher
คลาสนี้ใช้เพื่อปรับแต่งคำขอที่ไม่จำเป็นต้องมีการสกัดกั้นและการกรอง หากมีการกำหนดค่า CSRF คำขอ HTTP ทั้งหมดจะถูกดักจับโดย CSRFFILTER และมีคลาสส่วนตัว defaultrequirescsrfmatcher ใน csrffilter
ซอร์สโค้ด 1: คลาส defaultrequirescsrfmatcher
คลาสสุดท้ายคงที่คลาสสุดท้าย defaultrequirescsrfmatcher ใช้ requestmatcher {ส่วนตัวสุดท้าย hashset <string> ที่ได้รับอนุญาต; ส่วนตัว defaultrequirescsrfmatcher () {this.allowedmethods = new hashset (array.aslist (สตริงใหม่ [] {"get", "head", "trace", "ตัวเลือก"}); } การจับคู่บูลีนสาธารณะ (คำขอ httpservletrequest) {return! this.allowedmethods.contains (request.getMethod ()); - จากซอร์สโค้ดนี้เราสามารถพบได้ว่าวิธีการโพสต์นั้นไม่รวมนั่นคือมีเพียงสี่ประเภทของวิธีการเช่น Get | Head | Trace | ตัวเลือกจะถูกปล่อยออกมา คำขอ HTTP ของวิธีการอื่นจะต้องตรวจสอบว่าโทเค็น _CSRF นั้นถูกต้องหรือไม่ โดยปกติเมื่อเรียกใช้บริการส่วนต่อประสาน REST ในวิธีการโพสต์จะไม่มีโทเค็น _CSRF ซึ่งจะทำให้อินเทอร์เฟซ REST ของเราล้มเหลว เราจำเป็นต้องปรับแต่งคลาสเพื่อปล่อยอินเทอร์เฟซของประเภทนี้ มาดูตัวกรองที่กำหนดเองของเรา:
ซอร์สโค้ด 2: คลาส CSRFSecurityRequestMatcher
คลาสสาธารณะ CSRFSecurityRequestMatcher ใช้ requestmatcher {รูปแบบส่วนตัวอนุญาตให้ใช้ methods = pattern.compile ("^(รับ | head | trace | ตัวเลือก) $"); Private RegexRequestMatcher Unprotectormatcher = ใหม่ regexrequestmatcher ("^/rest /.*", null); @Override การแข่งขันบูลีนสาธารณะ (คำขอ httpservletRequest) {ถ้า (อนุญาต methods.matcher (request.getMethod ()). matches ()) {return false; } return! unprotectormatcher.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 = $ ("meta [name = '_ csrf_header']"). attr ("เนื้อหา"); $ .ajaxSetup ({beforesend: function (xhr) {ถ้า (ส่วนหัว && token) {xhr.setRequestheader (ส่วนหัว, โทเค็น);}}}); </script> $ .AJAXSETUP หมายถึงการเพิ่มส่วนหัวและโทเค็นนี้ลงในคำขอทั้งหมดของเราหรือใส่ไว้ในแบบฟอร์ม โปรดทราบว่า _csrf ควรตรงกับการกำหนดค่าในไฟล์การกำหนดค่าของความปลอดภัยของสปริงและค่าเริ่มต้นคือ _csrf
การวิเคราะห์ซอร์สโค้ด
เรารู้ว่าเนื่องจาก CSRF ได้รับการกำหนดค่าคำขอ HTTP ทั้งหมดจะถูกสกัดกั้นโดย CSRFFILTER ดังนั้นหลังจากดูที่ซอร์สโค้ดของ CSRFFILTER คุณจะชัดเจนเกี่ยวกับหลักการอย่างรวดเร็ว ที่นี่เราดูที่วิธีการกรองเฉพาะเท่านั้น:
ซอร์สโค้ด 3: วิธี dofilterinternal ของ csrffilter
เป็นโมฆะที่ได้รับการป้องกัน dofilterInternal (httpservletrequest คำขอ, httpservletResponse, filterchain filterchain) โยน servletexception, ioexception {request.setAttribute (httpservletResponse.class.getName () csrftoken csrftoken = this.tokenrepository.loadToken (คำขอ); บูลีน MissingToken = csrftoken == null; ถ้า (MissingToken) {// ถ้าโทเค็นว่างเปล่าหมายความว่าครั้งแรกที่คุณเข้าถึงให้สร้างวัตถุโทเค็น csrftoken = this.tokenrepository.generatetoken (คำขอ); this.tokenrepository.savetoken (csrftoken, คำขอ, การตอบสนอง); } request.setAttribute (csrftoken.class.getName (), csrftoken); // ใส่วัตถุโทเค็นลงในคำขอโปรดทราบว่าคีย์ที่นี่คือ csrftoken.getParametername () = _csrf ดังนั้นเราจึงเขียนถึงความตายบนหน้า request.setAttribute (csrftoken.getParametername (), csrftoken); // เครื่องนี้เป็นตัวกรองที่เราปรับแต่งในไฟล์การกำหนดค่าสปริงนั่นคือรับ, หัว, การติดตาม, ตัวเลือกและส่วนที่เหลือของเราไม่จัดการกับ (! this.requirecsrfprotectionmatcher.matches (คำขอ)) {filterchain.dofilter (คำขอ, การตอบสนอง); } else {String realToken = request.getheader (csrftoken.getheaderName ()); if (realToken == null) {realToken = request.getParameter (csrftoken.getParameterName ()); } if (! csrftoken.getToken (). เท่ากับ (realToken)) {ถ้า (this.logger.isdebugenabled ()) {this.logger.debug ("โทเค็น CSRF ที่ไม่ถูกต้องสำหรับ" } if (MissingToken) {this.AccessDeniedHandler.handle (คำขอ, การตอบสนอง, ใหม่ที่หายไป missingcsrftokenexception (realToken)); } else {this.accessDeniedhandler.handle (คำขอ, การตอบสนอง, ใหม่ InvalidCsrftokenexception (csrftoken, realToken)); }} else {filterchain.dofilter (คำขอ, การตอบกลับ); -ดังที่เห็นได้จากซอร์สโค้ดการร้องขอโพสต์นอกเหนือจากตัวกรองที่กำหนดเองของเราจำเป็นต้องมีการตรวจสอบโทเค็น
เดิมทีฉันต้องการใช้ภาพหน้าจอเพื่อรับเคสจากนั้นใช้เบรกพอยต์เพื่อดูสถานะการส่งค่าของหน้าและพื้นหลัง ... อย่างไรก็ตามฉันไม่สามารถอัปโหลดรูปภาพได้ที่นี่และบ้าไปแล้ว ตกลงมากที่จะสรุป! หากคุณมีการเขียนผิดหรือมีคำถามอื่น ๆ คุณสามารถฝากข้อความไว้เพื่อสื่อสาร
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น