關注公眾號 資源自由分享 回復 shiro 領取視頻教程
什么是權限管理:
-
-
- 基本上涉及到用戶參與的系統都要進行權限管理,權限管理屬於系統安全的范疇,權限管理實現對用戶訪問系統的控制,按照安全規則或者安全策略控制用戶可以訪問而且只能訪問自己被授權的資源。
- 權限管理包括用戶身份認證和授權兩部分,簡稱認證授權。對於需要訪問控制的資源用戶首先經過身份認證,認證通過后用戶具有該資源的訪問權限訪問
-
用戶身份認證:
-
-
- 身份認證,就是判斷一個用戶是否為合法用戶的處理過程。最常用的簡單身份認證方式是系統通過核對用戶輸入的用戶名和口令,看其是否與系統中存儲的該用戶的用戶名和口令一致,來判斷用戶身份是否正確。對於采用指紋等系統,則出示指紋;對於硬件Key等刷卡系統,則需要刷卡
-
用戶名密碼身份認證流程:
關鍵對象:
上邊的流程圖中需要理解以下關鍵對象:
Subject:主體:訪問系統的用戶,主體可以是用戶、程序等,進行認證的都稱為主體;
Principal:身份信息:是主體(subject)進行身份認證的標識,標識必須具有唯一性,如用戶名、手機號、郵箱地址等,一個主體可以有多個身份,但是必須有一個主身份(Primary Principal)。
credential:憑證信息:是只有主體自己知道的安全信息,如密碼、證書等。
授權:
授權,即訪問控制,控制誰能訪問哪些資源。主體進行身份認證后需要分配權限方可訪問系統的資源,對於某些資源沒有權限是無法訪問的
授權流程:
關鍵對象:
授權可簡單理解為who對what(which)進行How操作
ho:即主體(Subject),主體需要訪問系統中的資源。
What:即資源(Resource),如系統菜單、頁面、按鈕、類方法、系統商品信息等。資源包括資源類型和資源實例,比如商品信息為資源類型,類型為t01的商品為資源實例,編號為001的商品信息也屬於資源實例。
How:權限/許可(Permission),規定了主體對資源的操作許可,權限離開資源沒有意義,如用戶查詢權限、用戶添加權限、某個類方法的調用權限、編號為001用戶的修改權限等,通過權限可知主體對哪些資源都有哪些操作許可。權限分為粗顆粒和細顆粒,粗顆粒權限是指對資源類型的權限,細顆粒權限是對資源實例的權限。
主體、資源、權限關系如下圖:
權限模型:
對上節中的主體、資源、權限通過數據模型表示:
主體(賬號、密碼)、資源(資源名稱、訪問地址)、權限(權限名稱、資源id)、角色(角色名稱)、角色和權限關系(角色id、權限id)、主體和角色關系(主體id、角色id)
如下圖:
權限分配:
對主體分配權限,主體只允許在權限范圍內對資源進行操作,比如:對u01用戶分配商品修改權限,u01用戶只能對商品進行修改。
通常需要持久化,根據上邊的數據模型創建表並將用戶的權限信息存儲在數據庫中
權限控制:
用戶擁有了權限即可操作權限范圍內的資源,系統不知道主體是否具有訪問權限需要對用戶的訪問進行控制
以上是對權限的基本講解。下面開始真正的學習shiro
shiro介紹
什么是shiro
Shiro是apache旗下一個開源框架,它將軟件系統的安全認證相關的功能抽取出來,實現用戶身份認證,權限授權、加密、會話管理等功能,組成了一個通用的安全認證框架。
為什么要學shiro
既然shiro將安全認證相關的功能抽取出來組成一個框架,使用shiro就可以非常快速的完成認證、授權等功能的開發,降低系統成本。
shiro使用廣泛,shiro可以運行在web應用,非web應用,集群分布式應用中越來越多的用戶開始使用shiro。
java領域中spring security(原名Acegi)也是一個開源的權限管理框架,但是spring security依賴spring運行,而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的jar包 :
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-web</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-ehcache</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-quartz</artifactId> <version>1.2.3</version> </dependency>
也可以通過引入shiro-all包括shiro所有的包:
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-all</artifactId> <version>1.2.3</version> </dependency>
shiro認證
認證流程:
入門程序:
1、創建普通的java 工程項目
2、導入jar 包
3、使用log4j.properties日志配置文件輸出日志
log4j.rootLogger=debug, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m %n
4、使用shiro.ini 文件 【通過Shiro.ini配置文件初始化SecurityManager環境】
配置 eclipse支持ini文件編輯:
在eclipse配置后,在classpath創建shiro.ini配置文件,為了方便測試將用戶名和密碼配置的shiro.ini配置文件中:
[users] zhang=123 lisi=123
認證代碼:
// 用戶登陸、用戶退出 @Test public void testLoginLogout() { // 構建SecurityManager工廠,IniSecurityManagerFactory可以從ini文件中初始化SecurityManager環境 Factory<SecurityManager> factory = new IniSecurityManagerFactory( "classpath:shiro.ini"); // 通過工廠創建SecurityManager SecurityManager securityManager = factory.getInstance(); // 將securityManager設置到運行環境中 SecurityUtils.setSecurityManager(securityManager); // 創建一個Subject實例,該實例認證要使用上邊創建的securityManager進行 Subject subject = SecurityUtils.getSubject(); // 創建token令牌,記錄用戶認證的身份和憑證即賬號和密碼 UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123"); try { // 用戶登陸 subject.login(token); } catch (AuthenticationException e) { // TODO Auto-generated catch block e.printStackTrace(); } // 用戶認證狀態 Boolean isAuthenticated = subject.isAuthenticated(); System.out.println("用戶認證狀態:" + isAuthenticated); // 用戶退出 subject.logout(); isAuthenticated = subject.isAuthenticated(); System.out.println("用戶認證狀態:" + isAuthenticated); }
認證執行流程 :
1、 創建token令牌,token中有用戶提交的認證信息即賬號和密碼
2、 執行subject.login(token),最終由securityManager通過Authenticator進行認證
3、 Authenticator的實現ModularRealmAuthenticator調用realm從ini配置文件取用戶真實的賬號和密碼,這里使用的是IniRealm(shiro自帶)
4、 IniRealm先根據token中的賬號去ini中找該賬號,如果找不到則給ModularRealmAuthenticator返回null,如果找到則匹配密碼,匹配密碼成功則認證通過。
以上程序使用的是Shiro自帶的IniRealm,IniRealm從ini配置文件中讀取用戶的信息,大部分情況下需要從系統的數據庫中讀取用戶信息,所以需要自定義realm
shiro提供的realm 如下圖:
最基礎的是Realm接口,CachingRealm負責緩存處理,AuthenticationRealm負責認證,AuthorizingRealm負責授權,通常自定義的realm繼承AuthorizingRealm
自定義Realm 代碼如下:
public class CustomRealm1 extends AuthorizingRealm { @Override public String getName() { return "customRealm1"; } //支持UsernamePasswordToken @Override public boolean supports(AuthenticationToken token) { return token instanceof UsernamePasswordToken; } //認證 @Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException { //從token中 獲取用戶身份信息 String username = (String) token.getPrincipal(); //拿username從數據庫中查詢 //.... //如果查詢不到則返回null if(!username.equals("zhang")){//這里模擬查詢不到 return null; } //獲取從數據庫查詢出來的用戶密碼 String password = "123";//這里使用靜態數據模擬。。 //返回認證信息由父類AuthenticatingRealm進行認證 SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo( username, password, getName()); return simpleAuthenticationInfo; } //授權 @Override protected AuthorizationInfo doGetAuthorizationInfo( PrincipalCollection principals) { // TODO Auto-generated method stub return null; } }
同時需要創建shiro-realm.ini 文件:
[main] #自定義 realm customRealm=cn.itcast.shiro.authentication.realm.CustomRealm1 #將realm設置到securityManager securityManager.realms=$customRealm
測試代碼同入門程序,將ini的地址修改為shiro-realm.ini
一般來說密碼需要 加密 可以選擇MD5加密方式這里就不詳細說明。
shiro授權
授權流程 圖:
授權方式 :
Shiro 支持三種方式的授權: 編程式:通過寫if/else 授權代碼塊完成: Subject subject = SecurityUtils.getSubject(); if(subject.hasRole(“admin”)) { //有權限 } else { //無權限 } 注解式:通過在執行的Java方法上放置相應的注解完成: @RequiresRoles("admin") public void hello() { //有權限 } JSP/GSP 標簽:在JSP/GSP 頁面通過相應的標簽完成: <shiro:hasRole name="admin"> <!— 有權限—> </shiro:hasRole>
授權測試 :
1、創建存放權限的配置文件shiro-permission.ini,如下:
[users] #用戶zhang的密碼是123,此用戶具有role1和role2兩個角色 zhang=123,role1,role2 wang=123,role2 [roles] #角色role1對資源user擁有create、update權限 role1=user:create,user:update #角色role2對資源user擁有create、delete權限 role2=user:create,user:delete #角色role3對資源user擁有create權限 role3=user:create
注意:在ini文件中用戶、角色、權限的配置規則是:“用戶名=密碼,角色1,角色2...” “角色=權限1,權限2...”,首先根據用戶名找角色,再根據角色找權限,角色是權限集合
權限字符串規則:
權限字符串的規則是:“資源標識符:操作:資源實例標識符”,意思是對哪個資源的哪個實例具有什么操作,“:”是資源/操作/實例的分割符,權限字符串也可以使用*通配符。 例子: 用戶創建權限:user:create,或user:create:* 用戶修改實例001的權限:user:update:001 用戶實例001的所有權限:user:*:001
測試代碼如下:
@Test public void testPermission() { // 從ini文件中創建SecurityManager工廠 Factory<SecurityManager> factory = new IniSecurityManagerFactory( "classpath:shiro-permission.ini"); // 創建SecurityManager SecurityManager securityManager = factory.getInstance(); // 將securityManager設置到運行環境 SecurityUtils.setSecurityManager(securityManager); // 創建主體對象 Subject subject = SecurityUtils.getSubject(); // 對主體對象進行認證 // 用戶登陸 // 設置用戶認證的身份(principals)和憑證(credentials) UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123"); try { subject.login(token); } catch (AuthenticationException e) { // TODO Auto-generated catch block e.printStackTrace(); } // 用戶認證狀態 Boolean isAuthenticated = subject.isAuthenticated(); System.out.println("用戶認證狀態:" + isAuthenticated); // 用戶授權檢測 基於角色授權 // 是否有某一個角色 System.out.println("用戶是否擁有一個角色:" + subject.hasRole("role1")); // 是否有多個角色 System.out.println("用戶是否擁有多個角色:" + subject.hasAllRoles(Arrays.asList("role1", "role2"))); // subject.checkRole("role1"); // subject.checkRoles(Arrays.asList("role1", "role2")); // 授權檢測,失敗則拋出異常 // subject.checkRole("role22"); // 基於資源授權 System.out.println("是否擁有某一個權限:" + subject.isPermitted("user:delete")); System.out.println("是否擁有多個權限:" + subject.isPermittedAll("user:create:1", "user:delete")); //檢查權限 subject.checkPermission("sys:user:delete"); subject.checkPermissions("user:create:1","user:delete"); }
注意:測試代碼同認證代碼,注意ini地址改為shiro-permission.ini,主要學習下邊授權的方法;在用戶認證通過后執行下邊的授權代碼
基於角色的授權:
// 用戶授權檢測 基於角色授權 // 是否有某一個角色 System.out.println("用戶是否擁有一個角色:" + subject.hasRole("role1")); // 是否有多個角色 System.out.println("用戶是否擁有多個角色:" + subject.hasAllRoles(Arrays.asList("role1", "role2")));
//對應的check方法:
subject.checkRole("role1");
subject.checkRoles(Arrays.asList("role1", "role2"));
上邊check方法如果授權失敗則拋出異常:
org.apache.shiro.authz.UnauthorizedException: Subject does not have role [.....]
基於資源授權:
// 基於資源授權 System.out.println("是否擁有某一個權限:" + subject.isPermitted("user:delete")); System.out.println("是否擁有多個權限:" + subject.isPermittedAll("user:create:1", "user:delete")); 對應的check方法: subject.checkPermission("sys:user:delete"); subject.checkPermissions("user:create:1","user:delete");
與上邊認證自定義realm一樣,大部分情況是要從數據庫獲取權限數據,這里直接實現基於資源的授權
授權自定義 realm 代碼 如下:
直接在認證寫的自定義realm類中完善doGetAuthorizationInfo方法,此方法需要完成:根據用戶身份信息從數據庫查詢權限字符串,由shiro進行授權:
// 授權 @Override protected AuthorizationInfo doGetAuthorizationInfo( PrincipalCollection principals) { // 獲取身份信息 String username = (String) principals.getPrimaryPrincipal(); // 根據身份信息從數據庫中查詢權限數據 //....這里使用靜態數據模擬 List<String> permissions = new ArrayList<String>(); permissions.add("user:create"); permissions.add("user.delete"); //將權限信息封閉為AuthorizationInfo SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); for(String permission:permissions){ simpleAuthorizationInfo.addStringPermission(permission); } return simpleAuthorizationInfo; }
授權執行流程:
1、 執行subject.isPermitted("user:create")
2、 securityManager通過ModularRealmAuthorizer進行授權
3、 ModularRealmAuthorizer調用realm獲取權限信息
4、 ModularRealmAuthorizer再通過permissionResolver解析權限字符串,校驗是否匹配
shiro與spring web項目的整合
1、web.xml添加shiro Filter
<!-- shiro過慮器,DelegatingFilterProx會從spring容器中找shiroFilter --> <filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <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>
2、applicationContext-shiro.xml
<!-- Shiro 的Web過濾器 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager" /> <!-- 如果沒有認證將要跳轉的登陸地址,http可訪問的url,如果不在表單認證過慮器FormAuthenticationFilter中指定此地址就為身份認證地址 --> <property name="loginUrl" value="/login.action" /> <!-- 沒有權限跳轉的地址 --> <property name="unauthorizedUrl" value="/refuse.jsp" /> <!-- shiro攔截器配置 --> <property name="filters"> <map> <entry key="authc" value-ref="formAuthenticationFilter" /> </map> </property> <property name="filterChainDefinitions"> <value> <!-- 必須通過身份認證方可訪問,身份認 證的url必須和過慮器中指定的loginUrl一致 --> /loginsubmit.action = authc <!-- 退出攔截,請求logout.action執行退出操作 --> /logout.action = logout <!-- 無權訪問頁面 --> /refuse.jsp = anon <!-- roles[XX]表示有XX角色才可訪問 --> /item/list.action = roles[item],authc /js/** anon /images/** anon /styles/** anon <!-- user表示身份認證通過或通過記住我認證通過的可以訪問 --> /** = user <!-- /**放在最下邊,如果一個url有多個過慮器則多個過慮器中間用逗號分隔,如:/** = user,roles[admin] --> </value> </property> </bean> <!-- 安全管理器 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="userRealm" /> </bean> <!-- 自定義 realm --> <bean id="userRealm" class="cn.itcast.ssm.realm.CustomRealm1"> </bean> <!-- 基於Form表單的身份驗證過濾器,不配置將也會注冊此過慮器,表單中的用戶賬號、密碼及loginurl將采用默認值,建議配置 --> <bean id="formAuthenticationFilter" class="org.apache.shiro.web.filter.authc.FormAuthenticationFilter"> <!-- 表單中賬號的input名稱 --> <property name="usernameParam" value="usercode" /> <!-- 表單中密碼的input名稱 --> <property name="passwordParam" value="password" /> <!-- <property name="rememberMeParam" value="rememberMe"/> --> <!-- loginurl:用戶登陸地址,此地址是可以http訪問的url地址 --> <property name="loginUrl" value="/loginsubmit.action" /> </bean>
注意:
securityManager:這個屬性是必須的。 loginUrl:沒有登錄認證的用戶請求將跳轉到此地址,不是必須的屬性,不輸入地址的話會自動尋找項目web項目的根目錄下的”/login.jsp”頁面。 unauthorizedUrl:沒有權限默認跳轉的頁面。
3、使用shiro注解授權:
在springmvc.xml中配置shiro注解支持,可在controller方法中使用shiro注解配置權限:
<!-- 開啟aop,對類代理 --> <aop:config proxy-target-class="true"></aop:config> <!-- 開啟shiro注解支持 --> <bean class=" org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager" /> </bean>
修改Controller代碼,在方法上添加授權注解,如下:
// 查詢商品列表 @RequestMapping("/queryItem") @RequiresPermissions("item:query") public ModelAndView queryItem() throws Exception {
。。。。。。。
}
上邊代碼@RequiresPermissions("item:query")表示必須擁有“item:query”權限方可執行
4、重新 自定義realm :
此realm先不從數據庫查詢權限數據,當前需要先將shiro整合完成,在上定義的realm基礎上修改:
public class CustomRealm1 extends AuthorizingRealm { @Autowired private SysService sysService; @Override public String getName() { return "customRealm"; } // 支持什么類型的token @Override public boolean supports(AuthenticationToken token) { return token instanceof UsernamePasswordToken; } // 認證 @Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException { // 從token中 獲取用戶身份信息 String username = (String) token.getPrincipal(); // 拿username從數據庫中查詢 // .... // 如果查詢不到則返回null if (!username.equals("zhang")) {// 這里模擬查詢不到 return null; } // 獲取從數據庫查詢出來的用戶密碼 String password = "123";// 這里使用靜態數據模擬。。 // 根據用戶id從數據庫取出菜單 //...先用靜態數據 List<SysPermission> menus = new ArrayList<SysPermission>();; SysPermission sysPermission_1 = new SysPermission(); sysPermission_1.setName("商品管理"); sysPermission_1.setUrl("/item/queryItem.action"); SysPermission sysPermission_2 = new SysPermission(); sysPermission_2.setName("用戶管理"); sysPermission_2.setUrl("/user/query.action"); menus.add(sysPermission_1); menus.add(sysPermission_2); // 構建用戶身體份信息 ActiveUser activeUser = new ActiveUser(); activeUser.setUserid(username); activeUser.setUsername(username); activeUser.setUsercode(username); activeUser.setMenus(menus); // 返回認證信息由父類AuthenticatingRealm進行認證 SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo( activeUser, password, getName()); return simpleAuthenticationInfo; } // 授權 @Override protected AuthorizationInfo doGetAuthorizationInfo( PrincipalCollection principals) { // 獲取身份信息 ActiveUser activeUser = (ActiveUser) principals.getPrimaryPrincipal(); //用戶id String userid = activeUser.getUserid(); // 根據用戶id從數據庫中查詢權限數據 // ....這里使用靜態數據模擬 List<String> permissions = new ArrayList<String>(); permissions.add("item:query"); permissions.add("item:update"); // 將權限信息封閉為AuthorizationInfo SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); for (String permission : permissions) { simpleAuthorizationInfo.addStringPermission(permission); } return simpleAuthorizationInfo; } }
5、登錄controller :
//用戶登陸頁面 @RequestMapping("/login") public String login()throws Exception{ return "login"; } // 用戶登陸提交 @RequestMapping("/loginsubmit") public String loginsubmit(Model model, HttpServletRequest request) throws Exception { // shiro在認證過程中出現錯誤后將異常類路徑通過request返回 String exceptionClassName = (String) request .getAttribute("shiroLoginFailure"); if (UnknownAccountException.class.getName().equals(exceptionClassName)) { throw new CustomException("賬號不存在"); } else if (IncorrectCredentialsException.class.getName().equals( exceptionClassName)) { throw new CustomException("用戶名/密碼錯誤"); } else{ throw new Exception();//最終在異常處理器生成未知錯誤 } }
6、退出
由於使用shiro的sessionManager,不用開發退出功能,使用shiro的logout攔截器即可
<!-- 退出攔截,請求logout.action執行退出操作 --> /logout.action = logout
注意:如需添加MD5校驗需要修改applicationContext-shiro.xml:
<!-- 憑證匹配器 --> <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"> <property name="hashAlgorithmName" value="md5" /> <property name="hashIterations" value="1" /> </bean> <!-- 自定義 realm --> <bean id="userRealm" class="cn.itcast.ssm.realm.CustomRealm1"> <property name="credentialsMatcher" ref="credentialsMatcher" /> </bean>
shiro緩存 配置:
在applicationContext-shiro.xml中配置緩存管理器:
<!-- 安全管理器 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="userRealm" /> <property name="sessionManager" ref="sessionManager" /> <property name="cacheManager" ref="cacheManager"/> </bean> <!-- 緩存管理器 --> <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"> </bean>
session管理 :
在applicationContext-shiro.xml中配置sessionManager
<!-- 安全管理器 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="userRealm" /> <property name="sessionManager" ref="sessionManager" /> </bean> <!-- 會話管理器 --> <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"> <!-- session的失效時長,單位毫秒 --> <property name="globalSessionTimeout" value="600000"/> <!-- 刪除失效的session --> <property name="deleteInvalidSessions" value="true"/> </bean>
配置記住我【下次免登陸】
1、用戶身份實現java.io.Serializable接口【即用戶實體類】
2、修改applicationContext-shiro.xml中對FormAuthenticationFilter的配置:
<bean id="formAuthenticationFilter" class="org.apache.shiro.web.filter.authc.FormAuthenticationFilter"> 改為 如下:
<bean id="formAuthenticationFilter"
class="cn.itcast.ssm.shiro.MyFormAuthenticationFilter">
<!-- 表單中賬號的input名稱 -->
<property name="usernameParam" value="usercode" />
<!-- 表單中密碼的input名稱 -->
<property name="passwordParam" value="password" />
<property name="rememberMeParam" value="rememberMe"/>
<!-- loginurl:用戶登陸地址,此地址是可以http訪問的url地址 -->
<property name="loginUrl" value="/loginsubmit.action" />
</bean>
3、修改applicationContext-shiro.xml
<!-- 安全管理器 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="userRealm" /> <property name="sessionManager" ref="sessionManager" /> <property name="cacheManager" ref="cacheManager"/> <!-- 記住我 --> <property name="rememberMeManager" ref="rememberMeManager"/> </bean> <!-- rememberMeManager管理器 --> <bean id="rememberMeManager" class="org.apache.shiro.web.mgt.CookieRememberMeManager"> <property name="cookie" ref="rememberMeCookie" /> </bean> <!-- 記住我cookie --> <bean id="rememberMeCookie" class="org.apache.shiro.web.servlet.SimpleCookie"> <constructor-arg value="rememberMe" /> <!-- 記住我cookie生效時間30天 --> <property name="maxAge" value="2592000" /> </bean>
登錄頁面 添加如下:
<input type="checkbox" name="rememberMe" />自動登陸
附 :
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表示需要認證(登錄)才能使用,沒有參數 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是授權過濾器 shiro的jsp標簽 Jsp頁面添加: <%@ tagliburi="http://shiro.apache.org/tags" prefix="shiro" %> 標簽名稱 標簽條件(均是顯示標簽內容) <shiro:authenticated> 登錄之后 <shiro:notAuthenticated> 不在登錄狀態時 <shiro:guest> 用戶在沒有RememberMe時 <shiro:user> 用戶在RememberMe時 <shiro:hasAnyRoles name="abc,123" > 在有abc或者123角色時 <shiro:hasRole name="abc"> 擁有角色abc <shiro:lacksRole name="abc"> 沒有角色abc <shiro:hasPermission name="abc"> 擁有權限資源abc <shiro:lacksPermission name="abc"> 沒有abc權限資源 <shiro:principal> 顯示用戶身份名稱 <shiro:principal property="username"/> 顯示用戶身份中的屬性值