今天的任務是在原有的框架中集成shirojava
1.shiro的認識
> 權限框架(提供的易用的API,功能強大)web
1.1 和Spring security區別
框架 | shiro | Spring security
---|------| ---
易用性 | √ | X
粒度 | 粗 | 細(強大)算法
1.2 shiro的四大基石
> 身份驗證、受權、密碼學和會話管理
> securityManager:核心對象 realm:獲取數據接口spring
2.shiro的核心api
2.1 操做以前,先獲得securityManager對象
```數據庫
//一.建立咱們本身的Realm MyRealm myRealm = new MyRealm(); //二.搞一個核心對象: DefaultSecurityManager securityManager = new DefaultSecurityManager(); securityManager.setRealm(myRealm); //三.把securityManager放到上下文中 SecurityUtils.setSecurityManager(securityManager);
```apache
## 2.2 咱們使用過的方法api
```app
//1.拿到當前用戶 Subject currentUser = SecurityUtils.getSubject(); //2.判斷是否登陸 currentUser.isAuthenticated(); //3.登陸(須要令牌的) /** UnknownAccountException:用戶名不存在 IncorrectCredentialsException:密碼錯誤 AuthenticationException:其它錯誤 */ UsernamePasswordToken token = new UsernamePasswordToken("admin", "123456"); currentUser.login(token); //4.判斷是不是這個角色/權限 currentUser.hasRole("角色名") currentUser.isPermitted("權限名")
```
# 3.密碼加密功能
```框架
/** * String algorithmName, Object source, Object salt, int hashIterations) * 第一個參數algorithmName:加密算法名稱 * 第二個參數source:加密原密碼 * 第三個參數salt:鹽值 * 第四個參數hashIterations:加密次數 */ SimpleHash hash = new SimpleHash("MD5","123456","itsource",10); System.out.println(hash.toHex()); ``` # 4.自定義Realm > 繼承AuthorizingRealm >> 實現兩個方法:doGetAuthorizationInfo(受權) /doGetAuthenticationInfo(登陸認證) ``` //身份認證 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { //1.拿用戶名與密碼 UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken; String username = token.getUsername(); //2.根據用戶名拿對應的密碼 String password = getByName(username); if(password==null){ return null; //返回空表明用戶名有問題 } //返回認證信息 //準備鹽值 ByteSource salt = ByteSource.Util.bytes("asdf"); //密碼是shiro本身進行判斷 SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username,password,salt,getName()); return authenticationInfo; } //受權 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { //拿到用戶名 Principal:主體(用戶對象/用戶名) String username = (String)principalCollection.getPrimaryPrincipal(); //拿到角色 Set<String> roles = findRolesBy(username); //拿到權限 Set<String> permis = findPermsBy(username); //把角色權限交給用戶 SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); authorizationInfo.setRoles(roles); authorizationInfo.setStringPermissions(permis); return authorizationInfo; }
> 注意:若是咱們的密碼加密,應該怎麼判斷(匹配器)jsp
//一.建立咱們本身的Realm MyRealm myRealm = new MyRealm(); //建立一個憑證匹配器(沒法設置鹽值) HashedCredentialsMatcher matcher = new HashedCredentialsMatcher(); // 使用MD5的方式比較密碼 matcher.setHashAlgorithmName("md5"); // 設置編碼的迭代次數 matcher.setHashIterations(10); //設置憑證匹配器(加密方式匹配) myRealm.setCredentialsMatcher(matcher);
```
# 5.集成Spring
> 去找:shiro-root-1.4.0-RC2\samples\spring
## 5.1 導包
```
<!-- shiro的支持包 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-all</artifactId> <version>1.4.0</version> <type>pom</type> </dependency> <!-- shiro與Spring的集成包 --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.0</version> </dependency>
## 5.2 web.xml> 這個過濾器是一個代碼(只關注它的名稱)
<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>
## 5.3 application-shiro.xml
> 在我們的application引入
`<import resource="classpath:applicationContext-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-3.0.xsd"> <!-- 建立securityManager這個核心對象 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <!-- 設置一個realm進去 --> <property name="realm" ref="jpaRealm"/> </bean> <!-- 被引用的realm(必定會寫一個自定義realm) --> <bean id="jpaRealm" class="cn.xxx.aisell.shiro.JpaRealm"> <!-- 爲這個realm設置相應的匹配器 --> <property name="credentialsMatcher"> <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"> <!-- 設置加密方式 --> <property name="hashAlgorithmName" value="md5"/> <!-- 設置加密次數 --> <property name="hashIterations" value="10" /> </bean> </property> </bean> <!-- 可讓我們的權限判斷支持【註解】方法 --> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"/> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager"/> </bean> <!-- 真正實現權限的過濾器 它的id名稱和web.xml中的過濾器名稱同樣 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <property name="securityManager" ref="securityManager"/> <!-- 登陸路徑:若是沒有登陸,就會跳到這裏來 --> <property name="loginUrl" value="/s/login.jsp"/> <!-- 登陸成功後的跳轉路徑 --> <property name="successUrl" value="/s/main.jsp"/> <!-- 沒有權限跳轉的路徑 --> <property name="unauthorizedUrl" value="/s/unauthorized.jsp"/> <!-- anon:這個路徑不須要登陸也能夠訪問 authc:須要登陸才能夠訪問 perms[depts:index]:作權限攔截 我們之後哪些訪問有權限攔截,須要從數據庫中讀取 --> <!-- <property name="filterChainDefinitions"> <value> /s/login.jsp = anon /login = anon /s/permission.jsp = perms[user:index] /depts/index = perms[depts:index] /** = authc </value> </property> --> <property name="filterChainDefinitionMap" ref="filterChainDefinitionMap" /> </bean> <!-- 實例工廠設置 --> <bean id="filterChainDefinitionMap" factory-bean="filterChainDefinitionMapFactory" factory-method="createFilterChainDefinitionMap" /> <!-- 建立能夠拿到權限map的bean --> <bean id="filterChainDefinitionMapFactory" class="cn.itsource.aisell.shiro.FilterChainDefinitionMapFactory" /> </beans>
```
5.4 獲取Map過濾
> 注意,返回的Map必需是有序的(LinkedHashMap)```
public class FilterChainDefinitionMapFactory { /** * 後面這個值會從數據庫中來拿 * /s/login.jsp = anon * /login = anon * /s/permission.jsp = perms[user:index] * /depts/index = perms[depts:index] * /** = authc */ public Map<String,String> createFilterChainDefinitionMap(){ //注:LinkedHashMap是有序的 Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>(); filterChainDefinitionMap.put("/s/login.jsp", "anon"); filterChainDefinitionMap.put("/login", "anon"); filterChainDefinitionMap.put("/s/permission.jsp", "perms[user:index]"); filterChainDefinitionMap.put("/depts/index", "perms[depts:index]"); filterChainDefinitionMap.put("/**", "authc"); return filterChainDefinitionMap; } }
今日重點 : 對securityManage 對象的獲取,在權限認證步驟中須要的信息傳遞(用戶,角色,權限)
細節 : 對於在設置權限列表時須要注意順序,-----放行在前->權限在後->最後同一攔截 /** = authc