(轉) shiro權限框架詳解06-shiro與web項目整合(上)


http://blog.csdn.net/facekbook/article/details/54947730

shiro和web項目整合,實現類似真實項目的應用

本文中使用的項目架構是springMVC+mybatis,所以我們是基於搭建好的項目進行改造的。

  • 將shiro整合到web應用中
  • 登錄
  • 退出
  • 認證信息在頁面展現,也就是顯示菜單
  • shiro的過濾器

將shiro整合到web應用中

數據庫腳步

sql腳步放到項目中,項目上傳到共享的資源中,文章最后給出共享url。

去除項目中不使用shiro實現認證的攔截器

    <!--攔截器 --> <!-- <mvc:interceptors> <mvc:interceptor> --> <!-- 用戶認證攔截 --> <!-- <mvc:mapping path="/**" /> <bean class="cn.itcast.ssm.controller.interceptor.LoginInterceptor"></bean> </mvc:interceptor> <mvc:interceptor> --> <!-- 授權攔截 --> <!-- <mvc:mapping path="/**" /> <bean class="cn.itcast.ssm.controller.interceptor.PermissionInterceptor"></bean> </mvc:interceptor> </mvc:interceptors> --> 

 

添加shiro的jar包

除了前面文章提到的shiro-core相關的jar包,還需要如下:

  • 與web整合的 shiro-web-1.2.3.jar
  • 與spring整合的 shiro-spring-1.2.3.jar
  • 與ehcache整合的 shiro-ehcache-1.2.3.jar

在web.xml中配置shiro的filter

在web系統中,shiro 也是通過filter進行攔截的。filter攔截后將操作交給filterChain(過濾器煉)。shiro中提供了多個filter,在欄目 shiro的過濾器 會全部介紹 
在web中配置filter,如下:

    <!--shirofilter--> <!-- shiro過濾器,DelegatingFilterProxy通過代理模式將spring容器的bean和filter關聯起來 --> <filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <!--設置true由servlet容器控制filter的生命周期--> <init-param> <param-name>targetFilterLifecycle</param-name> <param-value>true</param-value> </init-param> <!--設置spring容器filter的bean id,如果不設置則找與filter-name一致的bean --> <init-param> <param-name>targetBeanName</param-name> <param-value>shiroFilter</param-value> </init-param> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>

 

新建applicationContext-shiro.xml文件

內容下圖:

    <!-- web.xml中shiro的filter對應的bean --> <!-- shiro的web過濾器 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager" /> <!-- logiUrl認證提交地址,如果沒有認證通過將會請求此地址進行認證,請求此地址將由formAuthenticationFilter進行表單認證 --> <property name="loginUrl" value="/login.action" /> <!-- 認證成功后統一跳轉到first.action,建議不配置,shiro認證成功自動到上一個鏈接 --> <property name="successUrl" value="/first.action" /> <!-- 通過unauthorizedUrl指定沒有權限時跳轉頁面 --> <property name="unauthorizedUrl" value="/refuse.jsp" /> <!-- 過濾器鏈定義,從上向下順序執行,一般將/**放在最后面 --> <property name="filterChainDefinitions"> <value> <!--靜態資源可以匿名訪問 --> /images/** = anon /js/** = anon /styles/** = anon <!--登錄驗證碼匿名訪問--> /validatecode.jsp = anon <!--任何鏈接都可以不認證訪問--> /** = anon </value> </property> </bean> <!--securityManager安全管理器 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="customRealm" /> </bean> <!-- 自定義的realm --> <bean id="customRealm" class="cn.itcast.ssm.shiro.CustomRealm"/>
  • 1

上面配置的CustomRealm 的內容和文章shiro權限框架詳解05-shiro授權的CustomRealm一樣。

測試是否整合成功

在界面輸入CustomRealm 代碼中的賬號為 zhangsan 密碼為 123 可以進入歡迎頁面。 

但是並沒有菜單和相關用戶信息

登錄功能

原理

由於登錄使用的是 org.apache.shiro.web.filter.authc.FormAuthenticationFilter filter實現的,具體流程如下: 
如果用戶沒有認證時,請求上面配置的loginUrl進行認證,用戶的身份信息和密碼提交到loginUrl,FormAuthenticationFilter攔截取出request中的username和password(參數的key是可以進行配置的,下一篇blog介紹)參數值。FormAuthenticationFilter調用realm傳入一個token(包含username和password),realm根據username查詢用戶信息,如果查詢不到,返回null,FormAuthenticationFilter向request域中填充一個參數,key為shiroLoginFailure 記錄異常信息。如果不為空的話,返回AuthenticationInfo 類。

修改登錄頁面

由於FormAuthenticationFilter的身份信息和密碼的請求參數的key默認是(username和password),修改login.jsp頁面的賬號和密碼輸入框name屬性值,並注釋掉驗證碼的代碼。

修改controller類

修改LoginController 的 login 方法如下:

    @RequestMapping("/login") public String login(HttpServletRequest request)throws Exception{ //如果登錄失敗從request中獲取認證異常信息,shiroLoginFailure就是shiro異常類的全限定名 String exceptionClassName = (String) request.getAttribute("shiroLoginFailure"); if(exceptionClassName!=null){ if(UnknownAccountException.class.getName().equals(exceptionClassName)){ throw new CustomException("賬號不存在"); }else if(IncorrectCredentialsException.class.getName().equals(exceptionClassName)){ throw new CustomException("用戶名或密碼錯誤"); }else { throw new Exception();//最終在異常處理器生成未知錯誤 } } //此方法不處理登錄成功(認證成功),shiro認證成功會自動跳轉到上一個請求路徑。 //登錄失敗還到login頁面 return "login"; }

 

這個方法只有校驗不通過的時候才會執行。真正的校驗方法是在自定義的realm中,校驗身份是否正確。

修改認證攔截器

將所有請求都改為需要認證才能訪問的。

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager" /> <!-- logiUrl認證提交地址,如果沒有認證通過將會請求此地址進行認證,請求此地址將由formAuthenticationFilter進行表單認證 --> <property name="loginUrl" value="/login.action" /> <!-- 認證成功后統一跳轉到first.action,建議不配置,shiro認證成功自動到上一個鏈接 --> <property name="successUrl" value="/first.action" /> <!-- 通過unauthorizedUrl指定沒有權限時跳轉頁面 --> <property name="unauthorizedUrl" value="/refuse.jsp" /> <!-- 自定義filter配置 --> <property name="filters"> <map> <entry key="authc" value-ref="formAuthenticationFilter"/> </map> </property> <!-- 過濾器鏈定義,從上向下順序執行,一般將/**放在最后面 --> <property name="filterChainDefinitions"> <value> <!--靜態資源可以匿名訪問 --> /images/** = anon /js/** = anon /styles/** = anon /validatecode.jsp = anon <!-- /**=authc 表示所有的url都需要認證才能訪問 --> /** = authc </value> </property> </bean>

 

驗證登錄功能

在登錄界面輸入賬號為 zhangsan 密碼為 123 驗證是否登錄成功,然后輸入錯誤的賬號,控制台出現下面的異常信息: 
 
如果輸入密碼錯誤: 
 
異常信息和前面Java項目演示的一樣。

退出

退出不需要我們自己實現,只要去訪問一個退出的url(該url是可以不存在的)即可,由LogoutFilter filter處理,清除session。在applicationContext.xml配置logoutFilter

    <!-- web.xml中shiro的filter對應的bean --> <!-- shiro的web過濾器 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager" /> <!-- logiUrl認證提交地址,如果沒有認證通過將會請求此地址進行認證,請求此地址將由formAuthenticationFilter進行表單認證 --> <property name="loginUrl" value="/login.action" /> <!-- 認證成功后統一跳轉到first.action,建議不配置,shiro認證成功自動到上一個鏈接 --> <property name="successUrl" value="/first.action" /> <!-- 通過unauthorizedUrl指定沒有權限時跳轉頁面 --> <property name="unauthorizedUrl" value="/refuse.jsp" /> <!-- 自定義filter配置 --> <property name="filters"> <map> <entry key="authc" value-ref="formAuthenticationFilter"/> </map> </property> <!-- 過濾器鏈定義,從上向下順序執行,一般將/**放在最后面 --> <property name="filterChainDefinitions"> <value> <!--靜態資源可以匿名訪問 --> /images/** = anon /js/** = anon /styles/** = anon /validatecode.jsp = anon <!-- 請求logout.action地址,shiro去清除session --> /logout.action = logout <!-- /**=authc 表示所有的url都需要認證才能訪問 --> /** = authc </value> </property> </bean>

 

刪除原來的退出方法。

菜單顯示

修改realm從數據庫查詢用戶信息及用戶擁有的菜單設置在AuthenticatorInfo中。具體代碼如下:

    /** * 用於認證 */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { //第一步:通過token獲取身份信息 String userCode = (String) token.getPrincipal(); if (!"zhangsan".equals(userCode)) {// 這里模仿查詢不到 return null; } String password = "123"; //模擬數據activeUser就是用戶身份信息 ActiveUser activeUser = new ActiveUser(); activeUser.setUserid("zhangsan"); activeUser.setUsercode("zhangsan"); activeUser.setUsername("張三"); //查詢菜單信息 List<SysPermission> menus = null; try { menus = sysService.findMenuListByUserId(activeUser .getUsercode()); } catch (Exception e) { e.printStackTrace(); } activeUser.setMenus(menus); //如果查詢到結果返回AuthenticationInfo AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(activeUser, password, ""); return authenticationInfo; }
  • 1

上面的代碼通過模擬從數據庫獲取數據設置到ActiveUser中。

修改FirstAction中的first方法

修改代碼將獲取身份信息,並放入request域中用於頁面顯示。

    //系統首頁 @RequestMapping("/first") public String first(Model model)throws Exception{ Subject subject =SecurityUtils.getSubject(); ActiveUser activeUser = (ActiveUser)subject.getPrincipal(); model.addAttribute("activeUser", activeUser); return "/first"; }

 

測試

在登錄界面,賬號輸入 zhangsan , 密碼輸入 123 
如果成功的話,將會看到如下頁面。 

shiro過濾器總結

過濾器簡稱 對應的Java類
anon org.apache.shiro.web.filter.authc.AnonymousFilter
authc org.apache.shiro.web.filter.authc.FormAuthenticationFilter
authcBasic org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
perms org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
port org.apache.shiro.web.filter.authz.PortFilter
rest org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter
roles org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
ssl org.apache.shiro.web.filter.authz.SslFilter
user org.apache.shiro.web.filter.authc.UserFilter
logout org.apache.shiro.web.filter.authc.LogoutFilter

各個過濾器的介紹和作用:


anon:例子/admins/**=anon 沒有參數,表示可以匿名使用。


authc:例如/admins/user/**=authc表示需要認證(登錄)才能使用,FormAuthenticationFilter是表單認證,沒有參數 。


roles:例子 /admins/user/** =roles[admin],參數可以寫多個,多個時必須加上引號,並且參數之間用逗號分割,當有多個參數時,例如admins/user/** =roles["admin,guest"],每個參數通過才算通過,相當於hasAllRoles()方法。


perms:例子/admins/user/**=perms[user:add:*],參數可以寫多個,多個時必須加上引號,並且參數之間用逗號分割,例如/admins/user/**=perms["user:add:*,user:modify:*"],當有多個參數時必須每個參數都通過才通過,想當於isPermitedAll()方法。


rest:例子/admins/user/**=rest[user],根據請求的方法,相當於/admins/user/**=perms[user:method],其中method為post,get,delete等。


port:例子/admins/user/**=port[8081],當請求的url的端口不是8081是跳轉到schemal://serverName:8081?queryString,其中schmal是協議http或https等,serverName是你訪問的host,8081是url配置里port的端口,queryString 
是你訪問的url里的?后面的參數。


authcBasic:例如/admins/user/**=authcBasic沒有參數表示httpBasic認證


ssl:例子/admins/user/**=ssl沒有參數,表示安全的url請求,協議為https


user:例如/admins/user/**=user沒有參數表示必須存在用戶, 身份認證通過或通過記住我認證通過的可以訪問,當登入操作時不做檢查


注: 
anon,authcBasic,auchc,user是認證過濾器, 
perms,roles,ssl,rest,port是授權過濾器

blog的項目地址

點擊進入下載頁面


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM