在 shiro 中,用戶需要提供principals (身份)和credentials(證明)給shiro,從而應用能
驗證用戶身份:
principals:身份,即主體的標識屬性,可以是任何東西,如用戶名、郵箱等,唯一即可。
一個主體可以有多個principals,但只有一個Primary principals,一般是用戶名/密碼/手機號。
credentials:證明/憑證,即只有主體知道的安全值,如密碼/數字證書等。
最常見principals和credentials組合就是用戶名/密碼了。
身份驗證的步驟:
1、收集用戶身份/憑證,即如用戶名/密碼;
2、調用Subject.login 進行登錄,如果失敗將得到相應的AuthenticationException 異常,根
據異常提示用戶錯誤信息;否則登錄成功;
3、最後調用Subject.logout進行退出操作。
如上測試的幾個問題:
1、用戶名/密碼硬編碼在ini配置文件,以後需要改成如數據庫存儲,且密碼需要加密存儲;
2、用戶身份Token 可能不僅僅是用戶名/密碼,也可能還有其他的,如登錄時允許用戶名/
郵箱/手機號同時登錄。
通過shiro 自帶的formAuthenticationFilter 攔截器進行登錄,登錄失敗的話
會把錯誤存到shiroLoginFailure 屬性中,在該控制器中獲取後來顯示相應的錯誤信息。
需要在spring-config-shiro.xml中配置
<!-- 基於Form表單的身份驗證過濾器 -->
<bean id="formAuthenticationFilter" class="org.apache.shiro.web.filter.authc.FormAuthenticationFilter">
<property name="usernameParam" value="username"/>
<property name="passwordParam" value="password"/>
<property name="rememberMeParam" value="rememberMe"/>
<property name="loginUrl" value="/login"/>
</bean>
<!-- Shiro的Web過濾器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/login"/>
<property name="filters">
<util:map>
<entry key="authc" value-ref="formAuthenticationFilter"/>
<entry key="sysUser" value-ref="sysUserFilter"/>
</util:map>
</property>
<property name="filterChainDefinitions">
<value>
/login = authc
/logout = logout
/authenticated = authc
/** = user,sysUser
</value>
</property>
</bean>
通過自定義的sysUserFilter用於根據當前登錄用戶身份獲取User信息放入request;然後就可以通過request獲取User。
需要在
spring-config-shiro.
<bean id="sysUserFilter" class="com.routon.sys.web.shiro.filter.SysUserFilter"/>
密解密
Shiro 提供了CredentialsMatcher 的散列實現HashedCredentialsMatcher,它只用於密碼驗證,且可以提供自己的鹽,而不是隨機生成鹽,且生成密碼散列值的算法需要自己寫,因爲能提供自己的鹽。
生成密碼散列值
使用MD5算法,“密碼+鹽(自定義的鹽)”的方式生成散列值
String algorithmName = "md5";
String username = "zhang";
String password = "123456";
String salt = 8d78869f470951332959580424d4bf4f;
int hashIterations = 2;
SimpleHash hash = new SimpleHash(algorithmName, password, salt, hashIterations);
寫用戶模塊時,需要在新增用戶/重置密碼時使用如上算法保存密碼,將生成的密碼及
salt存入數據庫
生成的密碼交給realm
//交給AuthenticatingRealm使用CredentialsMatcher進行密碼匹配
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
user.getUsername(), //用戶名
user.getPassword(), //密碼 ByteSource.Util.bytes(user.getCredentialsSalt()),//salt=username+salt
getName() //realm name
);
具體參看:spring-config-shiro.xml
<!-- 憑證匹配器 -->
<bean id="credentialsMatcher" class="com.routon.sys.credentials.RetryLimitHashedCredentialsMatcher">
<constructor-arg ref="cacheManager"/>
<property name="hashAlgorithmName" value="md5"/>
<!--散列迭代次數-->
<property name="hashIterations" value="2"/>
<!--表示是否存儲散列後的密碼爲16 進制,默認是base64 -->
<property name="storedCredentialsHexEncoded" value="true"/>
</bean>
<!-- Realm實現 -->
<bean id="userRealm" class="com.routon.sys.realm.UserRealm">
<property name="credentialsMatcher" ref="credentialsMatcher"/>
<property name="cachingEnabled" value="false"/>
<!--<property name="authenticationCachingEnabled" value="true"/>-->
<!--<property name="authenticationCacheName" value="authenticationCache"/>-->
<!--<property name="authorizationCachingEnabled" value="true"/>-->
<!--<property name="authorizationCacheName" value="authorizationCache"/>-->
</bean>
訪問控制
在系統中控制誰能訪問哪些資源(如訪問頁面/編輯數據/頁面操作
等)。
通過在執行的方法上放置相應的註解完成:
@RequiresPermissions("sys:role:view")
@RequestMapping(method = RequestMethod.GET)
public String list(Model model) {
model.addAttribute("roleList", roleService.findAll());
return "role/list";
}
在JSP頁面通過相應的標籤完成:
<shiro:hasPermission name="sys:role:view">
<!— 有權限—>
</shiro:hasPermission>