Shiro คืออะไร
ชิโรเป็นกรอบการอนุญาตโอเพนซอร์สสำหรับแพลตฟอร์ม Java สำหรับการรับรองความถูกต้องและการอนุญาตการเข้าถึง โดยเฉพาะการสนับสนุนสำหรับองค์ประกอบต่อไปนี้จะพบ:
ถาม: สนับสนุนกลุ่ม?
ตอบ: ชิโร่ไม่สนับสนุนการตั้งค่าการอนุญาตสำหรับกลุ่มโดยค่าเริ่มต้น
ถาม: มันสามารถตอบสนองความต้องการของการจัดสรรบทบาทสำหรับกลุ่มได้หรือไม่?
ตอบ: การขยายขอบเขตสามารถสนับสนุนการกำหนดบทบาทให้กับกลุ่มซึ่งจริง ๆ แล้วเป็นการกำหนดสิทธิ์ให้กับผู้ใช้ทั้งหมดภายใต้กลุ่ม
ถาม: สนับสนุนการอนุญาตข้อมูล? กำหนดไว้ในระบบธุรกิจ?
ตอบ: Shiro ใช้การควบคุมสิทธิ์ในการดำเนินการเท่านั้นซึ่งใช้เพื่อซ่อนหรือแสดงองค์ประกอบการควบคุมส่วนหน้าและตรวจสอบสิทธิ์การเข้าถึงทรัพยากร การอนุญาตข้อมูลมีความสัมพันธ์อย่างใกล้ชิดกับความต้องการทางธุรกิจที่เฉพาะเจาะจงและ Shiro เองก็ไม่สามารถควบคุมการอนุญาตข้อมูลได้
ถาม: การจัดสรรการอนุญาตแบบไดนามิก?
ตอบ: ขยาย org.apache.shiro.realm.realm เพื่อรองรับการจัดสรรการอนุญาตแบบไดนามิก
ถาม: รวมกับฤดูใบไม้ผลิ?
ตอบ: สามารถรองรับการรวมเข้ากับฤดูใบไม้ผลิและชิโร่ยังรองรับแท็ก JSP
ในบล็อกก่อนหน้านี้เราได้พูดคุยเกี่ยวกับคุณสมบัติที่ใหญ่ที่สุดสองประการของ Shiro คือการรับรองความถูกต้องและการอนุญาต การลงชื่อเข้าใช้ครั้งเดียวเป็นส่วนหนึ่งของการตรวจสอบสิทธิ์ โดยค่าเริ่มต้น Shiro ได้ดำเนินการรวมกับ CAS ให้กับเราและมันจะโอเคถ้าเราเพิ่มการกำหนดค่าแบบบูรณาการ
1. เพิ่มแพ็คเกจ Shiro-Cas
<!-Shiro รวม CAS Single Point-> <การพึ่งพา> <GroupId> org.apache.shiro </groupId> <ratifactid> Shiro-Cas </artifactid>
2. เพิ่มการกำหนดค่าการลงชื่อเข้าใช้ครั้งเดียว
ที่นี่ฉันโพสต์การกำหนดค่าทั้งหมดเพื่อการอ้างอิงที่ง่ายและมีการเพิ่มคำแนะนำโดยละเอียดในการกำหนดค่า
แพ็คเกจ com.chhliu.springboot.shiro.config; นำเข้า java.util.linkedhashmap; นำเข้า java.util.map; นำเข้า Javax.servlet.filter; นำเข้า org.apache.shiro.cache.ehcache.ehcachemanager; นำเข้า org.apache.shiro.cas.casfilter; นำเข้า org.apache.shiro.cas.cassubjectFactory; นำเข้า org.apache.shiro.spring.lifecyclebeanpostprocessor; นำเข้า org.apache.shiro.spring.security.interceptor.authorizationattributesourceadvisor; นำเข้า org.apache.shiro.spring.web.shirofilterfactorybean; นำเข้า org.apache.shiro.web.mgt.defaultwebsecurityManager; นำเข้า org.jasig.cas.client.session.singlesignoutfilter; นำเข้า org.jasig.cas.client.session.singlesignouthttpsessionListener; นำเข้า org.springframework.aop.framework.autoproxy.defaultadvisorautoproxycreator; นำเข้า org.springframework.boot.web.servlet.filterregistrationbean; นำเข้า org.springframework.boot.web.servlet.servletListenerRegistrationBean; นำเข้า org.springframework.context.annotation.bean; นำเข้า org.springframework.context.annotation.configuration; นำเข้า org.springframework.context.annotation.dependson; นำเข้า org.springframework.core.ordered; นำเข้า org.springframework.core.annotation.order; นำเข้า org.springframework.web.filter.delegatingFilterproxy; /*** การกำหนดค่า Shiro** Apache Shiro Core ถูกนำไปใช้ผ่านตัวกรองเช่นเดียวกับ SpringMVC ใช้ DispachServlet เพื่อควบคุม เนื่องจากเราใช้ตัวกรอง * โดยทั่วไปเราสามารถคาดเดาได้ว่าการกรองและการตรวจสอบการอนุญาตนั้นทำได้ผ่านกฎ URL ดังนั้นเราจึงต้องกำหนดชุดของกฎและสิทธิ์ในการเข้าถึงเกี่ยวกับ URL * * @author chhliu */@configuration คลาสสาธารณะ shiroconfiguration {// เซิร์ฟเวอร์เซิร์ฟเวอร์ที่อยู่สาธารณะคงที่สตริงสุดท้าย casserverurlprefix = "http://127.0.0.1"; // CAS หน้าล็อกอินที่อยู่สาธารณะคงที่สตริงสุดท้าย casloginurl = casserverurlprefix + "/ล็อกอิน"; // CAS logout page ที่อยู่สาธารณะคงที่สตริงสุดท้าย caslogouturl = casserverurlprefix + "/logout"; // ที่อยู่บริการปัจจุบันที่จัดทำโดยโครงการไปยัง Public Public Station Final String สุดท้าย ShiroServerUrlPrefix = "http://127.0.1.28:8080"; // casfilter urlpattern สาธารณะคงที่สตริงสุดท้าย casfilterurlpattern = "/index"; // ล็อกอินที่อยู่สาธารณะคงที่สตริงสุดท้าย loginUrl = casloginurl + "? service =" + shiroServerUrlprefix + casfilterurlpattern; // ที่อยู่ออกจากระบบ (Casserver เปิดใช้งานฟังก์ชั่น Service Jump และคุณต้องเปิดใช้งาน cas.logout.followserviceredirects = true ใน webapps/cas/web-inf/cas.properties ไฟล์) สตริงสุดท้ายคงที่ logouturl = caslogouturl+" // ล็อกอินที่อยู่ที่ประสบความสำเร็จ // สตริงสุดท้ายคงที่ล็อกอินล็อกอิน successurl = "/index"; // การรับรองความถูกต้องของการอนุญาตล้มเหลวที่อยู่ Public Static String สุดท้าย unauthorizedUrl = "/error/403.html"; / ** *อินสแตนซ์ SecurityManager คลาสนี้เป็นคลาสหลักของ Shiro */ @return */ @Bean Public DefaultWebsecurityManager MANYMANAGER () {DefaultWebSecurityManager SecurityManager = ใหม่ DefaultWebsecurityManager (); SecurityManager.setRealm (MyShirocasrealm ()); // <!-แคชข้อมูลการรับรอง/การรับรองความถูกต้องของผู้ใช้โดยใช้ Ehcache Cache-> SecurityManager.setCacheManager (getEhCacheManager ()); // ระบุ subjectFactory หากคุณต้องการใช้ฟังก์ชั่น MESIME ME ของ CAS คุณจะต้องใช้ CassubjectFactory ต่อไปนี้และตั้งค่าเป็น SecurityManager SecurityManager.setSubjectFactory (ใหม่ CassubjectFactory ()); Return SecurityManager; } / *** กำหนดค่าแคช* @return* / @bean สาธารณะ ehcachemanager getehcachemanager () {ehcachemanager em = new ehcachemanager (); Em.SetCacheManagerConFigFile ("classpath: config/ehcache-shiro.xml"); return em; } /*** กำหนดค่าอาณาจักร เนื่องจากเรากำลังใช้ Casrealm ฟังก์ชั่นการลงชื่อเข้าใช้เดียวได้ถูกรวมเข้าด้วยกัน * @param cachemanager * @return */ @bean สาธารณะ myshiReoralm myshirocasrealm () {myshirorealm lealm = new myshirorealm (); // CAS Login Server Address Prefix Realm.setCasserverUrlprefix (Shiroconfiguration.casserverurlprefix); // ที่อยู่การโทรกลับของลูกค้า, ที่อยู่กระโดดหลังจากเข้าสู่ระบบสำเร็จ (ที่อยู่บริการของตนเอง) Realm.SetCasservice (Shiroconfiguration.shiroServerUrlprefix + Shiroconfiguration.casfilterurlpattern); // บทบาทเริ่มต้นหลังจากการเข้าสู่ระบบสำเร็จที่นี่ค่าเริ่มต้นของบทบาทผู้ใช้ Realm.setDefaultroles ("ผู้ใช้"); กลับมาดินแดน; }/ ** * ลงทะเบียนผู้ฟังการลงชื่อเข้าใช้ครั้งเดียว * @return */ @suppresswarnings ({"rawtypes", "unchected"}) @bean @order (สั่งซื้อ highest_precedence) // การจัดลำดับความสำคัญสูง ใหม่ ServletListenerRegistrationBean (); Bean.setListener (ใหม่ SinglesignouthttpsessionListener ()); Bean.setenabled (จริง); คืนถั่ว; } / ** * ลงทะเบียนตัวกรองการลงชื่อเข้าใช้เดียว * @return * / @bean public filterregistrationbean singlesignoutfilter () {filterregistrationbean ถั่ว = ใหม่ตัวกรองการลงทะเบียนเบียน (); Bean.setName ("SinglesignoutFilter"); Bean.setFilter (SinglesignoutFilter ใหม่ ()); Bean.addurlpatterns ("/*"); Bean.setenabled (จริง); คืนถั่ว; } / ** * ลงทะเบียน DelegatingFilterProxy (Shiro) * / @Bean Public FilterRegistrationBean DelegatingFilterProxy () {FilterRegistrationBean FilterRegistration = FilterRegistrationBean () ใหม่ (); FilterRegistration.SetFilter (ใหม่ DelegatingFilterProxy ("Shirofilter")); // ค่านี้เป็นเท็จโดยค่าเริ่มต้นซึ่งระบุว่าวงจรชีวิตได้รับการจัดการโดย SpringApplicationContext ตั้งค่าเป็นจริงหมายความว่า servletContainer ได้รับการจัดการโดย FilterRegistration.addinitParameter ("TargetFilterLifecycle", "TRUE"); FilterRegistration.setEnabled (จริง); FilterRegistration.addurlpatterns ("/*"); ส่งคืนการลงทะเบียน; } / *** คลาสนี้สามารถตรวจสอบให้แน่ใจว่าวิธีการเริ่มต้นหรือ destory ของวัตถุ Shiro ที่ใช้ org.apache.shiro.util.initializable interface ถูกเรียกโดยอัตโนมัติ* โดยไม่ต้องระบุวิธีการเริ่มต้นหรือวิธีการทำลาย "LifeCycleBeanPostProcessor") Public LifecycleBeanPostProcessor GetLifecycleBeanPostProcessor () {ส่งคืน LifecyclecleBeanPostProcessor ใหม่ (); } /*** การกำหนดค่าสองแบบต่อไปนี้ส่วนใหญ่จะใช้เพื่อเปิดใช้งานการสนับสนุนคำอธิบายประกอบของ Shiro AOP ใช้วิธีพร็อกซี ดังนั้นคุณต้องเปิดใช้งานการสนับสนุนรหัส * @return */ @bean @dependson ("LifecycleBeanPostProcessor") Public DefaultAdvisorautoproxycreator getDefaultAdvisorautoproxycreator () {DefaultAdvisorautoproxycreator daap.setproxytargetClass (จริง); กลับ Daap; } / ** * @Param SecurityManager * @return * / @Bean Public AuthorizationAttributesourceAdvisor GetAuthorizationAtTributesourceAdVisor (DefaultWebsecurityManager SecurityManager) AuthorizationAttributesourceAdvisor.SetSecurityManager (SecurityManager); return AuthorizationAttributesourceadvisor; } / *** ตัวกรอง cas* @return* / @bean (name = "casfilter") สาธารณะ casfilter getcasfilter () {casfilter casfilter = ใหม่ casfilter (); casfilter.setName ("casfilter"); casfilter.setenabled (จริง); // URL ที่กระโดดหลังจากการเข้าสู่ระบบล้มเหลวนั่นคือ Shiro ดำเนินการวิธี dogetauthenticationInfo ของ casrealm เพื่อตรวจสอบ tiket casfilter.setfailureurl (loginurl); // เราเลือกที่จะเปิดหน้าเข้าสู่ระบบหลังจากการตรวจสอบบัญชีล้มเหลว กลับ Casfilter; } / ** * สร้างและเริ่มต้น shirofilter โดยใช้โหมดโรงงาน * @param SecurityManager * @param casfilter * @return * / @bean (name = "Shirofilter") ShirofilterfactoryBean ShirofilterFactoryBean (); // SecurityManager จะต้องตั้งค่า ShirofilterFactoryBean.setSecurityManager (SecurityManager); // หากคุณไม่ได้ตั้งค่าเริ่มต้นมันจะค้นหาหน้า "/login.jsp" โดยอัตโนมัติในไดเรกทอรีรูทของเว็บโครงการ ShirofilterFactoryBean.setLoginurl (loginurl); / * * การเชื่อมต่อที่จะเปลี่ยนเส้นทางหลังจากเข้าสู่ระบบสำเร็จ หากไม่ได้ตั้งค่าไว้มันจะข้ามไปยัง URL ก่อนหน้าโดยค่าเริ่มต้น * ตัวอย่างเช่นคุณป้อน http: // localhost: 8080/userlist ในเบราว์เซอร์ แต่ตอนนี้ผู้ใช้ไม่ได้เข้าสู่ระบบดังนั้นมันจะข้ามไปยังหน้าเข้าสู่ระบบ หลังจากผ่านการรับรองความถูกต้องเข้าสู่ระบบหน้า * จะข้ามไปที่หน้า http: // localhost: 8080/userlist หน้าแทนหน้าดัชนีหลังจากการเข้าสู่ระบบสำเร็จ ไม่แนะนำฟิลด์นี้ให้ตั้งค่า */ // shirofilterfactorybean.setsuccessurl (loginsuccessurl); // ตั้งค่าการเข้าถึงที่ไม่ได้รับอนุญาตไปยังหน้า ShirofilterFactoryBean.setUnauthorizedUrl (ไม่ได้รับอนุญาต); / * * เพิ่ม casfilter ลงใน Shirofilter โปรดทราบว่าจะต้องวาง Casfilter ไว้หน้า Shirofilter * เพื่อให้แน่ใจว่าโปรแกรมจะป้อนการตรวจสอบจุดเดียวก่อนเข้าสู่ระบบล็อกอิน Shiro */ MAP <String, Filter> Filter = New LinkedHashMap <> (); Filters.put ("casfilter", casfilter); // logout ถูกแทนที่ด้วย logout จุดเดียว // filters.put ("logout", logoutfilter ()); ShirofilterFactoryBean.setFilters (ตัวกรอง); Loadshirofilterchain (ShirofilterFactoryBean); ส่งคืน ShirofilterFactoryBean; } /*** โหลดกฎการควบคุมการอนุญาต Shirofilter (อ่านจากฐานข้อมูลแล้วกำหนดค่า) ข้อมูลบทบาท /การอนุญาตจะจัดทำโดยวัตถุ MyShirocasrealm การใช้งาน DoGetauthorizationInfo * ส่วนหนึ่งของกฎนี้จะถูกวางไว้ในฐานข้อมูลระหว่างการผลิต * @param ShirofilterFactoryBean */โมฆะส่วนตัว loadshirofilterchain (shirofilterfactorybean shirofilterfactorybean) {/////////////////////////////////////////////////////////////////////////////////////////////////////// Note that the filter added here needs to be orderly, so use LinkedHashMap ///////////////////////////////////////////////// Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>(); FilterChainDefinitionMap.put (casfilterurlpattern, "casfilter"); // 2. คำขอที่ไม่สกัดกั้น FilterChainDefinitionMap.put ("/CSS/**", "anon"); FilterChainDefinitionMap.put ("/js/**", "anon"); FilterChainDefinitionMap.put ("/เข้าสู่ระบบ", "anon"); // ที่นี่ตั้งค่าหน้าการออกจากระบบเป็น anon ไม่ใช่ออกจากระบบเนื่องจากการออกจากระบบถูกประมวลผลโดยจุดเดียวและไม่จำเป็นต้องสกัดกั้นโดย LogoutFilter FilterChainDefinitionMap.put ("/logout", "Anon"); FilterChainDefinitionMap.put ("/ข้อผิดพลาด", "anon"); // 3. คำขอที่สกัดกั้น (รับจากฐานข้อมูลท้องถิ่นหรือจาก Casserver (วิธีการระยะไกลเช่น Webservice, HTTP ฯลฯ ) ดูที่กำหนดค่าการอนุญาตบทบาทของคุณ) FilterChainDefinitionMap.put ("/ผู้ใช้", "Authc"); // เข้าสู่ระบบที่ต้องการ // 4 การเข้าสู่ระบบไม่สกัดกั้น FilterChainDefinitionMap.put ("/**", "Authc"); ShirofilterFactoryBean.SetFilterChainDefinitionMap (FilterChainDefinitionMap); -การอ้างอิงการกำหนดค่าบางอย่าง: http://shiro.apache.org/spring.html
3. เขียนอาณาจักร
เนื่องจากเราจำเป็นต้องรวมฟังก์ชั่นของการลงชื่อเข้าใช้เดียวเราจึงต้องรวมคลาส Casrealm คลาสนี้ได้ใช้ฟังก์ชั่นของการตรวจสอบจุดเดียวสำหรับเรา สิ่งที่เราต้องทำคือการใช้ฟังก์ชั่นของส่วนการอนุญาต รหัสตัวอย่างมีดังนี้:
แพ็คเกจ com.chhliu.springboot.shiro.config; นำเข้า Javax.annotation.Resource; นำเข้า org.apache.shiro.securityutils; นำเข้า org.apache.shiro.authc.authenticationinfo; นำเข้า org.apache.shiro.authc.authenticationToken; นำเข้า org.apache.shiro.authz.authenticationinfo; นำเข้า org.apache.shiro.authz.simpleauthorizationInfo; นำเข้า org.apache.shiro.cas.casrealm; นำเข้า org.apache.shiro.subject.principalcollection; นำเข้า com.chhliu.springboot.shiro.mode.syspermission; นำเข้า com.chhliu.springboot.shiro.mode.syspermission; นำเข้า com.chhliu.springboot.shiro.mode.userinfo; นำเข้า com.chhliu.springboot.shiro.service.userinfoservice; /*** คลาสหลักตรวจสอบการอนุญาต; เนื่องจากใช้การลงชื่อเข้าใช้ครั้งเดียวจึงไม่จำเป็นต้องตรวจสอบสิทธิ์เพียงแค่การอนุญาตให้ใช้งาน * * @author chhliu */ คลาสสาธารณะ myshiRorealm ขยาย casrealm {@Resource ผู้ใช้ส่วนตัว userinfoservice userinfoservice; / *** 1. การรับรองความถูกต้องของ CAS, ตรวจสอบตัวตนของผู้ใช้* 2. ตั้งค่าข้อมูลพื้นฐานของผู้ใช้เป็นเซสชันเพื่อให้เข้าถึงได้ง่าย* 3. วิธีนี้สามารถใช้วิธีการตรวจสอบความถูกต้องโดยตรงใน casrealm ซึ่งใช้เป็นแบบทดสอบ*/ @Override การรับรองความถูกต้อง Casrealm ได้ดำเนินการตรวจสอบจุดเดียวสำหรับเรา AuthenticationInfo Authc = super.dogetauthenticationInfo (โทเค็น); // รับบัญชีที่เข้าสู่ระบบ หลังจากการรับรองความถูกต้องของ CAS สำเร็จแล้วบัญชีจะถูกบันทึกไว้ บัญชีสตริง = (สตริง) AuthC.getPrincipals (). getPrimaryPrincipal (); // บันทึกข้อมูลผู้ใช้ลงในเซสชันสำหรับการได้มาซึ่งโปรแกรมง่าย ๆ ที่นี่คุณสามารถใส่ข้อมูลผู้ใช้ที่สอบถามตามบัญชีเข้าสู่ระบบลงในเซสชัน SecurityUtils.getSubject (). getSession (). setAttribute ("ไม่", บัญชี); ส่งคืน authc; } /*** การโทรกลับจะดำเนินการเฉพาะเมื่อวิธีการนี้เรียก Hasrole และ Haspermission * * ข้อมูลการอนุญาต (การอนุญาต): 1. หากผู้ใช้ออกจากปกติแคชจะถูกล้างโดยอัตโนมัติ 2. หากผู้ใช้ออกอย่างผิดปกติแคชจะถูกล้างโดยอัตโนมัติ * 3. หากเราแก้ไขสิทธิ์ของผู้ใช้ แต่ผู้ใช้ไม่ได้ออกจากระบบระบบการอนุญาตที่ได้รับการแก้ไขจะไม่สามารถมีผลได้ทันที (จำเป็นต้องดำเนินการด้วยตนเองให้บริการสำหรับการโทร) * หลังจากได้รับการแก้ไขการอนุญาตวิธีการในอาณาจักรเรียกว่า Realm ได้รับการจัดการในฤดูใบไม้ผลิดังนั้นอินสแตนซ์ของอาณาจักรจึงได้มาจากฤดูใบไม้ผลิและวิธีการ ClearCached เรียกว่า; *: การอนุญาตเป็นตัวควบคุมการเข้าถึงที่ได้รับอนุญาตใช้เพื่ออนุญาตให้ดำเนินการโดยผู้ใช้พิสูจน์ว่าผู้ใช้อนุญาตให้ดำเนินการในปัจจุบันเช่นการเข้าถึงลิงก์บางไฟล์ไฟล์ทรัพยากรบางอย่าง ฯลฯ * * @param principals * @return */ @Override Protected การกำหนดค่า-> myshirorealm.dogetauthorizationInfo () "); SimpleAtorizationInfo AuthorizationInfo = ใหม่ SimpleAdeAdizationInfo (); // รับชื่อผู้ใช้หลังจากการลงชื่อเข้าใช้ครั้งเดียวคุณสามารถรับได้จากเซสชันเนื่องจากหลังจากการตรวจสอบความถูกต้องประสบความสำเร็จชื่อผู้ใช้ได้ถูกนำไปใส่ในเซสชันสตริงผู้ใช้ชื่อ = (สตริง) super.getAvailablePrincipal (หลักการ); // principals.getPrimaryPrincipal (); วิธีนี้ยังสามารถรับชื่อผู้ใช้ // ได้รับบทบาทและข้อมูลการอนุญาตของผู้ใช้ตามชื่อผู้ใช้ userInfo userInfo = userInFoservice.FindByUserName (ชื่อผู้ใช้); // แพคเกจข้อมูลบทบาทและการอนุญาตที่สอดคล้องกันของผู้ใช้ในการอนุญาตให้ใช้งาน Info สำหรับ (บทบาท Sysrole: userInfo.getRoleList ()) {AuthorizationInfo.addrole (role.getRole ()); สำหรับ (Syspermission P: role.getPermissions ()) {AuthorizationInfo.addstringPermission (P.GetPermission ()); }} return AuthorizationInfo; - ต่อไปเราสามารถทำการทดสอบการตรวจสอบได้!
ป้อน http: 127.0.1.28: 8080/userinfo/userlist ในเบราว์เซอร์และเราจะพบว่ามันจะข้ามไปยังหน้าเข้าสู่ระบบจุดเดียวโดยอัตโนมัติ
จากนั้นเราป้อนชื่อผู้ใช้และรหัสผ่านและจะข้ามไปที่ HTTP: 127.0.1.28 โดยอัตโนมัติ: 8080/userInfo/userlist หน้า
ข้างต้นเป็นเนื้อหาทั้งหมดของบทความนี้ ฉันหวังว่ามันจะเป็นประโยชน์ต่อการเรียนรู้ของทุกคนและฉันหวังว่าทุกคนจะสนับสนุน wulin.com มากขึ้น