shiro(java安全框架)
來源:http://www.cnblogs.com/zhouguanglin/p/8477807.html
以下都是綜合之前的人加上自己的一些小總結
Apache Shiro是一個強大且易用的Java安全框架,執行身份驗證、授權、密碼學和會話管理。使用Shiro的易於理解的API,您可以快速、輕鬆地獲得任何應用程序,從最小的移動應用程序到最大的網絡和企業應用程序。
Shiro 主要分爲來個部分就是認證和授權,在個人感覺來看就是查詢數據庫做相應的判斷而已,Shiro只是一個框架而已,其中的內容需要自己的去構建,前後是自己的,中間是Shiro幫我們去搭建和配置好的
個人認爲需要看一下其中的一些源碼,更有幫助的深入的去了解Shiro的原理。
Shiro的主要框架圖:
方法類的走向:
對一些其中的方法的簡單說明:
Subject
Subject即主體,外部應用與subject進行交互,subject記錄了當前操作用戶,將用戶的概念理解爲當前操作的主體,可能是一個通過瀏覽器請求的用戶,也可能是一個運行的程序。 Subject在shiro中是一個接口,接口中定義了很多認證授相關的方法,外部程序通過subject進行認證授,而subject是通過SecurityManager安全管理器進行認證授權
SecurityManager
SecurityManager即安全管理器,對全部的subject進行安全管理,它是shiro的核心,負責對所有的subject進行安全管理。通過SecurityManager可以完成subject的認證、授權等,實質上SecurityManager是通過Authenticator進行認證,通過Authorizer進行授權,通過SessionManager進行會話管理等。
SecurityManager是一個接口,繼承了Authenticator, Authorizer, SessionManager這三個接口。
Authenticator
Authenticator即認證器,對用戶身份進行認證,Authenticator是一個接口,shiro提供ModularRealmAuthenticator實現類,通過ModularRealmAuthenticator基本上可以滿足大多數需求,也可以自定義認證器。
Authorizer
Authorizer即授權器,用戶通過認證器認證通過,在訪問功能時需要通過授權器判斷用戶是否有此功能的操作權限。
realm
Realm即領域,相當於datasource數據源,securityManager進行安全認證需要通過Realm獲取用戶權限數據,比如:如果用戶身份數據在數據庫那麼realm就需要從數據庫獲取用戶身份信息。
注意:不要把realm理解成只是從數據源取數據,在realm中還有認證授權校驗的相關的代碼。
sessionManager
sessionManager即會話管理,shiro框架定義了一套會話管理,它不依賴web容器的session,所以shiro可以使用在非web應用上,也可以將分佈式應用的會話集中在一點管理,此特性可使它實現單點登錄。
SessionDAO
SessionDAO即會話dao,是對session會話操作的一套接口,比如要將session存儲到數據庫,可以通過jdbc將會話存儲到數據庫。
CacheManager
CacheManager即緩存管理,將用戶權限數據存儲在緩存,這樣可以提高性能。
Cryptography
Cryptography即密碼管理,shiro提供了一套加密/解密的組件,方便開發。比如提供常用的散列、加/解密等功能。
shiro認證與授權的在Web中實現
第一步:添加jar包
<!-- shiro --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.4.0</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.0</version> </dependency>
第二步:配置web.xml
<!-- shiro 過濾器 start --> <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> </filter> <filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- shiro 過濾器 end -->
第三步:自定義Realm 繼承AuthorizingRealm 重寫 AuthorizationInfo(授權) 和 AuthenticationInfo(認證)
以下只是簡單的測試
以下都是根據個人的設置和需求改變的。現在數據是死的,運用的時候需要從數據庫中得到
/** * @author zhouguanglin * @date 2018/2/26 14:05 */ public class CustomRealm extends AuthorizingRealm { /** * 授權 * @param principalCollection * @return */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { String userName = (String) principalCollection.getPrimaryPrincipal(); List<String> permissionList=new ArrayList<String>(); permissionList.add("user:add"); permissionList.add("user:delete"); if (userName.equals("zhou")) { permissionList.add("user:query"); } SimpleAuthorizationInfo info=new SimpleAuthorizationInfo(); info.addStringPermissions(permissionList); info.addRole("admin"); return info; } /** * 認證 * @param authenticationToken * @return * @throws AuthenticationException */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { String userName = (String) authenticationToken.getPrincipal(); if ("".equals(userName)) { return null; } SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(userName,"123456",this.getName()); return info; } }
第四步:配置spring-shiro.xml
這裏面都是按照自己的需求去配置的
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--開啓shiro的註解--> <bean id="advisorAutoProxyCreator" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"> <property name="proxyTargetClass" value="true"></property> </bean> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"/> <!--注入自定義的Realm--> <bean id="customRealm" class="com.test.realm.CustomRealm"></bean> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="customRealm"></property> </bean> <!--配置ShiroFilter--> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager"></property> <!--登入頁面--> <property name="loginUrl" value="/login.jsp"></property> <!--登入成功頁面--> <property name="successUrl" value="/index.jsp"/> <property name="filters"> <map> <!--退出過濾器--> <entry key="logout" value-ref="logoutFilter" /> </map> </property> <!--URL的攔截--> <property name="filterChainDefinitions" > <value> /share = authc /logout = logout </value> </property> </bean> <!--自定義退出LogoutFilter--> <bean id="logoutFilter" class="com.test.filter.SystemLogoutFilter"> <property name="redirectUrl" value="/login"/> </bean> </beans>
一些屬性的意義:
securityManager: 這個屬性是必須的。
loginUrl: 沒有登錄的用戶請求需要登錄的頁面時自動跳轉到登錄頁面,不是必須的屬性,不輸入地址的話會自動尋找項目web項目的根目錄下的”/login.jsp”頁面。
successUrl: 登錄成功默認跳轉頁面,不配置則跳轉至”/”。如果登陸前點擊的一個需要登錄的頁面,則在登錄自動跳轉到那個需要登錄的頁面。不跳轉到此。
unauthorizedUrl: 沒有權限默認跳轉的頁面。
Shiro中默認的過濾器:
過濾器名稱 | 過濾器類 | 描述 |
anon | org.apache.shiro.web.filter.authc.AnonymousFilter | 匿名過濾器 |
authc | org.apache.shiro.web.filter.authc.FormAuthenticationFilter | 如果繼續操作,需要做對應的表單驗證否則不能通過 |
authcBasic | org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter | 基本http驗證過濾,如果不通過,跳轉屋登錄頁面 |
logout | org.apache.shiro.web.filter.authc.LogoutFilter | 登錄退出過濾器 |
noSessionCreation | org.apache.shiro.web.filter.session.NoSessionCreationFilter | 沒有session創建過濾器 |
perms | org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter | 權限過濾器 |
port | org.apache.shiro.web.filter.authz.PortFilter | 端口過濾器,可以設置是否是指定端口如果不是跳轉到登錄頁面 |
rest | org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter | http方法過濾器,可以指定如post不能進行訪問等 |
roles | org.apache.shiro.web.filter.authz.RolesAuthorizationFilter | 角色過濾器,判斷當前用戶是否指定角色 |
ssl | org.apache.shiro.web.filter.authz.SslFilter | 請求需要通過ssl,如果不是跳轉回登錄頁 |
user | org.apache.shiro.web.filter.authc.UserFilter | 如果訪問一個已知用戶,比如記住我功能,走這個過濾器 |
在spring中直接引入<import resource="spring-shiro.xml"></import>
第五步:在spring-mvc.xml中配置權限的控制 異常的跳轉
<!-- 未認證或未授權時跳轉必須在springmvc裏面配,spring-shiro裏的shirofilter配不生效 --> <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <!--表示捕獲的異常 --> <prop key="org.apache.shiro.authz.UnauthorizedException"> <!--捕獲該異常時跳轉的路徑 --> /403 </prop> <!--表示捕獲的異常 --> <prop key="org.apache.shiro.authz.UnauthenticatedException"> <!--捕獲該異常時跳轉的路徑 --> /403 </prop> </props> </property> </bean>
403是錯誤頁面
第六步:在controller中測試使用的驗證登入
@RequestMapping(value = "/login", method = RequestMethod.POST) public String login(String userName, String passwd, Model model) { Subject subject = SecurityUtils.getSubject(); UsernamePasswordToken token = new UsernamePasswordToken(userName, passwd); try { subject.login(token); } catch (UnknownAccountException e) { e.printStackTrace(); model.addAttribute("userName", "用戶名錯誤!"); return "login"; } catch (IncorrectCredentialsException e) { e.printStackTrace(); model.addAttribute("passwd", "密碼錯誤"); return "login"; } return "index"; }
之後的都是HTML頁面的跳轉
有關HTML中的一些shiro設置:
在使用Shiro標籤庫前,首先需要在JSP引入shiro標籤:
<%@ taglib prefix=
"shiro"
uri=
"http://shiro.apache.org/tags"
%>
1、介紹Shiro的標籤guest標籤 :驗證當前用戶是否爲“訪客”,即未認證(包含未記住)的用戶。
1 2 3 4 5 | <shiro:guest> Hi there! Please <a href= "login.jsp" >Login</a> or <a href= "signup.jsp" >Signup</a> today! </shiro:guest> |
2、user標籤 :認證通過或已記住的用戶。
1 2 3 4 5 | <shiro:user> Welcome back John! Not John? Click <a href= "login.jsp" >here<a> to login. </shiro:user> |
3、authenticated標籤 :已認證通過的用戶。不包含已記住的用戶,這是與user標籤的區別所在。
1 2 3 4 5 | <shiro:authenticated> <a href= "updateAccount.jsp" >Update your contact information</a>. </shiro:authenticated> |
4、notAuthenticated標籤 :未認證通過用戶,與authenticated標籤相對應。與guest標籤的區別是,該標籤包含已記住用戶。
1 2 3 4 5 | <shiro:notAuthenticated> Please <a href= "login.jsp" >login</a> in order to update your credit card information. </shiro:notAuthenticated> |
5、principal 標籤 :輸出當前用戶信息,通常爲登錄帳號信息。
1 | Hello, <shiro:principal/>, how are you today? |
6、hasRole標籤 :驗證當前用戶是否屬於該角色。
1 2 3 4 5 | <shiro:hasRole name= "administrator" > <a href= "admin.jsp" >Administer the system</a> </shiro:hasRole> |
7、lacksRole標籤 :與hasRole標籤邏輯相反,當用戶不屬於該角色時驗證通過。
1 2 3 4 5 | <shiro:lacksRole name= "administrator" > Sorry, you are not allowed to administer the system. </shiro:lacksRole> |
8、hasAnyRole標籤 :驗證當前用戶是否屬於以下任意一個角色。
1 2 3 4 5 | <shiro:hasAnyRoles name= "developer, project manager, administrator" > You are either a developer, project manager, or administrator. </shiro:lacksRole> |
9、hasPermission標籤 :驗證當前用戶是否擁有指定權限。
1 2 3 4 5 | <shiro:hasPermission name= "user:create" > <a href= "createUser.jsp" >Create a new User</a> </shiro:hasPermission> |
10、lacksPermission標籤 :與hasPermission標籤邏輯相反,當前用戶沒有制定權限時,驗證通過。
1 2 3 4 5 | <shiro:hasPermission name= "user:create" > <a href= "createUser.jsp" >Create a new User</a> </shiro:hasPermission> |