Apa itu Shiro
Shiro adalah kerangka izin sumber terbuka untuk platform Java untuk otentikasi dan otorisasi akses. Secara khusus, dukungan untuk elemen -elemen berikut dipenuhi:
T: Dukungan untuk grup?
A: Shiro tidak mendukung izin pengaturan untuk grup secara default.
T: Bisakah memenuhi kebutuhan alokasi peran untuk kelompok?
A: Perluasan ranah dapat mendukung penugasan peran ke grup, yang sebenarnya untuk menetapkan izin untuk semua pengguna di bawah grup.
T: Dukungan untuk izin data? Didefinisikan dalam sistem bisnis?
A: Shiro hanya mengimplementasikan kontrol atas izin operasi, yang digunakan untuk menyembunyikan atau menampilkan elemen kontrol front-end dan memeriksa izin akses sumber daya. Izin data terkait erat dengan kebutuhan bisnis tertentu, dan Shiro sendiri tidak dapat mengontrol izin data.
T: Alokasi izin dinamis?
A: Perpanjang org.apache.shiro.realm.realm untuk mendukung alokasi izin dinamis.
T: Integrasi dengan Spring?
A: Ini dapat mendukung integrasi dengan Spring, dan Shiro juga mendukung tag JSP.
Di blog sebelumnya, kami berbicara tentang dua fitur, otentikasi, dan otorisasi terbesar Shiro. Masuk tunggal juga merupakan bagian dari otentikasi. Secara default, Shiro telah menerapkan integrasi dengan CAS untuk kami, dan akan baik -baik saja jika kami menambahkan beberapa konfigurasi terintegrasi.
1. Tambahkan paket shiro-cas
<!-Shiro mengintegrasikan CAS Single Point-> <dependency> <GroupId> org.apache.shiro </groupid> <ArTifactId> Shiro-Cas </artifactid> <version> 1.2.4 </version> </dependensi>
2. Tambahkan konfigurasi masuk tunggal
Di sini, saya memposting semua konfigurasi untuk referensi yang mudah, dan instruksi terperinci telah ditambahkan ke konfigurasi.
paket com.chhliu.springboot.shiro.config; impor java.util.linkedhashmap; impor java.util.map; impor javax.servlet.filter; impor org.apache.shiro.cache.ehcache.ehcachemanager; impor org.apache.shiro.cas.casfilter; impor org.apache.shiro.cas.cassubjectFactory; impor org.apache.shiro.spring.lifecycleBeanPostProcessor; impor org.apache.shiro.spring.security.interceptor.authorizationAttributeSourceadVisor; impor org.apache.shiro.spring.web.shirofilterfactorybean; impor org.apache.shiro.web.mgt.defaultwebsecurityManager; impor org.jasig.cas.client.Session.SinglesignoutFilter; impor org.jasig.cas.client.Session.SinglesignouthttpsessionListener; impor org.springframework.aop.framework.autoproxy.defaultAdvisorAutoproxyCreator; impor org.springframework.boot.web.servlet.filterregistrationBean; impor org.springframework.boot.web.servlet.servletlistenerregistrationBean; impor org.springframework.context.annotation.bean; impor org.springframework.context.annotation.configuration; impor org.springframework.context.annotation.dependson; impor org.springframework.core.ordered; impor org.springframework.core.annotation.order; impor org.springframework.web.filter.delegatingfilterproxy; /*** Konfigurasi Shiro** Apache Shiro Core diimplementasikan melalui filter, sama seperti SpringMVC menggunakan dispachservlet untuk mengendalikannya. Karena kami menggunakan * filter, kami umumnya dapat menebak bahwa pemfilteran dan verifikasi izin dilakukan melalui aturan URL, jadi kami perlu mendefinisikan serangkaian aturan dan mengakses hak tentang URL. * * @author chhliu */@configuration kelas publik shiroconfiguration {// cas address server public static final string casserverurlprefix = "http://127.0.0.1"; // CAS Halaman Login Alamat Public Static Final String Casloginurl = CasserverUrlPrefix + "/Login"; // CAS LOGOUT Halaman Alamat Public Static Final String caslogoutUrl = casserverurlprefix + "/logout"; // Alamat layanan saat ini yang disediakan oleh proyek ke luar dunia luar statis public static shiroServerurlprefix = "http://127.0.1.28:8080"; // casfilter urlpattern public static final string casfilterurlpattern = "/index"; // Alamat login Public Static Final String LoginUrl = casloginurl + "? Service =" + ShiroServerUrlPrefix + casfilterurlPattern; // Alamat Logout (Casserver Mengaktifkan fungsi lompatan layanan, dan Anda perlu mengaktifkan cas.logout.followserviceredirects = true di Webapps/cas/web-inf/cas.properties file) public static string final string finalUrl = caslogoutUrl+"? Layanan ="+Loginurl; // Login Alamat Sukses // String Akhir Statis Public LoginsucCessUrl = "/Index"; // Otentikasi Izin Gagal lompat alamat public static final string unrorizedUrl = "/Error/403.html"; / ** *Instantiate SecurityManager, kelas ini adalah kelas inti Shiro */ @return */ @bean DefaultWebSecurityManager SecurityManager () {DefaultWebSecurityManager SecurityManager = New DefaultWebSecurityManager (); SecurityManager.setrealm (myshirocasrealm ()); // <!-Otorisasi Pengguna/Informasi Otentikasi Cache, menggunakan EHCACHE CACHE-> SecurityManager.setCachemanager (getehcacheManager ()); // Tentukan SubjectFactory. Jika Anda ingin mengimplementasikan fungsi Remember Me dari CAS, Anda perlu menggunakan CassubjectFactory berikut dan mengaturnya ke SUMNYMANAGER SUBBACTFACTORY SecurityManager. Return SecurityManager; } / *** Konfigurasikan cache* @return* / @bean ehcachemanager getehcachemanager () {ehcachemanager em = ehcachemanager baru (); em.setCachemanAgerConfigFile ("classpath: config/ehcache-shiro.xml"); mengembalikan mereka; } /*** Mengkonfigurasi ranah. Karena kami menggunakan casrealm, fungsi masuk tunggal telah terintegrasi * @param cachemanager * @return */ @bean public myshirorealm myshirocasrealm () {myshirorealm ranah = myshirorealm baru (); // CAS Login Server Address Prefix Realm.SetCasserverUrlPrefix (ShiroConfiguration.CasserverUrlPrefix); // Alamat Callback Klien, Lompat Alamat Setelah Masuk Berhasil (Alamat Layanannya Sendiri) Realm.SetCasservice (ShiroConfiguration.ShiroServerurlprefix + shiroconfiguration.casfilterurlpattern); // Peran default setelah login berhasil, di sini default untuk peran pengguna realm.setDefaultroles ("pengguna"); Return Realm; }/ ** * Daftarkan pendengar masuk tunggal * @return */ @suppresswarnings ({"rawtypes", "uncecked"}) @bean @order (ordered.highest_precedence) // prioritas lebih tinggi dari cas publiclistenerregistration <? ServletListenerRegistrationBean (); bean.setListener (singlesignouthttpsessionlistener baru ()); bean.setenabled (true); Kembalikan kacang; } / ** * Daftarkan filter masuk tunggal * @return * / @bean filterregistrationBean singlemignoutfilter () {filterregistrationBean bean = new filterregistrationBean (); bean.setname ("singlemersignoutfilter"); bean.setfilter (SingLemersignoutFilter baru ()); bean.addurlpatterns ("/*"); bean.setenabled (true); Kembalikan kacang; } / ** * Register delegatingFilterproxy (shiro) * / @bean filterregistrationBean delegatingFilterproxy () {filterregistrationBean filterregistration = new filterregistrationBean (); filterregistration.setFilter (delegatingFilterproxy baru ("shirofilter")); // Nilai ini salah secara default, menunjukkan bahwa siklus hidup dikelola oleh SpringApplicationContext. Ditetapkan ke true berarti bahwa servletContainer dikelola oleh filterregistration.addinitparameter ("targetFilterlifecycle", "true"); filterregistration.setenabled (true); filterregistration.addurlpatterns ("/*"); return filterregistration; } / *** Kelas ini dapat memastikan bahwa metode init atau destory dari objek Shiro yang mengimplementasikan org.apache.shiro.util.initializable antarmuka secara otomatis dipanggil,* tanpa secara manual menentukan metode init-Method atau destorion (Metode Metode* Catatan: Jika kelas ini digunakan, tidak perlu untuk menentukan metode inisialisasi @ @ @ @ @ "LifecyclebeanPostProcessor") Publik LifecyclebeanPostProcessor getlifecycleBeanPostProcessor () {return LifecycleBeanPostProcessor () baru; } /*** Dua konfigurasi berikut terutama digunakan untuk memungkinkan dukungan anotasi Shiro AOP. Gunakan metode proxy; Jadi Anda perlu mengaktifkan dukungan kode; * @return */ @bean @dependson ("LifeCycleBeanPostProcessor") Public DefaultAdvisorAutOproxyCreator GetDefaultAdvisorAutoproxyCreator () {defaultAdvisorAutoproxycreator DAAP = DefaultAdvaultAdvisorRoxRoxRoxyCreate (); daap.setProxyTargetClass (true); mengembalikan daap; } /** * @param securityManager * @return */ @Bean public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) { AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor(); OtorisasiTributSourceadVisor.SetsecurityManager (SecurityManager); return otorisasiArtributeSourceadvisor; } / *** CAS filter* @return* / @bean (name = "casfilter") casfilter publik getCasfilter () {casfilter casfilter = new casfilter (); casfilter.setname ("casfilter"); casfilter.setenabled (true); // URL yang melompat setelah login gagal, yaitu, Shiro mengeksekusi metode dogetAuthenticationInfo dari casrealm untuk memverifikasi tiket casfilter.setfailureUrl (loginurl); // kami memilih untuk membuka halaman login setelah otentikasi gagal casfilter.setloginurl (LOGINURL); Kembalikan Casfilter; } / ** * Buat dan inisialisasi shirofilter menggunakan mode pabrik * @param SecurityManager * @param casfilter * @return * / @bean (name = "shirofilter") public shirofilterfactorybean getshirofilterfactorybean (defaultWebSeCurityManager SecurityManager, casfilter casfilterkorybean {DefaultWebSecurityManager, casfilter CasfilterkoryBean {DefaultWeSekurityManager, Casfilter Casfilter. Casfilterbeand {DefaultWeansManager, shirofilterfactorybean = baru shirofilterfactorybean (); // SecurityManager harus ditetapkan ShirofilterFactoryBean.SetsecurityManager (SecurityManager); // Jika Anda tidak mengatur default, itu akan secara otomatis menemukan halaman "/login.jsp" di direktori root proyek web shirofilterfactorybean.setloginurl (loginurl); / * * Koneksi yang akan dialihkan setelah login berhasil. Jika tidak diatur, itu akan melompat ke URL sebelumnya secara default. * Misalnya, Anda pertama kali memasukkan http: // localhost: 8080/userlist di browser, tetapi sekarang pengguna tidak masuk, sehingga akan melompat ke halaman login. Setelah otentikasi login dilewati, halaman * akan secara otomatis melompat ke halaman http: // localhost: 8080/userlist alih -alih halaman indeks setelah login berhasil. Bidang ini tidak disarankan untuk diatur */ // shirofilterfactorybean.setsuccessurl (loginsuccessurl); // atur akses tidak sah ke halaman shirofilterfactorybean.setunauthorizedUrl (tidak sah); / * * Tambahkan Casfilter ke Shirofilter. Perhatikan bahwa Casfilter perlu ditempatkan di depan shirofilter, * untuk memastikan bahwa program akan memasukkan otentikasi titik tunggal sebelum memasukkan login login Shiro */ peta <string, filter> filter = LinkedHashMap baru <> (); filter.put ("casfilter", casfilter); // Logout telah diganti dengan logout titik tunggal // filter.put ("Logout", LogoutFilter ()); shirofilterfactorybean.setfilters (filter); loadshirofilterchain (shirofilterfactorybean); kembalikan shirofilterfactorybean; } /*** Muat aturan kontrol izin shirofilter (dibaca dari database dan kemudian mengkonfigurasi), informasi peran /izin disediakan oleh objek myshirocasrealm. Implementasi DoGetauthorizationInfo. * Bagian aturan ini akan ditempatkan dalam database selama produksi * @param shirofilterfactorybean */private void loadshirofilterchain (shirofilterfactorybean shirofilterfactorybean {////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// file. 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. Permintaan yang tidak mencegat filterchainDefinitionMap.put ("/css/**", "anon"); filterChainDefinitionMap.put ("/js/**", "anon"); filterChainDefinitionMap.put ("/login", "anon"); // Di sini, atur halaman logout ke anon, bukan logout, karena logout diproses oleh satu titik, dan tidak perlu dicegat oleh logoutfilter shiro filterchaindefinitionmap.put ("/logout", "anon"); filterChainDefinitionMap.put ("/error", "anon"); // 3. Permintaan yang dicegat (dapatkan dari database lokal atau dari casserver (metode jarak jauh seperti layanan web, http, dll.), Lihat di mana izin peran Anda dikonfigurasi) filterChainDefinitionMap.put ("/user", "authc"); // Login diperlukan // 4. Login tidak mencegat filterChainDefinitionMap.put ("/**", "authc"); shirofilterfactorybean.setfilterchaindefinitionMap (filterchainDefinitionMap); }}Beberapa referensi konfigurasi: http://shiro.apache.org/spring.html
3. Tulis Realm
Karena kita perlu mengintegrasikan fungsi masuk tunggal, kita perlu mengintegrasikan kelas Casrealm. Kelas ini telah menerapkan fungsi otentikasi titik tunggal untuk kami. Yang perlu kita lakukan adalah mengimplementasikan fungsi bagian otorisasi. Kode contoh adalah sebagai berikut:
paket com.chhliu.springboot.shiro.config; impor javax.annotation.Resource; impor org.apache.shiro.securityutils; impor org.apache.shiro.authc.authenticationInfo; impor org.apache.shiro.authc.authenticationToken; impor org.apache.shiro.authz.authenticationInfo; impor org.apache.shiro.authz.simpleauthorizationInfo; impor org.apache.shiro.cas.casrealm; impor org.apache.shiro.subject.principalcollection; impor com.chhliu.springboot.shiro.mode.syspermission; impor com.chhliu.springboot.shiro.mode.syspermission; impor com.chhliu.springboot.shiro.mode.userinfo; impor com.chhliu.springboot.shiro.service.userinfoservice; /*** Kelas inti verifikasi izin; Karena masuk tunggal digunakan, tidak perlu mengotentikasi, hanya otorisasi yang diperlukan * * @author chhliu */ kelas publik myshirorealm memperluas casrealm {@resource private userinfoserFoservice userinfoservice; / *** 1. Otentikasi CAS, verifikasi identitas pengguna* 2. Atur informasi dasar pengguna ke dalam sesi untuk akses mudah* 3. Metode ini dapat secara langsung menggunakan metode otentikasi dalam casrealm, yang hanya digunakan sebagai tes*/ @override AuthenticationInfo dogetAuthenticationIncy (authenticationtokentoken) {// call class in authenticationIncation in authenticationIncation (authentication. Casrealm telah menerapkan satu titik otentikasi untuk kami. AuthenticationInfo authc = super.dogetauthenticationInfo (token); // Dapatkan akun yang masuk. Setelah otentikasi CAS berhasil, akun akan disimpan. String Account = (String) authc.getPrincipals (). GetPrimaryPrincipal (); // Simpan informasi pengguna ke dalam sesi untuk akuisisi program yang mudah. Di sini Anda dapat menempatkan informasi pengguna ditanya berdasarkan akun login ke sesi SecurityUtils.getSubject (). GetSession (). SetAttribute ("no", akun); mengembalikan authc; } /*** Callback akan dilakukan hanya ketika metode ini memanggil Hasrole dan Haspermisi. * * Informasi Izin. (Otorisasi): 1. Jika pengguna keluar secara normal, cache akan secara otomatis dihapus; 2. Jika pengguna keluar secara abnormal, cache akan secara otomatis dihapus; * 3. Jika kami memodifikasi izin pengguna tetapi pengguna tidak keluar dari sistem, izin yang dimodifikasi tidak dapat segera berlaku. (Perlu diimplementasikan secara manual; dimasukkan ke dalam layanan untuk panggilan) * Setelah izin dimodifikasi, metode di ranah dipanggil. Ranah telah dikelola oleh Spring, sehingga instance ranah diperoleh dari musim semi dan metode clearcached disebut; * :Authorization is authorized access control, used to authorize the operation performed by the user, proving whether the user allows the current operation, such as accessing a certain link, a certain resource file, etc. * * @param principals * @return */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { System.out.println("Permission Konfigurasi-> myshirorealm.dogetauthorizationInfo () "); SimpleauthorizationInfo otorisasiinfo = SimpleauthorizationInfo baru (); // Dapatkan nama pengguna setelah masuk tunggal, Anda juga bisa mendapatkannya dari sesi, karena setelah otentikasi berhasil, nama pengguna telah dimasukkan ke dalam sesi string username = (string) super.getavailablePrincipal (prinsipal); // principals.getPrimaryPrincipal (); Metode ini juga dapat memperoleh nama pengguna // memperoleh peran dan informasi izin pengguna berdasarkan nama pengguna userInfo userInfo = userInfoservice.findbyusername (nama pengguna); // paket peran dan informasi izin yang sesuai pengguna ke dalam otorisasiinfo untuk (peran sysrole: userInfo.getrolelist ()) {otorizationInfo.addole (role.getrole ()); untuk (syspermission p: role.getpermissions ()) {otorizationInfo.addstringPerMission (p.getPerMission ()); }} return otorizationInfo; }} Selanjutnya, kita dapat melakukan tes verifikasi!
Masukkan http: 127.0.1.28: 8080/UserInfo/UserList di browser dan kami akan menemukan bahwa itu akan secara otomatis melompat ke halaman login titik tunggal
Kemudian kami memasukkan nama pengguna dan kata sandi dan secara otomatis akan melompat ke http: 127.0.1.28: 8080/halaman UserInfo/UserList.
Di atas adalah semua konten artikel ini. Saya berharap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.