- Shiro四大基石(身份認證,授權,會話管理,密碼學)
- shiro核心對象:SecurityManager對象
- 控制層登錄認證:獲取到SecurityManager對象后,通過SecurityUtils將SecurityManager設置到shiro環境中去和獲取主體,然后在創建一個令牌,主體登錄,將token傳入進去。
@RequestMapping("/login")
public String login(String username,String password){
// 獲取當前登錄的主體
Subject subject = SecurityUtils.getSubject();
// 判斷當前主體是否已經通過了驗證
if (!subject.isAuthenticated()){
// 沒有通過驗證,獲取token傳入username和password進行登錄
UsernamePasswordToken token = new UsernamePasswordToken(username,password);
try {
subject.login(token);
} catch (UnknownAccountException e) {
e.printStackTrace();
System.out.println("用戶名不存在");
}catch (IncorrectCredentialsException e) {
e.printStackTrace();
System.out.println("密碼錯誤");
}catch (AuthenticationException e) {
e.printStackTrace();
System.out.println("未知錯誤");
}
}
return "redirect:/s/main.jsp";//跳轉到登錄成功的頁面去
} - 自定義realm(繼承AuthorizingRealm)
認證,授權,加密 - Shiro整合Spring
a) 導入shiro和Spring的整合包
<!-- 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>
b) 在web.xml配置shiroFilter(代理過濾器)
<!--shiro代理過濾器-->
<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>
c) 配置Shiro的配置文件:配置shiro安全管理器,和自定義的realm,配置讓shiro支持注解,配置真實過濾器(Id必須與web.xml 中的shiroFilter名字對應),真實過濾器中要配置放行和攔截,然后在Spring配置文件中引入shiro的配置文件
<?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="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="myRealm"/>
</bean>
<!--自定義的realm-->
<bean id="myRealm" class="cn.itsource.aisell.shiro.MyRealm">
<!--配置加密方式
加鹽的話就在myRealm實體類在返回SimpleAuthenticationInfo之前加鹽。
-->
<property name="credentialsMatcher">
<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="MD5"/>
<property name="hashIterations" value="10"/>
</bean>
</property>
</bean>
<!--配置支持shiro注解-->
<!-- 3.lifecycleBeanPostProcessor:可以自動調用在Spring Ioc窗口中 Shiro bean的生成周期方法 -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<!-- 4.啟動ioc容器中使用 shiro的注解,但是必需配置在Spring Ioc容器中Shiro bean的生成周期方法 -->
<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>
<!--配置shiro的真實過濾器-->
<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:需要權限才能訪問
/** :所有文件及其子文件,這里筆者創建了一個bean來裝權限交給Spring進行管理
-->
<property name="filterChainDefinitionMap" ref="filterChainDefinitionMap">
<!--<value>-->
<!--<!–anon放行,authc攔截–>-->
<!--/login = anon-->
<!--/s/login.jsp = anon-->
<!--<!–對資源進行權限控制,要控制的資源都應該從數據庫查出,現在咱們先寫死–>-->
<!--/s/permission.jsp = perms[user:*]-->
<!--/** = authc-->
<!--</value>-->
</property>
</bean>
<bean id="filterChainDefinitionMap" factory-bean="aisellFilterChainDefinitionMapBuilder" factory-method="creatFilterChainDefinitionMap"/>
<bean id="aisellFilterChainDefinitionMapBuilder" class="cn.itsource.aisell.shiro.AisellFilterChainDefinitionMapBuilder"/>
</beans>
- shiro的兩大核心(登錄驗證和授權)
a) 登錄驗證
i. 在控制層前台傳過來兩個登錄信息,首先通過SecurityUtils獲取到當前登錄的主體,判斷這個主體是否已經通過了驗證,如果沒有通過驗證,就new UsernamePasswordToken對象傳入前 台傳入的兩個登錄信息,然后主體調用登錄方法,進行登錄。在自定義的Realm(我這里是myRealm),進行登錄驗證,通過賦寫的方法的參數獲取到當前主體,獲取到登錄的兩個信息,然后到 數據庫查詢是否有這個信息,有就登錄成功,沒有就登陸失敗,向前台返回一個 SimpleAuthenticationInfo對象
// 身份認證
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
// 獲取當前主體
UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
String username = token.getUsername();
String password = findPasswordByUsername(username);
if (password==null){
return null;
}
// SimpleHash simpleHash = new SimpleHash("MD5", "147258", 10);
// System.out.println(simpleHash);
// 填加鹽值
ByteSource salt = ByteSource.Util.bytes("itsource");
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username,password,salt,getName());
return authenticationInfo;
}
private String findPasswordByUsername(String username){
if ("admin".equals(username)){
// 這個是進行了加密的密碼
return "d824670230ca2856ad808c0c0f834b42";
}
return null;
}
b) 授權
i. 首先我們定義一個實體類,來創建map集合來存儲權限交給Spring管理,然后在Spring的配置文件里面配置這個bean。在外面自定義的realm(我的是MyRealm)中進行一個授權,首先通 過賦寫的方法的參數獲取帶當前的登錄對象,定義一個Set來裝權限,通過獲取SimpleAuthorizationInfo對象將Set穿進去與Spring管理的Map權限進行比對
// 身份授權
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals){
// 獲取當前登錄主體
String username = (String)principals.getPrimaryPrincipal();
System.out.println("后面需要根據用戶名獲取資源"+username);
// 定義一個set來裝權限
HashSet<String> permissons = new HashSet<>();
// 添加權限
permissons.add("user:*");
// 將權限交給Spring進行比對
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
// 將權限交給設置進去Spring
authorizationInfo.setStringPermissions(permissons);
return authorizationInfo;
}
- Shiro的密碼學
a) 我們先在我們xml配置的自定義的realm里面添加加密的方式,注意這里面只能添加密的方式和次數,如果要添加鹽值的話就要到MyRealm的實體類中的身份認證方法里面去添加鹽值
在上面的shiro配置文件里面有配置