ما هو شيرو
Shiro هو إطار إذن مفتوح المصدر لمنصة Java للمصادقة والوصول إلى إذن. على وجه التحديد ، يتم استيفاء دعم العناصر التالية:
س: دعم المجموعة؟
ج: لا يدعم شيرو إعداد أذونات للمجموعات افتراضيًا.
س: هل يمكن أن تلبي احتياجات تخصيص الأدوار للمجموعات؟
ج: يمكن لتمديد المجال دعم تعيين أدوار للمجموعات ، وهو في الواقع تعيين أذونات لجميع المستخدمين تحت المجموعة.
س: دعم أذونات البيانات؟ محددة في نظام الأعمال؟
ج: يقوم Shiro فقط بتنفيذ التحكم في أذونات التشغيل ، والذي يتم استخدامه لإخفاء أو عرض عناصر التحكم في الواجهة الأمامية والتحقق من أذونات الوصول إلى الموارد. ترتبط أذونات البيانات ارتباطًا وثيقًا باحتياجات الأعمال المحددة ، ولا يمكن لشيرو نفسها التحكم في أذونات البيانات.
س: تخصيص الإذن الديناميكي؟
ج: تمديد org.apache.shiro.realm.realm لدعم تخصيص الإذن الديناميكي.
س: الاندماج مع الربيع؟
ج: يمكن أن تدعم التكامل مع الربيع ، ويدعم Shiro أيضًا علامات JSP.
في المدونة السابقة ، تحدثنا عن أكبر ميزتين لشيرو ، المصادقة والترخيص. علامة واحدة هي أيضا جزء من المصادقة. افتراضيًا ، قام Shiro بتنفيذ التكامل مع CAS بالنسبة لنا ، وسيكون على ما يرام إذا أضفنا بعض التكوينات المتكاملة.
1. أضف حزمة Shiro-Cas
<!-يدمج Shiro نقطة واحدة CAS-> <Rependency> <roupiD> org.apache.shiro </groupid> <StifactId> shiro-cas </stifactid> <الإصدار> 1.2.4 </version> </respency>
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.AuthorizationAtributesourCeadVisor ؛ استيراد org.apache.shiro.spring.web.shirofilterfactorybean ؛ استيراد org.apache.shiro.web.mgt.defaultwebsecurityManager ؛ استيراد org.jasig.cas.client.session.SingLesignoutFilter ؛ استيراد org.jasig.cas.client.session.singlesignouthtttsessionistener ؛ استيراد 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 {// cas address string public static static casserverurlprefix = "http://127.0.0.1" ؛ // CAS Login عنوان صفحة STATION STATIC FINDALT CASLOGINURL = CASSERVERURLPREFIX + "/login" ؛ . . // casfilter urlpattern public static final string casfilterurlpattern = "/index" ؛ // address address public static static final loginurl = casloginurl + "؟ service =" + shiroserverurlprefix + casfilterurlpattern ؛ // عنوان تسجيل الدخول (Casserver يتيح وظيفة قفزة الخدمة ، وتحتاج إلى تمكين cas.logout.followServicerEdirects = صحيح في ملف webapps/cas/web-inf/cas.properties) // تسجيل الدخول العنوان الناجح // Static Final String loginsuccessurl = "/index" ؛ // فشل مصادقة الإذن عنوان القفزة العامة Static Final String UnauletizedUrl = "/error/403.html" ؛ / ** *instantiate SecurityManager ، هذه الفئة هي الفئة الأساسية من Shiro */ @REGTURN */ bean public defaultwebsecurityManager SecurityManager () {defaultWebSecurityManager SecurityManager = New DefaultWebsCurityManager () ؛ SecurityManager.setRealm (myshirocasrealm ()) ؛ // <!-ذاكرة التخزين المؤقت لتخويل المستخدم/المصادقة ، باستخدام ehcache cache-> SecurityManager.setCachemanager (gethecachemanager ()) ؛ // حدد thispfactory. إذا كنت ترغب في تنفيذ وظيفة تذكر ME الخاصة بـ CAS ، فأنت بحاجة إلى استخدام CassubjectFactory التالي وتعيينها على SecurityManager thispactory SecurityManager.SetSubjectFactory (New CassUbjectFactory ()) ؛ Return SecurityManager ؛ } / *** تكوين ذاكرة التخزين المؤقت* regurn* / bean public ehcachemanager gethecachemanager () {ehcachemanager em = new ehcachemanager () ؛ EM.SetCachemanagerConfile ("classpath: config/ehcache-shiro.xml") ؛ العودة م ؛ } /*** تكوين عالم. نظرًا لأننا نستخدم CASREALM ، فقد تم دمج وظيفة تسجيل الدخول المفردة * param cachemanager * regurn */ bean public myShirorealm myShirocasRealM () {myShirorealm Realm = new MyShirorealM () ؛ // CAS Login Server عنوان Prefix RealM.SetCasserverurlPrefix (shiroconfiguration.casserverurlprefix) ؛ // عنوان رد الاتصال العميل ، عنوان القفزة بعد تسجيل الدخول ناجح (عنوان الخدمة الخاص به) RealM.SetCasservice (shiroconfiguration.shiroserverurlprefix + shiroconfiguration.casfilterurlpattern) ؛ // إن الدور الافتراضي بعد تسجيل الدخول ناجح ، هنا الافتراضيات لدور المستخدم الحقيقي. عودة عالم. }/ ** * تسجيل مستمع واحد تسجيل الدخول * @REGRINT */ suppressWarnings ({"RawTypes" ، "uncheced"}) bean order (ordered.highest_precedence) // الأولوية أعلى من cas public servleTisterationBean <؟ servleTlistenerRegistrationBean () ؛ Bean.SetListener (New SingleSignouthTtpsessionListener ()) ؛ Bean.setEnabled (صواب) ؛ عودة الفول } / ** * سجل مرشح تسجيل الدخول الفردي * @RETURN * / bean publicergistrationBean singlesignoutFilter () {filterRegistrationBean Bean = new FilterRegistrationBean () ؛ Bean.setName ("singleSignoutFilter") ؛ Bean.setFilter (singleSignoutFilter ()) ؛ bean.addurlpatterns ("/*") ؛ Bean.setEnabled (صواب) ؛ عودة الفول } / ** * سجل devingfilterproxy (shiro) * / bean publiterregistrationbean devingfilterproxy () {filterregistrationBean filterregistration = new FilterRegistrationBean () ؛ FilterRegistration.setFilter (New DelegatingFilterProxy ("Shirofilter")) ؛ // هذه القيمة خاطئة بشكل افتراضي ، مما يشير إلى أن دورة الحياة تدار بواسطة springapplicationContext. التعيين يعني أن ServletContainer تتم إدارة بواسطة filterregistration.addinitparameter ("TargetFilterLifecycle" ، "True") ؛ filterRegistration.setEnabled (true) ؛ FilterRegistration.Addurlpatterns ("/*") ؛ مرشح الإرجاع ؛ } / *** يمكن لهذه الفئة التأكد من أن الواجهة init أو القمامة لكائن shiro الذي ينفذ org.apache.shiro.util.Initializable تسمى تلقائيًا ،* دون تحديد طريقة init-method أو طريقة @ @، إذا تم استخدام هذه الفئة ، فلا توجد حاجة لتحديد طريقة التهيئة اليدوي وطريقة التدمير ، "LifecyClebeanPostProcessor") Public LifeCycleBeanPostProcessor getLifecycleBeanPostProcessor () {Return New LifeCycleBeanPostProcessor () ؛ } /*** يتم استخدام التكوين التاليين بشكل أساسي لتمكين دعم شرح الشيرو AOP. استخدام طريقة الوكيل ؛ لذلك تحتاج إلى تمكين دعم الكود ؛ * regurn */ @beandependson ("LifecyCleBeanPostProcessor") Public DefaultAdvisorautOproxyCreator getDefaultAdvisorautoproxyCreator () {defaultAdvisorautoproxycreator daap = new DefaultAdrauproxyCreator () ؛ daap.setproxytargetClass (صواب) ؛ إرجاع داب. } / ** * param securitymanager * @return * / bean publicizationAtributesourCeadVisor getAuthorizationAttributesourCeadVisor (DefaultWebSecurityManager SecurityManager) {elevitizationTributesourCeadVisor DuittRibutesourceadVisor = New AuthorizationArtIrizOrCeadVisor () ؛ EantaLyatTributesourCeadVisor.SetSecurityManager (SecurityManager) ؛ Return OfferizationAtRibutesourCeadVisor ؛ } / *** cas filter* return* / @bean (name = "casfilter") public casfilter getCasfilter () {casfilter casfilter = new casfilter () ؛ casfilter.setName ("casfilter") ؛ casfilter.setEnabled (true) ؛ . إرجاع casfilter. } / ** * إنشاء وتهيئة shirofilter باستخدام وضع المصنع * param securitymanager * param casfilter * return * / @bean (name = "shirofilter") shirofilterfactorybean getShiRofilterfactorybean (defaultWebsCurutionManager SecurityManager ، 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> Filters = New LinkedHashMap <> () ؛ Filters.put ("casfilter" ، casfilter) ؛ // تم استبدال LogOut بـ One-Point LogOut // filters.put ("logout" ، logoutFilter ()) ؛ shirofilterfactorybean.setFilters (المرشحات) ؛ loadshirofilterchain (shirofilterfactorybean) ؛ إرجاع shirofilterfactorybean ؛ } /*** قم بتحميل قواعد التحكم في إذن Shirofilter (اقرأ من قاعدة البيانات ثم تكوينها) ، يتم توفير معلومات الدور /الإذن بواسطة كائن MyShiroCasRealM. DOGETAuthorizationInfo تنفيذ. * سيتم وضع هذا الجزء من القواعد في قاعدة البيانات أثناء الإنتاج * param shirofilterfactorybean */private void loadshirofilterchain (shirofilterfactorybean shirofilterfactorybean) {////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ملف التكوين. لاحظ أن المرشح الذي تم إضافته هنا يجب أن يكون منظمًا ، لذا استخدم LinkedHashMap ////////////////////////////////////////////////////////////////////خريطة <string ، String> filterChainDefinitionMap = New Linkedhashmap <string> () FilterChainDefinitionMap.put (casfilterurlpattern ، "casfilter") ؛ // 2. الطلبات التي لا تعترض filterchaindefinitionmap.put ("/css/**" ، "anon") ؛ FilterChainDefinitionMap.put ("/JS/**" ، "Anon") ؛ FilterChainDefinitionMap.put ("/login" ، "anon") ؛ // هنا ، قم بتعيين صفحة تسجيل الخروج على Anon ، وليس تسجيل الدخول ، لأنه تتم معالجة عمليات تسجيل الدخول بنقطة واحدة ، ولا تحتاج إلى اعتراضها بواسطة Shiro FilterChainDefinitionMap.pt (/logout "،" Anon ") ؛ FilterChainDefinitionMap.put ("/error" ، "anon") ؛ // 3. الطلبات المعتادة (الحصول على قاعدة البيانات المحلية أو من Casserver (الطرق عن بُعد مثل WebService ، HTTP ، وما إلى ذلك) ، انظر إلى أين يتم تكوين أذونات الدور) FilterChainDefinitionMap.pt ("/user" ، "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 ؛ /*** الإذن التحقق من الفئة الأساسية ؛ نظرًا لاستخدام تسجيل الدخول الفردي ، ليست هناك حاجة للمصادقة ، فالمناسبة فقط * * @auuthor chhliu */ public class myshirorealm يمتد casrealm {resource userinfoservice userinfoservice ؛ / *** 1. مصادقة CAS ، تحقق من هوية المستخدم* 2. اضبط المعلومات الأساسية للمستخدم في الجلسة لسهولة الوصول* 3. يمكن لهذه الطريقة استخدام طريقة المصادقة مباشرة في CASREALM ، والتي تُستخدم فقط كاختبار*/ Override مصادقة محمية في ClassicationInfo doggetauthenticationInfo (anuffectionToken token) {استدعاء طريقة المصادقة الأصلية. قامت CASEREALM بتنفيذ نقطة واحدة من المصادقة بالنسبة لنا. AuthenticationInfo Authc = super.dogetauthenticationInfo (رمز) ؛ // احصل على حساب مسجّل. بعد نجاح مصادقة CAS ، سيتم حفظ الحساب. string account = (string) authc.getPrincipals (). getPrimaryPrincipal () ؛ // حفظ معلومات المستخدم في الجلسة لسهولة الاستحواذ على البرنامج. هنا يمكنك وضع معلومات المستخدم التي يتم الاستعلام عنها استنادًا إلى حساب تسجيل الدخول في SessionUtilStilStilSubject (). GetSession (). إرجاع AUTHC ؛ } /*** سيتم إجراء رد الاتصال فقط عندما تستدعي هذه الطريقة هاسول و haspermission. * * معلومات الإذن. (إذن): 1. إذا خرج المستخدم بشكل طبيعي ، فسيتم مسح ذاكرة التخزين المؤقت تلقائيًا ؛ 2. إذا خرج المستخدم بشكل غير طبيعي ، فسيتم مسح ذاكرة التخزين المؤقت تلقائيًا ؛ * 3. إذا قمنا بتعديل أذونات المستخدم ولكن المستخدم لا يسجل الخروج من النظام ، فلن تسري الأذونات المعدلة على الفور. (يجب تنفيذها يدويًا ؛ وضعت في الخدمة للاتصال) * بعد تعديل الإذن ، يتم استدعاء الطريقة في عالم. تمت إدارة عالم الربيع بحلول الربيع ، لذلك يتم الحصول على مثيل العالم من الربيع ويتم تسمى الطريقة ClearCached ؛ *: التفويض هو التحكم في الوصول المعتمدة ، يستخدم للتفويض من العملية التي يقوم بها المستخدم ، مما يثبت ما إذا كان المستخدم يسمح للعملية الحالية ، مثل الوصول إلى رابط معين ، وملف مورد معين ، إلخ. التكوين-> myshirorealm.dogetauthorizationInfo () ") ؛ SimpleAuthorizationInfo EmitalizationInfo = new SimpleAuthorizationInfo () ؛ // احصل على اسم المستخدم بعد تسجيل الدخول المفرد ، يمكنك أيضًا الحصول عليه من الجلسة ، لأنه بعد نجاح المصادقة ، تم وضع اسم المستخدم في اسم مستخدم سلسلة الجلسة = (String) Super.GetAvailablePrincipal (المديرين) ؛ // principals.getPrimaryPrincipal () ؛ يمكن أن تحصل هذه الطريقة أيضًا على اسم المستخدم // الحصول على دور المستخدم وإذنه بناءً على اسم المستخدم UserInfo userInfo = userInfoservice.findbyusername (اسم المستخدم) ؛ // حزمة الدور المقابل للمستخدم وإذنه في إذن (sysrole row: userInfo.getRolelist ()) {efurnizationInfo.addrole (rob.getRole ()) ؛ لـ (syspermission p: roly.getPermissions ()) {uputizationInfo.addStringPermission (p.getPermission ()) ؛ }} إرجاع التفويض }} بعد ذلك ، يمكننا إجراء اختبارات التحقق!
أدخل http: 127.0.1.28: 8080/userinfo/قائمة المستخدمين في المتصفح وسوف نجد أنه سيقفز تلقائيًا إلى صفحة تسجيل الدخول إلى نقطة واحدة
ثم ندخل اسم المستخدم وكلمة المرور ، وسوف نقفز تلقائيًا إلى HTTP: 127.0.1.28: 8080/userInfo/userlist.
ما سبق هو كل محتوى هذه المقالة. آمل أن يكون ذلك مفيدًا لتعلم الجميع وآمل أن يدعم الجميع wulin.com أكثر.