Shiro
1.權限管理的概念
基本上涉及到用戶參與的系統都要進行權限管理,權限管理屬於系統安全的範疇,權限管理實現對用戶訪問系統的控制,按照安全規則或者安全策略控制用戶可以訪問而且只能訪問自己被授權的資源。
權限管理包括用戶身份認證和授權兩部分,簡稱認證授權。對於需要訪問控制的資源用戶首先經過身份認證,認證通過後用戶具有該資源的訪問權限方可訪問。
2.認證
1.認證的概念
- 認證:用戶訪問系統的控制
2.認證中抽象出的對象
- subject :主體相當於之前的user,訪問系統的用戶,主體可以是用戶、程序等,進行認證的都稱爲主體;
- Principal:身份信息,是主體(subject)進行身份認證的標識,標識必須具有唯一性,如用戶名、手機號、郵箱地址等,一個主體可以有多個身份,但是必須有一個主身份(Primary Principal)。
- credential:憑證信息,是隻有主體自己知道的安全信息,如密碼、證書等.
3.授權
1.授權的概念
- 授權,即訪問控制,控制誰能訪問哪些資源。主體進行身份認證後需要分配權限方可訪問系統的資源,對於某些資源沒有權限是無法訪問的。
2.授權中抽象對象
- Who,即主體(Subject),主體需要訪問系統中的資源。
- What,即資源(Resource),如系統菜單、頁面、按鈕、類方法、系統商品信息等。資源包括資源類型和資源實例,比如商品信息爲資源類型,類型爲t01的商品爲資源實例,編號爲001的商品信息也屬於資源實例。
- How,權限/許可(Permission),規定了主體對資源的操作許可,權限離開資源沒有意義,如用戶查詢權限、用戶添加權限、某個類方法的調用權限、編號爲001用戶的修改權限等,通過權限可知主體對哪些資源都有哪些操作許可。權限分爲粗顆粒和細顆粒,粗顆粒權限是指對資源類型的權限,細顆粒權限是對資源實例的權限。
4.權限模型
5.權限控制的方案
1.基於角色的權限控制
RBAC基於角色的訪問控制(Role-Based Access Control)是以角色爲中心進行訪問控制,比如:主體的角色爲總經理可以查詢企業運營報表,查詢員工工資信息等,訪問控制流程如下:
if(主體.hasRole(“總經理角色id”)){
查詢工資
}
2.基於資源的權限控制
RBAC基於資源的訪問控制(Resource-Based Access Control)是以資源爲中心進行訪問控制,比如:主體必須具有查詢工資權限纔可以查詢員工工資信息等,訪問控制流程如下:
if(主體.hasRole(“查詢工資的權限”)){
查詢工資
}
6.什麼是shiro
Shiro是apache旗下一個開源框架,它將軟件系統的安全認證相關的功能抽取出來,實現用戶身份認證,權限授權、加密、會話管理等功能,組成了一個通用的安全認證框架.
7.爲什麼要學shiro
既然shiro將安全認證相關的功能抽取出來組成一個框架,使用shiro就可以非常快速的完成認證、授權等功能的開發,降低系統成本。shiro使用廣泛,shiro可以運行在web應用,非web應用,集羣分佈式應用中越來越多的用戶開始使用shiro。java領域中spring security(原名Acegi)也是一個開源的權限管理框架,但是spring security依賴spring運行,而shiro就相對獨立,最主要是因爲shiro使用簡單、靈活,所以現在越來越多的用戶選擇shiro。
8.shiro的核心架構圖
9.shiro的第一個程序
1.創建一個maven或者springboot項目
2.導入jar
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.3.2</version>
</dependency>
2.第一個認證的程序
package com.baizhi.test;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
public class TestShiro {
public static void main(String[] args) {
//獲取安全管理器工廠
IniSecurityManagerFactory iniSecurityManagerFactory = new IniSecurityManagerFactory("classpath:shiro.ini");
//通過工廠 獲取安全管理器
SecurityManager securityManager = iniSecurityManagerFactory.getInstance();
//將安全管理器 給 安全工具類
SecurityUtils.setSecurityManager(securityManager);
//獲取主體對象
Subject subject = SecurityUtils.getSubject();
//token 就是用戶的令牌 包含用戶的身份信息和憑證信息
AuthenticationToken token =new UsernamePasswordToken("zhangcn","111111");
try {
//認證
subject.login(token);
} catch (AuthenticationException e) {
e.printStackTrace();
// AuthenticationToken 未找到賬戶異常
// IncorrectCredentialsException 證書不正確異常
}
//當前用戶是否通過驗證
boolean authenticated = subject.isAuthenticated();
System.out.println(authenticated);
}
}
3.配置文件
shiro.ini
[users]
zhangcn=111111
lisi=123456
注意:shiro中主體是否認證成功是通過拋異常的形式體現的,一般會拋出兩個異常
- UnknownAccountException 未找到賬戶異常 賬號異常
- IncorrectCredentialsException 證書不正確異常 密碼異常
10.shiro認證連接數據庫
1.源碼追蹤中出現的關鍵對象
AuthenticatingRealm //抽象類
//3.關鍵屬性 該屬性爲憑證匹配器
CredentialsMatcher credentialsMatcher;
//1.該方法爲抽象方法 其作用使用來獲取數據
protected abstract AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken var1) throws AuthenticationException;
SimpleAccountRealm
//2.實現了AuthenticatingRealm抽象方法,用來獲取配置文件中的用戶信息,該類不做數據比對
SimpleCredentialsMatcher
//4.shiro中默認的憑證匹配器
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
Object tokenCredentials = this.getCredentials(token);
Object accountCredentials = this.getCredentials(info);
return this.equals(tokenCredentials, accountCredentials);
}
2.連接數據庫
1.開發自定義realm
package com.baizhi.test;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.AuthenticatingRealm;
public class MyRealm extends AuthenticatingRealm {
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//根據token 獲取身份信息
String username = (String) authenticationToken.getPrincipal();
//調用根據用戶名查詢用戶的方法 數據庫操作
//User user=userDao.queryByName(username);
AuthenticationInfo authenticationInfo=null;
if(username.equals("zhangcn")){
authenticationInfo = new SimpleAuthenticationInfo("zhangcn","111111",this.getName());
}
return authenticationInfo;
}
}
2.告知shiro要使用自定義realm
[main]
#自定義 realm
customRealm=com.baizhi.test.MyRealm
#將realm設置到securityManager
securityManager.realms=$customRealm
注意:需要導入一個jar
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
11.shiro的加密認證方式
1.加密測試
@Test
public void testMD5() {
//參數 明文密碼
Md5Hash md5Hash = new Md5Hash("111111");
//參數 明文密碼 鹽值
Md5Hash md5Hash = new Md5Hash("111111","ABCD");
//參數 明文密碼 鹽值 散列次數
Md5Hash md5Hash = new Md5Hash("111111","ABCD",1024);
//調用加密方法
String s = md5Hash.toHex();
System.out.println(s);
}
2.realm返回密文數據
package com.baizhi.test;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.AuthenticatingRealm;
import org.apache.shiro.util.ByteSource;
public class MyRealm extends AuthenticatingRealm {
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//根據token 獲取身份信息
String username = (String) authenticationToken.getPrincipal();
//調用根據用戶名查詢用戶的方法
//User user=userDao.queryByName(username);
AuthenticationInfo authenticationInfo=null;
if(username.equals("zhangcn")){
//參數: 數據庫取出的 用戶名 密文 鹽值
authenticationInfo = new SimpleAuthenticationInfo("zhangcn","e0504e77b06f5a26faf37d044c65992b", ByteSource.Util.bytes("ABCD"),this.getName());
}
return authenticationInfo;
}
}
3.修改配置文件,加入憑證匹配器的相關配置
[main]
#自定義憑證匹配器
hashedCredentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
#自定義 realm
customRealm=com.baizhi.test.MyRealm
#憑證匹配器告訴誰
customRealm.credentialsMatcher=$hashedCredentialsMatcher
hashedCredentialsMatcher.hashAlgorithmName=MD5
hashedCredentialsMatcher.hashIterations=1024
#將realm設置到securityManager
securityManager.realms=$customRealm
12.授權
1.授權數據來源於數據庫
public class MyRealm extends AuthorizingRealm {
//獲取數據 獲取認證的數據
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token){
//數據庫操作 基於身份信息查主體
}
//獲取數據 獲取授權的數據
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection var1){
//數據庫操作 基於身份信息查主體 基於主體查角色 基於角色查權限
}
}
1-1.示例
package com.baizhi.test;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.AuthenticatingRealm;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import java.util.Arrays;
import java.util.List;
public class MyRealm extends AuthorizingRealm {
//認證
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//根據token 獲取身份信息
String username = (String) authenticationToken.getPrincipal();
//調用根據用戶名查詢用戶的方法
//User user=userDao.queryByName(username);
AuthenticationInfo authenticationInfo=null;
if(username.equals("zhangcn")){
//參數 用戶名,密碼,鹽值,類名
authenticationInfo = new SimpleAuthenticationInfo("zhangcn","e0504e77b06f5a26faf37d044c65992b", ByteSource.Util.bytes("ABCD"),this.getName());
}
return authenticationInfo;
}
//授權
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//主體 角色 權限
//從數據庫查 主身份
String primaryPrincipal = (String) principalCollection.getPrimaryPrincipal();
if(primaryPrincipal.equals("zhangcn")){
//從數據庫查根據主體查角色
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
//添加角色
simpleAuthorizationInfo.addRole("super");
//simpleAuthorizationInfo.addRole("admin");
//添加權限
//simpleAuthorizationInfo.addStringPermission("admin:delete");
//添加多個權限
List<String> strings = Arrays.asList("admin:delete","admin:query","admin:update");
simpleAuthorizationInfo.addStringPermissions(strings);
return simpleAuthorizationInfo;
}
return null;
}
}
2.java環境下授權的api
-
基於角色
//判斷當前主體是否包含此角色
boolean b = subject.hasRole(“super”);//判斷當前主體是否包含某個角色 List<String> list = Arrays.asList("super", "admin"); boolean[] booleans = subject.hasRoles(list); //判斷當前主體是否包含全部角色 boolean b = subject.hasAllRoles(list);
-
基於資源
//判斷當前角色是否包含此權限
boolean permitted = subject.isPermitted(“admin:delete”);//判斷當前角色是否包含某個權限 String[] str={"admin:delete","admin:insert"}; boolean[] permitted = subject.isPermitted(str); //判斷當前角色是否包含全部權限 boolean permittedAll = subject.isPermittedAll(str);
2-1示例
package com.baizhi.test;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.A uthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import java.util.Arrays;
import java.util.List;
public class TestShiro {
public static void main(String[] args) {
//獲取安全管理器工廠
IniSecurityManagerFactory iniSecurityManagerFactory = new IniSecurityManagerFactory();
//通過工廠 獲取安全管理器
SecurityManager securityManager = iniSecurityManagerFactory.getInstance();
//將安全管理器 給 安全工具類
SecurityUtils.setSecurityManager(securityManager);
//獲取主體對象
Subject subject = SecurityUtils.getSubject();
//token 就是用戶的令牌 包含用戶的身份信息和憑證信息
AuthenticationToken token =new UsernamePasswordToken("zhangcn","111111");
try {
//認證
subject.login(token);
} catch (AuthenticationException e) {
e.printStackTrace();
// AuthenticationToken 未找到賬戶異常
// IncorrectCredentialsException 證書不正確異常
}
//當前用戶是否通過驗證 是否認證通過
boolean authenticated = subject.isAuthenticated();
//基於角色
if(authenticated){
// admin super
if(subject.hasRole("super")){
System.out.println("super");
}
//判斷當前主體是否包含此角色
//boolean b = subject.hasRole("super");
List<String> str = Arrays.asList("super", "admin");
//判斷當前主體是否包含某個角色
boolean[] booleans = subject.hasRoles(str);
for (int i = 0; i < booleans.length; i++) {
boolean aBoolean = booleans[i];
System.out.println(aBoolean);
}
//判斷當前主體是否包含全部的角色
boolean b = subject.hasAllRoles(str);
System.out.println(b);
}*/
//基於資源
if(authenticated){
//判斷當前角色是否包含此權限
boolean permitt = subject.isPermitted("admin:delete");
//如果包含此權限 繼續執行操作
if(permitted){
//adminDao.delete(id); 執行刪除方法
System.out.println("執行刪除方法");
}
//判斷當前角色是否包含某個權限
String[] str={"admin:delete","admin:insert"};
boolean[] permitted = subject.isPermitted(str);
for (int i = 0; i < permitted.length; i++) {
boolean b = permitted[i];
System.out.println(b);
}
//判斷當前角色是否包含全部權限
boolean permittedAll = subject.isPermittedAll(str);
System.out.println(permittedAll);
}
}
}
3.權限的標識符
權限字符串的規則是:“資源標識符:操作:資源實例標識符”,意思是對哪個資源的哪個實例具有什麼操作,“:”是資源/操作/實例的分割符,權限字符串也可以使用*通配符。
例子:
- 用戶創建權限:user:create,或user:create:*
- 用戶修改實例001的權限:user:update:001
- 用戶實例001的所有權限:user:*:001
13.springboot環境下的認證和授權
1.相關的jar
<!-- 給內嵌tomcat提供jsp解析功能的jar-->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
<!--shiro相關jar包-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.3.2</version>
</dependency>
<!--shiro與spring整合相關jar包-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
2.配置shrio的核心過濾器
@Configuration
public class ShiroFilterConf {
//shiro過濾器的配置
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
//多個過濾器 AnonymousFilter 匿名過濾器 anon
// FormAuthenticationFilter 認證過濾器 authc
Map<String, String> map = new HashMap<>();
map.put("/user/loginUser", "anon");
map.put("/index.jsp", "anon");
map.put("/**", "authc");
//設置登錄入口的路徑
shiroFilterFactoryBean.setLoginUrl("/main/login.jsp");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
}
//shiro的核心對象 安全管理器
@Bean
public SecurityManager getSecurityManager(Realm realm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(realm);
return securityManager;
}
//自定義realm
@Bean
public Realm getRealm(CredentialsMatcher credentialsMatcher) {
MyRealm myRealm = new MyRealm();
myRealm.setCredentialsMatcher(credentialsMatcher);
return myRealm;
}
//選擇HashedCredentialsMatcher 憑證匹配器
@Bean
public CredentialsMatcher getCredentialsMatcher() {
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashAlgorithmName("md5");
hashedCredentialsMatcher.setHashIterations(1024);
return hashedCredentialsMatcher;
}
}
//緩存jar包
<!--緩存jar包-->
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>3.6.3</version>
</dependency>
3.shiro過濾器
ssl :org.apache.shiro.web.filter.authz.SslFilter
user :org.apache.shiro.web.filter.authz.UserFilter
anon :org.apache.shiro.web.filter.authc.AnonymousFilter
port :org.apache.shiro.web.filter.authz.PortFilter
rest :org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter
authc :org.apache.shiro.web.filter.authc.FormAuthenticationFilter
perms :org.apache.shiro.web.filter.authz.PermissionAuthorizationFilter
roles :org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
logout :org.apache.shiro.web.filter.authc.LogoutFilter
authcBasic :org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
noSessionCreation :org.apache.shiro.web.filter.session.NoSessionCreationFilter
過濾器簡稱
過濾器 作用
4.shiro中相關的標籤
<shiro:principal></shiro:principal> //用戶的身份信息
<shiro:authenticated></shiro:authenticated> //認證成功 執行標籤體的內容
<shiro:notAuthenticated></shiro:notAuthenticated> //未認證 執行標籤體內容
//授權
//基於角色
<shiro:hasRole name="super"></shiro:hasRole>
//有任意角色都展示
<shiro:hasAnyRoles name="admin,super"></shiro:hasAnyRoles>
//基於資源
<shiro:hasPermission name="user:delete"></shiro:hasPermission>
5.示例
5.1.Controller
package com.baizhi.controller;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@RequestMapping("/user")
@Controller
public class UserController {
@RequestMapping("login")
public String login(String username,String password){
System.out.println("=="+username);
System.out.println("=="+password);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username,password);
try {
subject.login(usernamePasswordToken);
return "main/main";
} catch (UnknownAccountException e) {
System.out.println("用戶不存在");
return "main/login";
} catch (IncorrectCredentialsException e) {
System.out.println("密碼不正確");
return "main/login";
}
}
@RequestMapping("logout")
public String logout(){
Subject subject = SecurityUtils.getSubject();
subject.logout();
return "/main/main";
}
}
5.2.認證和授權
package com.baizhi.shiro.realm;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.authz.aop.AuthorizingAnnotationHandler;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import java.util.Arrays;
public class MyRealm extends AuthorizingRealm {
//認證
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//根據Token獲取身份信息
String username = (String) authenticationToken.getPrincipal();
//根據身份信息查詢數據庫
//獲取數據庫的身份信息與前臺的傳入的身份信息作對比
if(username.equals("zhangcn")){
//從數據庫查出的信息 身份信息 憑證信息 鹽值 類名
AuthenticationInfo authenticationInfo=new SimpleAuthenticationInfo("zhangcn","e0504e77b06f5a26faf37d044c65992b", ByteSource.Util.bytes("ABCD"),this.getName());
return authenticationInfo;
}
return null;
}
//授權
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("=========================");
//給主體賦予角色 權限
//從數據庫查 通過主體查角色,同構角色查權限 ppl主體
String ppl = (String) principalCollection.getPrimaryPrincipal();
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
simpleAuthorizationInfo.addRole("super");
//添加某個權限
simpleAuthorizationInfo.addStringPermission("user:delete");
simpleAuthorizationInfo.addStringPermission("user:update");
simpleAuthorizationInfo.addStringPermission("user:query");
//添加權限集合
simpleAuthorizationInfo.addStringPermissions(Arrays.asList("user:delete","user:update","user:query"));
return simpleAuthorizationInfo;
}
}
5.3.配置
package com.baizhi.shiro.conf;
import com.baizhi.shiro.realm.MyRealm;
import com.sun.org.apache.bcel.internal.generic.RETURN;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
@Configuration
public class ShiroFilterConf {
//創建shiro過濾器
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(SecurityManager securityManager){
//shiro過濾器
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
//過濾器默認不攔截 想要攔截需要配置攔截規則 /* *.do
HashMap<String, String> map = new HashMap<>();
//配置攔截規則
map.put("/**","authc");
map.put("/user/login","anon");
map.put("/main/main.jsp","anon");
//設置跳轉頁面
shiroFilterFactoryBean.setLoginUrl("/main/login.jsp");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
}
//創建安全管理器
@Bean
public SecurityManager getSecurityManager(Realm realm,EhCacheManager ehCacheManager){
//安全管理器
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
defaultWebSecurityManager.setCacheManager(ehCacheManager);
defaultWebSecurityManager.setRealm(realm);
return defaultWebSecurityManager;
}
//配置自定義realm
@Bean
public Realm getRealm(CredentialsMatcher credentialsMatcher){
MyRealm myRealm = new MyRealm();
//將憑證匹配器 放入Realm
myRealm.setCredentialsMatcher(credentialsMatcher);
return myRealm;
}
//配置憑證匹配器
@Bean
public CredentialsMatcher getCredentialsMatcher(){
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
hashedCredentialsMatcher.setHashIterations(1024);
hashedCredentialsMatcher.setHashAlgorithmName("md5");
return hashedCredentialsMatcher;
}
//配置shiro緩存
@Bean
public EhCacheManager getEhCacheManager(){
EhCacheManager ehCacheManager = new EhCacheManager();
return ehCacheManager;
}
}
5.4.jsp
<%@page pageEncoding="UTF-8" isELIgnored="false" contentType="text/html; UTF-8" %>
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="path" value="${pageContext.request.contextPath}" />
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body align="center">
<h1>持明法州後臺管理系統</h1>
<shiro:authenticated>
您好!<font style="color: red"><strong><shiro:principal/></strong></font>歡迎登錄本系統  
<strong><a href="${path}/user/logout">退出</a></strong><br>
<ul>
<li>輪播圖管理</li>
<li>上師管理</li>
<li>專輯管理</li>
<li>文章管理</li>
<shiro:hasAnyRoles name="admin,super">
<li>用戶管理</li>
</shiro:hasAnyRoles>
<shiro:hasRole name="super">
管理員管理
<hr>
<shiro:hasPermission name="user:query">增</shiro:hasPermission>
<shiro:hasPermission name="user:delete">刪</shiro:hasPermission>
<shiro:hasPermission name="user:update">改</shiro:hasPermission>
<shiro:hasPermission name="user:insert">查</shiro:hasPermission>
</shiro:hasRole>
</ul>
</shiro:authenticated>
<shiro:notAuthenticated>
<a href="${path}/main/login.jsp">您還沒有登錄,請登錄本系統,登陸之後可以瀏覽更多內容</a>
</shiro:notAuthenticated>
</body>
</html>