ในตัวอย่างก่อนหน้านี้เราใช้ Zuul เพื่อสร้างเกตเวย์ //www.vevb.com/article/133235.htm
ฉันจะไม่เข้าไปดูรายละเอียดเกี่ยวกับบทบาทของเกตเวย์ที่นี่ จุดเน้นของเราในวันนี้คือตัวกรองของ Zuul ผ่านตัวกรองเราสามารถใช้การควบคุมความปลอดภัยตัวอย่างเช่นลูกค้าที่มีชื่อผู้ใช้และรหัสผ่านในพารามิเตอร์คำขอเท่านั้นที่สามารถเข้าถึงทรัพยากรของเซิร์ฟเวอร์ได้ ดังนั้นจะใช้ตัวกรองได้อย่างไร?
ในการใช้ตัวกรองจำเป็นต้องมีขั้นตอนต่อไปนี้:
1. สืบทอดคลาส Zuulfilter เพื่อตรวจสอบคุณสมบัติของตัวกรองเราสร้างตัวกรอง 3 ตัวที่นี่
ตัวกรองตามชื่อผู้ใช้
แพ็คเกจ com.chhliu.springcloud.zuul; นำเข้า javax.servlet.http.httpservletrequest; นำเข้า com.netflix.zuul.zuulfilter; นำเข้า com.netflix.zuul.context.requestcontext; Public Class AccessusERNAMEFILTER ขยาย ZUULFILTER {@OverRide วัตถุสาธารณะรัน () {requestContext ctx = requestContext.getCurrentContext (); httpservletRequest Request = ctx.getRequest (); System.out.println (string.format (" %s AccessUnSerNameFilter ขอ %s", request.getMethod (), request.getRequesturl (). toString ())); String username = request.getParameter ("ชื่อผู้ใช้"); // รับพารามิเตอร์ที่ร้องขอถ้า (null! = ชื่อผู้ใช้ && ชื่อผู้ใช้. equals ("chhliu")) {// ถ้าพารามิเตอร์ที่ร้องขอไม่ว่าง ctx.set ("issuccess", true); // ตั้งค่าเพื่อให้ตัวกรองถัดไปดูสถานะของตัวกรองก่อนหน้าคืนค่า null; } else {ctx.setsendzuulResponse (เท็จ); // กรองคำขอและไม่กำหนดเส้นทาง ctx.setResponSestatusCode (401); // ส่งคืนรหัสข้อผิดพลาด ctx.setResponseBody ("{/" ผลลัพธ์/":/" username ไม่ถูกต้อง! คืนค่า null; }} @Override บูลีนสาธารณะควร filter () {return true; // ว่าจะเรียกใช้ตัวกรองหรือไม่มันเป็นความจริงที่นี่แสดงว่าจำเป็นต้องมีการกรอง} @Override public int filterorder () {return 0; // ลำดับความสำคัญคือ 0 โดยการสืบทอด Zuulfilter และเขียนทับวิธี 4 ข้างต้นคุณสามารถใช้ตัวกรองอย่างง่าย ต่อไปนี้เป็นคำอธิบายของจุดสนใจที่เกี่ยวข้อง
FilterType: ส่งคืนสตริงที่แสดงถึงประเภทของตัวกรอง สี่ประเภทตัวกรองที่มีวงจรชีวิตที่แตกต่างกันถูกกำหนดใน Zuul ดังนี้:
วงจรการร้องขอหลักของ Zuul มีขั้นตอนเช่น "pre", "เส้นทาง" และ "โพสต์" สำหรับแต่ละคำขอตัวกรองทั้งหมดที่มีประเภทเหล่านี้จะทำงาน
FilterOrder: กำหนดลำดับการดำเนินการของตัวกรองผ่านค่า int
ควรกรอง: ส่งคืนประเภทบูลีนเพื่อตรวจสอบว่าจะต้องดำเนินการตัวกรองหรือไม่ดังนั้นฟังก์ชั่นนี้สามารถใช้สวิตช์ของตัวกรองได้ ในตัวอย่างข้างต้นเรากลับมาจริงโดยตรงดังนั้นตัวกรองจะมีผลเสมอ
Run: ตรรกะเฉพาะของตัวกรอง ควรสังเกตว่าที่นี่เราใช้ CTX.SetsEndZuulResponse (เท็จ) เพื่อกรองคำขอและไม่กำหนดเส้นทางแล้วตั้งค่ารหัสข้อผิดพลาดที่ส่งคืนผ่าน CTX.SetResponSestatusCode (401)
การประสานงานระหว่างตัวกรอง
ไม่มีวิธีโดยตรงสำหรับตัวกรองในการเข้าถึงซึ่งกันและกัน พวกเขาสามารถใช้ requestcontext เพื่อแบ่งปันสถานะซึ่งเป็นโครงสร้างคล้ายแผนที่ที่มีวิธีการเข้าถึงที่ชัดเจนสำหรับบางวิธีสำหรับการพิจารณา zuul พวกเขาจะถูกนำไปใช้ภายในโดยใช้ ThreadLocal นักเรียนที่สนใจสามารถตรวจสอบซอร์สโค้ด
สร้างตัวกรองและตัวกรองอื่นตามรหัสผ่าน:
แพ็คเกจ com.chhliu.springcloud.zuul; นำเข้า javax.servlet.http.httpservletrequest; นำเข้า com.netflix.zuul.zuulfilter; นำเข้า com.netflix.zuul.context.requestcontext; คลาสสาธารณะ AccessPasswordFilter ขยาย ZuulFilter {@Override วัตถุสาธารณะรัน () {requestContext ctx = requestContext.getCurrentContext (); httpservletRequest Request = ctx.getRequest (); System.out.println (string.format (" %s AccessPasswordFilter คำขอไปที่ %s", request.getMethod (), request.getRequesturl (). toString ())); String username = request.getParameter ("รหัสผ่าน"); if (null! = ชื่อผู้ใช้ && username.equals ("123456")) {ctx.setsendzuulResponse (จริง); CTX.SetResponSestatusCode (200); ctx.set ("issuccess", true); คืนค่า null; } else {ctx.setsendzuulResponse (เท็จ); CTX.SetResponSestatusCode (401); ctx.setResponseBody ("{/" ผลลัพธ์/":/" รหัสผ่านไม่ถูกต้อง!/"}"); ctx.set ("issuccess", false); คืนค่า null; }} @Override บูลีนสาธารณะควร filter () {requestcontext ctx = requestcontext.getCurrentContext (); ผลตอบแทน (บูลีน) ctx.get ("issuccess"); // หากผลลัพธ์ของตัวกรองก่อนหน้านี้เป็นจริงหมายความว่าตัวกรองก่อนหน้านี้ประสบความสำเร็จและจำเป็นต้องป้อนตัวกรองปัจจุบัน หากผลลัพธ์ของตัวกรองก่อนหน้าเป็นเท็จนั่นหมายความว่าตัวกรองก่อนหน้านี้ไม่ประสบความสำเร็จ ไม่จำเป็นต้องดำเนินการกรองต่อไปนี้ ข้ามตัวกรองที่ตามมาทั้งหมดและส่งคืนผลลัพธ์} @Override public int filterOrder () {return 1; // ลำดับความสำคัญตั้งค่าเป็น 1} @Override Public String FilterType () {return "pre"; - สร้างตัวกรองโพสต์ในตอนท้าย
แพ็คเกจ com.chhliu.springcloud.zuul; นำเข้า javax.servlet.http.httpservletrequest; นำเข้า com.netflix.zuul.zuulfilter; นำเข้า com.netflix.zuul.context.requestcontext; Public Class AccessTokenFilter ขยาย ZuulFilter {@Override วัตถุสาธารณะรัน () {requestContext ctx = requestContext.getCurrentContext (); httpservletRequest Request = ctx.getRequest (); System.out.println (string.format (" %s AccessTokenFilter คำขอไปที่ %s", request.getMethod (), request.getRequesturl (). toString ())); ctx.setsendzuulresponse (จริง); CTX.SetResponSestatusCode (200); ctx.setResponseBody ("{/" ชื่อ/":/" chhliu/"}"); // ส่งออกผลลัพธ์สุดท้ายส่งคืนค่า null; } @Override บูลีนสาธารณะควร filter () {return true; } @Override public int filterOrder () {return 0; } @Override Public String FilterType () {return "post"; // หลังจากดำเนินการตามคำขอตัวกรองจะถูกป้อน}} 2. ในชั้นเรียนหลักเปิดตัวฟิลเตอร์สองตัวแรกก่อน
@bean สาธารณะ accessuserNameFilter AccessUnerNameFilter () {ส่งคืน AccessUnerNameFilter ใหม่ (); } @Bean Public AccessPasswordFilter AccessPasswordFilter () {ส่งคืน AccessPasswordFilter ใหม่ (); - 3. ป้อนคำขอและตรวจสอบ
(1) คำขอคือ: http: // localhost: 8768/h2service/user/1? ชื่อผู้ใช้ = chhliu
ผลการทดสอบคือ: {"ผลลัพธ์": "รหัสผ่านไม่ถูกต้อง!"}
ผลการพิมพ์คอนโซล
รับคำขอ AccessUnSerNameFilter ไปที่ http: // localhost: 8768/h2service/ผู้ใช้/1
รับคำขอ AccessPasswordFilter ไปที่ http: // localhost: 8768/h2service/ผู้ใช้/1
ผ่านตัวกรอง AccessUnSerNameFilter ล้มเหลวเมื่อตรวจสอบตัวกรอง AccessPasswordFilter
ไม่มีการพิมพ์ SQL ในพื้นหลังซึ่งหมายความว่าคำขอไม่ได้ถูกกำหนดเส้นทาง
(2) คำขอคือ: http: // localhost: 8768/h2service/ผู้ใช้/1? รหัสผ่าน = 123456
ผลการทดสอบคือ: {"ผลลัพธ์": "ชื่อผู้ใช้ไม่ถูกต้อง!"}
ผลการพิมพ์คอนโซล:
รับคำขอ AccessUnSerNameFilter ไปที่ http: // localhost: 8768/h2service/ผู้ใช้/1
หมายความว่าตัวกรอง AccessusERNAMEFILTER ได้รับมาแล้ว แต่ยังไม่ถึงตัวกรอง AccessPasswordFilter เนื่องจากตัวกรอง accessuserNameFilter มีลำดับความสำคัญสูงกว่าจึงจะถูกดำเนินการก่อน เมื่อดำเนินการพบว่าเงื่อนไขตัวกรองไม่ตรงตามดังนั้นตัวกรองทั้งหมดหลังจากนั้นจะถูกข้ามและผลลัพธ์จะถูกส่งคืนโดยไม่ต้องพิมพ์ SQL ในพื้นหลังแสดงว่าคำขอไม่ได้ถูกกำหนดเส้นทาง
(3) คำขอคือ: http: // localhost: 8768/h2service/ผู้ใช้/1? รหัสผ่าน = 123456 & username = chhliu
ผลการทดสอบคือ:
-
"id": 1,
"ชื่อผู้ใช้": "user1",
"ชื่อ": "จางซาน"
"อายุ": 20,
"สมดุล": 100.00
-
ผลลัพธ์ของการพิมพ์คอนโซล:
รับคำขอ AccessUnSerNameFilter ไปที่ http: // localhost: 8768/h2service/ผู้ใช้/1
รับคำขอ AccessPasswordFilter ไปที่ http: // localhost: 8768/h2service/ผู้ใช้/1
ซึ่งหมายความว่า AccessusERNAMEFILTER จะถูกดำเนินการก่อนจากนั้นจะดำเนินการ AccessPasswordFilter สิ่งนี้สอดคล้องกับค่าสั่งซื้อที่เล็กกว่าที่เรากล่าวถึงก่อนหน้านี้ยิ่งมีความสำคัญสูงขึ้น
บริการที่ร้องขอในเวลาเดียวกันมีเอาต์พุต SQL:
Hibernate: เลือก user0_.id เป็น id1_0_0_, user0_.age เป็น Age2_0_0_, user0_.balance เป็น Balance3_0_0_, user0_.name เป็น name4_0_0_, user0_.username เป็นชื่อผู้ใช้ 5_0_0_ จากผู้ใช้
ระบุว่าคำขอถูกกำหนดเส้นทาง
4. เปิดตัวกรองโพสต์แล้วเรียกใช้อีกครั้ง
ผลการทดสอบ: พบว่าตัวกรองโพสต์ถูกดำเนินการครั้งล่าสุดแม้ว่าลำดับความสำคัญของมันคือ 0
เกี่ยวกับวงจรชีวิตของตัวกรองของ Zuul ดูรูปด้านล่าง
หมายเหตุ: มีข้อผิดพลาดเล็กน้อยในภาพด้านบนการกำหนดเส้นทางควรเป็นเส้นทาง
5. ขยาย
Zuul ยังให้ตัวกรองชนิดพิเศษ ได้แก่ : StaticResponseFilter และ SurgicalDebugFilter
StaticResponseFilter: StaticResponseFilter อนุญาตให้สร้างการตอบสนองจาก Zuul เองแทนที่จะส่งคำขอไปยังแหล่งที่มา
SurgicalDebugFilter: SurgicalDebugFilter อนุญาตให้กำหนดเส้นทางคำขอเฉพาะไปยังคลัสเตอร์ดีบั๊กหรือโฮสต์ที่คั่นด้วย
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น