亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Java > 正文

spring boot整合Shiro實現單點登錄的示例代碼

2024-07-13 10:17:22
字體:
來源:轉載
供稿:網友

Shiro是什么

Shiro是一個Java平臺的開源權限框架,用于認證和訪問授權。具體來說,滿足對如下元素的支持:

  1. 用戶,角色,權限(僅僅是操作權限,數據權限必須與業務需求緊密結合),資源(url)。
  2. 用戶分配角色,角色定義權限。
  3. 訪問授權時支持角色或者權限,并且支持多級的權限定義。

Q:對組的支持?
A:shiro默認不支持對組設置權限。

Q:是否可以滿足對組進行角色分配的需求?
A:擴展Realm,可以支持對組進行分配角色,其實就是給該組下的所有用戶分配權限。

Q:對數據權限的支持? 在業務系統中定義?
A:shiro僅僅實現對操作權限的控制,用于在前端控制元素隱藏或者顯示,以及對資源訪問權限進行檢查。數據權限與具體的業務需求緊密關聯,shiro本身無法實現對數據權限的控制。

Q:動態權限分配?
A:擴展org.apache.shiro.realm.Realm,支持動態權限分配。

Q:與Spring集成?
A:可以支持與Spring集成,shiro還支持jsp標簽。

前面的博客中,我們說道了Shiro的兩個最大的特點,認證和授權,而單點登錄也是屬于認證的一部分,默認情況下,Shiro已經為我們實現了和Cas的集成,我們加入集成的一些配置就ok了。

1、加入shiro-cas包

<!-- shiro整合cas單點 -->     <dependency>       <groupId>org.apache.shiro</groupId>       <artifactId>shiro-cas</artifactId>       <version>1.2.4</version>     </dependency> 

2、加入單點登錄的配置

這里,我將所有的配置都貼出來,方便參考,配置里面已經加了詳盡的說明。

package com.chhliu.springboot.shiro.config;  import java.util.LinkedHashMap; import java.util.Map; import javax.servlet.Filter; import org.apache.shiro.cache.ehcache.EhCacheManager; import org.apache.shiro.cas.CasFilter; import org.apache.shiro.cas.CasSubjectFactory; import org.apache.shiro.spring.LifecycleBeanPostProcessor; import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.jasig.cas.client.session.SingleSignOutFilter; import org.jasig.cas.client.session.SingleSignOutHttpSessionListener; import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.boot.web.servlet.ServletListenerRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.DependsOn; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.web.filter.DelegatingFilterProxy;  /**  * Shiro 配置  *  * Apache Shiro 核心通過 Filter 來實現,就好像SpringMvc 通過DispachServlet 來主控制一樣。 既然是使用  * Filter 一般也就能猜到,是通過URL規則來進行過濾和權限校驗,所以我們需要定義一系列關于URL的規則和訪問權限。  *  * @author chhliu  */ @Configuration public class ShiroConfiguration {      // cas server地址   public static final String casServerUrlPrefix = "http://127.0.0.1";   // Cas登錄頁面地址   public static final String casLoginUrl = casServerUrlPrefix + "/login";   // Cas登出頁面地址   public static final String casLogoutUrl = casServerUrlPrefix + "/logout";   // 當前工程對外提供的服務地址   public static final String shiroServerUrlPrefix = "http://127.0.1.28:8080";   // casFilter UrlPattern   public static final String casFilterUrlPattern = "/index";   // 登錄地址   public static final String loginUrl = casLoginUrl + "?service=" + shiroServerUrlPrefix + casFilterUrlPattern;   // 登出地址(casserver啟用service跳轉功能,需在webapps/cas/WEB-INF/cas.properties文件中啟用cas.logout.followServiceRedirects=true)   public static final String logoutUrl = casLogoutUrl+"?service="+loginUrl;   // 登錄成功地址 //  public static final String loginSuccessUrl = "/index";   // 權限認證失敗跳轉地址   public static final String unauthorizedUrl = "/error/403.html";      /**    * 實例化SecurityManager,該類是shiro的核心類    * @return    */   @Bean   public DefaultWebSecurityManager securityManager() {     DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();     securityManager.setRealm(myShiroCasRealm()); //   <!-- 用戶授權/認證信息Cache, 采用EhCache 緩存 -->     securityManager.setCacheManager(getEhCacheManager());     // 指定 SubjectFactory,如果要實現cas的remember me的功能,需要用到下面這個CasSubjectFactory,并設置到securityManager的subjectFactory中     securityManager.setSubjectFactory(new CasSubjectFactory());     return securityManager;   }    /**    * 配置緩存    * @return    */   @Bean   public EhCacheManager getEhCacheManager() {     EhCacheManager em = new EhCacheManager();     em.setCacheManagerConfigFile("classpath:config/ehcache-shiro.xml");     return em;   }    /**    * 配置Realm,由于我們使用的是CasRealm,所以已經集成了單點登錄的功能    * @param cacheManager    * @return    */   @Bean   public MyShiroRealm myShiroCasRealm() {     MyShiroRealm realm = new MyShiroRealm();     // cas登錄服務器地址前綴     realm.setCasServerUrlPrefix(ShiroConfiguration.casServerUrlPrefix);     // 客戶端回調地址,登錄成功后的跳轉地址(自己的服務地址)     realm.setCasService(ShiroConfiguration.shiroServerUrlPrefix + ShiroConfiguration.casFilterUrlPattern);     // 登錄成功后的默認角色,此處默認為user角色     realm.setDefaultRoles("user");     return realm;   }    /**    * 注冊單點登出的listener    * @return    */   @SuppressWarnings({ "rawtypes", "unchecked" })   @Bean   @Order(Ordered.HIGHEST_PRECEDENCE)// 優先級需要高于Cas的Filter   public ServletListenerRegistrationBean<?> singleSignOutHttpSessionListener(){     ServletListenerRegistrationBean bean = new ServletListenerRegistrationBean();     bean.setListener(new SingleSignOutHttpSessionListener());     bean.setEnabled(true);     return bean;   }    /**    * 注冊單點登出filter    * @return    */   @Bean   public FilterRegistrationBean singleSignOutFilter(){     FilterRegistrationBean bean = new FilterRegistrationBean();     bean.setName("singleSignOutFilter");     bean.setFilter(new SingleSignOutFilter());     bean.addUrlPatterns("/*");     bean.setEnabled(true);     return bean;   }    /**    * 注冊DelegatingFilterProxy(Shiro)    */   @Bean   public FilterRegistrationBean delegatingFilterProxy() {     FilterRegistrationBean filterRegistration = new FilterRegistrationBean();     filterRegistration.setFilter(new DelegatingFilterProxy("shiroFilter"));     // 該值缺省為false,表示生命周期由SpringApplicationContext管理,設置為true則表示由ServletContainer管理     filterRegistration.addInitParameter("targetFilterLifecycle", "true");     filterRegistration.setEnabled(true);     filterRegistration.addUrlPatterns("/*");     return filterRegistration;   }    /**    * 該類可以保證實現了org.apache.shiro.util.Initializable接口的shiro對象的init或者是destory方法被自動調用,    * 而不用手動指定init-method或者是destory-method方法    * 注意:如果使用了該類,則不需要手動指定初始化方法和銷毀方法,否則會出錯    * @return    */   @Bean(name = "lifecycleBeanPostProcessor")   public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {     return new LifecycleBeanPostProcessor();   }    /**    * 下面兩個配置主要用來開啟shiro aop注解支持. 使用代理方式;所以需要開啟代碼支持;    * @return    */   @Bean   @DependsOn("lifecycleBeanPostProcessor")   public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {     DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();     daap.setProxyTargetClass(true);     return daap;   }      /**    * @param securityManager    * @return    */   @Bean   public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {     AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();     authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);     return authorizationAttributeSourceAdvisor;   }    /**    * CAS過濾器    * @return    */   @Bean(name = "casFilter")   public CasFilter getCasFilter() {     CasFilter casFilter = new CasFilter();     casFilter.setName("casFilter");     casFilter.setEnabled(true);     // 登錄失敗后跳轉的URL,也就是 Shiro 執行 CasRealm 的 doGetAuthenticationInfo 方法向CasServer驗證tiket     casFilter.setFailureUrl(loginUrl);// 我們選擇認證失敗后再打開登錄頁面     casFilter.setLoginUrl(loginUrl);     return casFilter;   }    /**    * 使用工廠模式,創建并初始化ShiroFilter    * @param securityManager    * @param casFilter    * @return    */   @Bean(name = "shiroFilter")   public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager, CasFilter casFilter) {     ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();     // 必須設置 SecurityManager     shiroFilterFactoryBean.setSecurityManager(securityManager);     // 如果不設置默認會自動尋找Web工程根目錄下的"/login.jsp"頁面     shiroFilterFactoryBean.setLoginUrl(loginUrl);     /*      * 登錄成功后要跳轉的連接,不設置的時候,會默認跳轉到前一步的url      * 比如先在瀏覽器中輸入了http://localhost:8080/userlist,但是現在用戶卻沒有登錄,于是會跳轉到登錄頁面,等登錄認證通過后,      * 頁面會再次自動跳轉到http://localhost:8080/userlist頁面而不是登錄成功后的index頁面      * 建議不要設置這個字段      */ //    shiroFilterFactoryBean.setSuccessUrl(loginSuccessUrl);          // 設置無權限訪問頁面     shiroFilterFactoryBean.setUnauthorizedUrl(unauthorizedUrl);     /*      * 添加casFilter到shiroFilter中,注意,casFilter需要放到shiroFilter的前面,      * 從而保證程序在進入shiro的login登錄之前就會進入單點認證      */     Map<String, Filter> filters = new LinkedHashMap<>();     filters.put("casFilter", casFilter);          // logout已經被單點登錄的logout取代     // filters.put("logout",logoutFilter());     shiroFilterFactoryBean.setFilters(filters);      loadShiroFilterChain(shiroFilterFactoryBean);     return shiroFilterFactoryBean;   }    /**    * 加載shiroFilter權限控制規則(從數據庫讀取然后配置),角色/權限信息由MyShiroCasRealm對象提供doGetAuthorizationInfo實現獲取來的    * 生產中會將這部分規則放到數據庫中    * @param shiroFilterFactoryBean    */   private void loadShiroFilterChain(ShiroFilterFactoryBean shiroFilterFactoryBean){     /////////////////////// 下面這些規則配置最好配置到配置文件中,注意,此處加入的filter需要保證有序,所以用的LinkedHashMap ///////////////////////     Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();      filterChainDefinitionMap.put(casFilterUrlPattern, "casFilter");      //2.不攔截的請求     filterChainDefinitionMap.put("/css/**","anon");     filterChainDefinitionMap.put("/js/**","anon");     filterChainDefinitionMap.put("/login", "anon");     // 此處將logout頁面設置為anon,而不是logout,因為logout被單點處理,而不需要再被shiro的logoutFilter進行攔截     filterChainDefinitionMap.put("/logout","anon");     filterChainDefinitionMap.put("/error","anon");     //3.攔截的請求(從本地數據庫獲取或者從casserver獲取(webservice,http等遠程方式),看你的角色權限配置在哪里)     filterChainDefinitionMap.put("/user", "authc"); //需要登錄     //4.登錄過的不攔截     filterChainDefinitionMap.put("/**", "authc");     shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);   } } 

部分配置參考:http://shiro.apache.org/spring.html

3、編寫Realm

由于需要集成單點登錄的功能,所以需要集成CasRealm類,該類已經為我們實現了單點認證的功能,我們要做的就是實現授權部分的功能,示例代碼如下:

package com.chhliu.springboot.shiro.config;  import javax.annotation.Resource;  import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.cas.CasRealm; import org.apache.shiro.subject.PrincipalCollection;  import com.chhliu.springboot.shiro.mode.SysPermission; import com.chhliu.springboot.shiro.mode.SysRole; import com.chhliu.springboot.shiro.mode.UserInfo; import com.chhliu.springboot.shiro.service.UserInfoService;  /**  * 權限校驗核心類; 由于使用了單點登錄,所以無需再進行身份認證 只需要授權即可  *  * @author chhliu  */ public class MyShiroRealm extends CasRealm {    @Resource   private UserInfoService userInfoService;    /**    * 1、CAS認證 ,驗證用戶身份    * 2、將用戶基本信息設置到會話中,方便獲取    * 3、該方法可以直接使用CasRealm中的認證方法,此處僅用作測試    */   @Override   protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {      // 調用父類中的認證方法,CasRealm已經為我們實現了單點認證。     AuthenticationInfo authc = super.doGetAuthenticationInfo(token);      // 獲取登錄的賬號,cas認證成功后,會將賬號存起來     String account = (String) authc.getPrincipals().getPrimaryPrincipal();      // 將用戶信息存入session中,方便程序獲取,此處可以將根據登錄賬號查詢出的用戶信息放到session中     SecurityUtils.getSubject().getSession().setAttribute("no", account);      return authc;   }    /**    * 此方法調用 hasRole,hasPermission的時候才會進行回調.    *    * 權限信息.(授權): 1、如果用戶正常退出,緩存自動清空; 2、如果用戶非正常退出,緩存自動清空;    * 3、如果我們修改了用戶的權限,而用戶不退出系統,修改的權限無法立即生效。 (需要手動編程進行實現;放在service進行調用)    * 在權限修改后調用realm中的方法,realm已經由spring管理,所以從spring中獲取realm實例, 調用clearCached方法;    * :Authorization 是授權訪問控制,用于對用戶進行的操作授權,證明該用戶是否允許進行當前操作,如訪問某個鏈接,某個資源文件等。    *    * @param principals    * @return    */   @Override   protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {     System.out.println("權限配置-->MyShiroRealm.doGetAuthorizationInfo()");      SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();     // 獲取單點登陸后的用戶名,也可以從session中獲取,因為在認證成功后,已經將用戶名放到session中去了     String userName = (String) super.getAvailablePrincipal(principals); //       principals.getPrimaryPrincipal(); 這種方式也可以獲取用戶名      // 根據用戶名獲取該用戶的角色和權限信息     UserInfo userInfo = userInfoService.findByUsername(userName);      // 將用戶對應的角色和權限信息打包放到AuthorizationInfo中     for (SysRole role : userInfo.getRoleList()) {       authorizationInfo.addRole(role.getRole());       for (SysPermission p : role.getPermissions()) {         authorizationInfo.addStringPermission(p.getPermission());       }     }      return authorizationInfo;   } } 

下面,我們就可以進行驗證測試了!

在瀏覽器輸入http:127.0.1.28:8080/userInfo/userList 我們會發現,會自動跳轉到單點的登錄頁面

spring,boot,Shiro,單點登錄

然后我們輸入用戶名和密碼,就會自動跳轉到http:127.0.1.28:8080/userInfo/userList頁面了。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久久久久久久网站| 日韩精品视频三区| 日韩在线欧美在线国产在线| 亚洲精品videossex少妇| 福利精品视频在线| 欧美日本高清视频| 国产精品第一区| 国产精品av网站| 日韩av综合网| 日日摸夜夜添一区| 欧美激情第一页xxx| 亚洲精品v欧美精品v日韩精品| 亚洲一区二区三区在线视频| 亚洲精品美女免费| 91九色单男在线观看| 久久精品国产视频| 国产午夜精品美女视频明星a级| 欧美性极品xxxx做受| 一区二区成人av| 欧美夫妻性生活视频| 最近中文字幕日韩精品| 人人做人人澡人人爽欧美| 欧美激情2020午夜免费观看| 欧美影院成年免费版| 久久这里有精品视频| 国产精品精品一区二区三区午夜版| 日韩电影中文字幕在线| 色综合色综合久久综合频道88| 国产一区视频在线| 亲子乱一区二区三区电影| 91中文精品字幕在线视频| 国产成人精品在线视频| 激情av一区二区| 日韩成人在线视频| 中日韩美女免费视频网站在线观看| 欧美激情小视频| 国产脚交av在线一区二区| 欧美亚洲国产视频小说| 欧美高清在线观看| 欧美电影免费在线观看| 国产91精品久久久久久久| 国产精品爽爽爽爽爽爽在线观看| 波霸ol色综合久久| 欧美激情成人在线视频| 日韩精品www| 欧美视频中文在线看| 国产精品久久久久久亚洲影视| 2024亚洲男人天堂| 欧美日产国产成人免费图片| 亚洲精品一二区| 国产精品精品久久久| 欧美黑人巨大xxx极品| 成人精品久久av网站| 日韩欧美成人区| y97精品国产97久久久久久| 国产精品流白浆视频| 国产成人aa精品一区在线播放| 欧美尤物巨大精品爽| 国产日韩在线亚洲字幕中文| 欧美成人中文字幕| 亚洲天堂免费视频| 国模吧一区二区| 日本高清+成人网在线观看| 亚洲国产精品va在线| 日韩暖暖在线视频| 91在线高清视频| 麻豆成人在线看| 日韩精品极品视频免费观看| 亚洲精品成人久久电影| 精品久久久久久久久中文字幕| 日韩中文字幕在线观看| 中文字幕精品网| 91免费的视频在线播放| 亚洲国产一区二区三区在线观看| 97免费在线视频| 黑人欧美xxxx| 色狠狠久久aa北条麻妃| 欧美成人精品激情在线观看| 成人黄色免费看| 午夜精品美女自拍福到在线| 国产91在线视频| 在线观看成人黄色| 亚洲电影免费观看高清完整版| 欧美午夜性色大片在线观看| 91最新在线免费观看| 亚洲一区美女视频在线观看免费| 亚洲精品一区在线观看香蕉| 亚洲精品videossex少妇| 疯狂蹂躏欧美一区二区精品| 91精品国产高清久久久久久| 日韩大片免费观看视频播放| 国内精品久久久久伊人av| 亚洲欧美制服第一页| 国产91免费看片| 国产成人拍精品视频午夜网站| 久久精品福利视频| 91久久精品美女高潮| 亚洲成人网在线观看| 91av视频在线观看| 在线观看视频亚洲| 亚洲欧美日韩一区二区三区在线| 久久男人av资源网站| 一区二区三区www| 日韩人体视频一二区| 这里只有精品丝袜| 国产啪精品视频| 亚洲va久久久噜噜噜| 国产精品电影一区| 精品亚洲夜色av98在线观看| 国内揄拍国内精品少妇国语| 欧美一区二三区| 国产婷婷成人久久av免费高清| 国产自产女人91一区在线观看| 欧美成人激情图片网| 午夜精品一区二区三区在线视| 久热精品视频在线观看| 欧美激情精品久久久久久| 欧美成年人视频| 国产精品久久久久久久久久久新郎| 日本精品视频在线播放| 国产精品免费久久久久影院| 久久久精品一区二区三区| 国产精品女人久久久久久| 一本色道久久88亚洲综合88| 欧美激情视频网| www.久久久久久.com| 韩国国内大量揄拍精品视频| 国产亚洲精品成人av久久ww| 456亚洲影院| 91超碰caoporn97人人| 成人av资源在线播放| 乱亲女秽乱长久久久| 亚洲第一在线视频| 精品久久久久久电影| 亚洲精品在线91| 亚洲天堂av在线免费| 久久久亚洲福利精品午夜| 美女性感视频久久久| 欧美视频在线免费看| 日韩在线观看网站| 亚洲黄色免费三级| 亚洲美女av网站| 国产精品6699| 欧美老女人在线视频| 国产精品久久久久久久电影| 久久精品国产欧美激情| 亚洲男人天堂九九视频| 国产主播喷水一区二区| 亚洲成人a级网| 97精品伊人久久久大香线蕉| 欧美激情视频网址| 91久久久亚洲精品| 日韩欧美aⅴ综合网站发布| 亚洲国产精品99久久| 欧美日韩成人在线视频| 日韩中文综合网| 最新国产精品拍自在线播放| 日韩av在线电影网| 国产日韩一区在线| 欧美中文字幕视频在线观看| 亚洲成av人影院在线观看| 欧美亚洲在线视频| 中文字幕亚洲情99在线| 91精品免费看|