Shiro學習(二)之整合SSH框架篇

1:在pom.xml文件引入shiro的依賴java

<properties>
          <shiro.version>1.3.2</shiro.version> 
        </properties>

        <!-- 引入shiro依賴  START-->
		<dependency>
		 <groupId>org.apache.shiro</groupId>
		 <artifactId>shiro-core</artifactId>
		 <version>${shiro.version}</version>
		</dependency>
		
		<dependency>
		 <groupId>org.apache.shiro</groupId>
		 <artifactId>shiro-web</artifactId>
		 <version>${shiro.version}</version>
		</dependency>
		
		<dependency>
		 <groupId>org.apache.shiro</groupId>
		 <artifactId>shiro-spring</artifactId>
		 <version>${shiro.version}</version>
		</dependency>
		<!-- 引入shiro依賴  END-->

2:在web.xml配置shiro的攔截器web

<!-- 配置shiro的核心攔截器   start -->
    <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>
   <!-- 配置shiro的核心攔截器     end -->

3:新建applicationContext-shiro.xml文件spring

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
">

        <!--1.配置CacheManager實例:管理Shiro相關緩存操做  -->  
        <!-- <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">   
            <property name="cacheManagerConfigFile" value="classpath:ehcache.xml"></property>  
        </bean>  --> 
          
        <!--2.配置realm實例,實際的認證和受權都是由R ealm實例來完成的!  -->  
        <bean id="myRealm" class="com.mrp.shiro.MyShiroRealm">
	        <!-- 配置密碼匹配器 -->   
	     <property name="credentialsMatcher" ref="credentialsMatcher"/>  
        </bean>
        
        <!--3.憑證匹配器 -->  
	    <bean id="credentialsMatcher" class="com.mrp.shiro.CustomCredentialsMatcher">  
	    </bean> 
      
        <!-- 4.配置 SecurityManager 實例. SecurityManager 是 Shiro 最核心的組件 -->  
        <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">  
           <!--  <property name="cacheManager" ref="cacheManager"/> -->  
            <property name="realm" ref="myRealm"/>  
        </bean>  
          
        <!--5.配置bean的後置處理器來自動調用Shiro中的bean的init和destroy方法。  -->  
        <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"></bean>  
          
          
        <!--6.配置使shiro註解起做用的bean,須要放在 lifecycleBeanPostProcessor後面 -->  
        <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"></bean>      
        <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">  
            <property name="securityManager" ref="securityManager"></property>  
        </bean>  
        
        <!--自定義的filter,roles[]知足其中一個角色便可-->
		<bean id="roleOrFilter" class="com.mrp.shiro.CustomRolesAuthorizationFilter"> 
		 </bean>
          
        <!--  
            7.配置哪些頁面須要被攔截,以及訪問這些頁面所需的權限 。  
                                   該bean中的id 屬性值必須和 web.xml 文件中配置的 filter 的 filter-name 值一致  
        -->  
        <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">  
            <property name="securityManager" ref="securityManager"></property>  
          
            <!-- 未認證,跳轉到哪一個頁面      -->  
            <property name="loginUrl" value="/login.jsp"></property>  
            <!-- 登陸成功跳轉頁面    -->
            <property name="successUrl" value="/biz/Login_openIndex.action"></property> 
            <!-- 認證後,沒有權限跳轉頁面 -->
           <property name="unauthorizedUrl" value="/biz/SysUser_openNoPermission.action"></property>
           <property name="filters">
		       <map>
	    	    <entry key="roleOrFilter" value-ref="roleOrFilter"/>
	    	  </map>
		   </property>
               <!-- shiro URL控制過濾器規則  
		        anon未認證能夠訪問
				authc認證後能夠訪問
				perms須要特定權限才能訪問
				roles須要特定角色才能訪問
				user須要特定用戶才能訪問
				port須要特定端口才能訪問(不經常使用)
				rest根據指定HTTP請求才能訪問(不經常使用)
			    *文件夾中的所有文件
			    **  文件夾中的所有文件(含子文件夾)
		       -->  
		     <!--②配置須要被攔截的資源 以及訪問權限 -->
            <property name="filterChainDefinitions">  
                <value>  
                    <!-- anon: 表示匿名的, 即任何人均可以訪問 -->
			        /lib/** = anon
			        /static/**  = anon
                    /login.jsp=anon 
                    /rand/SecurityCodeImage_execute.action=anon 
                    /biz/Login_webLogin.action=anon 
                    <!--③設置訪問具體資源的權限  
                    /biz/Login_webLogin.action=roles[admin]  
                    /user.jsp=roles[user]  
                      --> 
                    <!-- authc 表示必須通過認證以後才能夠訪問的頁面 -->  
                    <!-- /WEB-INF/page/index.jsp=authc
                    /WEB-INF/page/welcome.jsp=authc -->
                    
                    <!-- perms須要特定權限才能訪問 -->
                    /biz/SysOperateRecord_list.action=perms[sysOperateRecord]
                    /biz/SysRight_list.action=authc,roleOrFilter["root","manager"]
                    /**=authc
                </value>  
            </property>  
        </bean>  

</beans>

4:自定義Realm,新建MyShiroRealm.java數據庫

public class MyShiroRealm extends AuthorizingRealm {
	
	@Autowired
	private ISysUserService sysUserService;
	@Autowired
	private SysUserDAO sysUserDAO;

	/**
	 * 受權
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		//獲取當前登陸輸入的用戶名
		String loginName = (String) principals.getPrimaryPrincipal();
    	//到數據庫查是否有此對象
    	SysUser sysUser =  sysUserDAO.findSysUserByProperty("userId", loginName);
    	if(sysUser != null) {
    		//權限信息對象info,用來存放查出的用戶的全部的角色(role)及權限(permission)
    		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
    		//查詢用戶對於的角色
    		List<String> userRoleList = sysUserService.findByRole(sysUser.getUserId());
    		//添加角色
    		info.addRoles(userRoleList);
    		// 查詢用戶對應的權限(用戶->角色->權限)
    		List<String> permissions = sysUserService.findUserPermissions(sysUser.getUserId());
    		//添加權限
    		info.addStringPermissions(permissions);
    		return info;
    	}
        return null;  
	}

	/**
	 * 登陸驗證
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
		//UsernamePasswordToken對象用來存放提交的登陸信息
    	UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
    	//查出是否有此用戶
    	SysUser sysUser =  sysUserDAO.findSysUserByProperty("userId", token.getUsername());
    	if (sysUser == null) {
            //用戶不存在
            return null;//拋出異常
        } else {
            //用戶名存在
            //參數1:用戶對象,未來要放入session,數據庫查詢出來的用戶
            //參數2:憑證(密碼):密碼校驗:校驗的動做交給shiro
            //參數3:當前使用的Realm在Spring容器中的名字(bean的名字,自動在spring容器中尋找)
            SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(sysUser.getUserId(), sysUser.getPwd(), super.getName());
            return authenticationInfo;//密碼校驗失敗,會自動拋出IncorrectCredentialsException
        }
	}

}

5:自定義密碼匹配器(由於以前的項目都是使用spring自帶的PasswordEncoder加密與匹配,因此須要自定義密碼匹配器)apache

public class CustomCredentialsMatcher extends SimpleCredentialsMatcher {
	@Override   
    public boolean doCredentialsMatch(AuthenticationToken authcToken, AuthenticationInfo info) {    
             
    UsernamePasswordToken token = (UsernamePasswordToken) authcToken; 
    //明文密碼(須要匹配的用戶輸入的那份)
    String rawPasswd =  String.valueOf(token.getPassword());
    //數據庫的中的密碼  
    String accountCredentials = (String) getCredentials(info);  
    //將密碼加密與系統加密後的密碼校驗,內容一致就返回true,不一致就返回false  
    return SystemContext.passwdDecryption(rawPasswd, accountCredentials);  
    }  
}

6:自定義的filter,roles[]知足其中一個角色便可,新建CustomRolesAuthorizationFilter.java緩存

public class CustomRolesAuthorizationFilter extends AuthorizationFilter {

	@Override
	protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
		Subject subject = getSubject(request, response);  
        String[] rolesArray = (String[]) mappedValue;  

        if (rolesArray == null || rolesArray.length == 0) //沒有角色限制,有權限訪問
        {  
            return true;  
        }  
        for(int i=0;i<rolesArray.length;i++)
        {
            if(subject.hasRole(rolesArray[i]))////若當前用戶是rolesArray中的任何一個,則有權限訪問
            {  
                return true;  
            }  
        }  
        return false; 
	}

}

7.修改LoginAction.java登陸的方法session

public String webLogin() {
		// 獲取用戶傳過來的驗證�?
		String passCode = (String) getRequest().getParameter("passCode");
		// 獲取系統生成的驗證碼
		String securityCode = (String) (getRequest().getSession().getAttribute("securityCode"));
		// 驗證碼校驗,不正確直接返�?
		if (passCode!=null&&securityCode!=null&&passCode.equals(securityCode)) {
			//獲取認證對象的包裝對象
			Subject subject = SecurityUtils.getSubject();
			//獲取頁面的用戶名跟密碼進行校驗
			AuthenticationToken authenticationtoken = new UsernamePasswordToken(sysUser.getUserId(), sysUser.getPwd());
			String ip = ServletActionContext.getRequest().getRemoteAddr(); //獲取用戶登陸IP
			sysOperateRecord.setOperateIp(ip);
			try{
				subject.login(authenticationtoken);
				// 獲取用戶名,並把用戶名存入session
				String userName = sysUser.getUserId();
				getRequest().getSession().setAttribute("userName", userName);
				// 把用戶對象放到session當中
				sysUser = sysUserService.findByUserId(sysUser.getUserId());
				ActionContext.getContext().getSession().put("sysUser", sysUser);
				//將用戶登陸信息放到用戶登陸記錄對象中
				sysOperateRecord.setOperateContent("登陸成功");
				//operateType表示日誌類型:1表示登陸,2表示其它
				sysOperateRecord.setOperateType(1);
				sysOperateRecord.setOperateIp(ip);
				sysOperateRecord.setUserId(sysUser.getUserId());
				sysOperateRecord.setUserName(sysUser.getFullname());
				sysOperateRecord.setOperateTime(new Timestamp(System.currentTimeMillis()));
				//將用戶登陸記錄存放到用戶登陸記錄表中
				sysOperateRecordService.add(sysOperateRecord);
				// System.out.println("登錄成功-------------------");
				forwardView = INDEX_JSP;
			}catch(UnknownAccountException e){
				//用戶名不存在
				 forwardView = LOGIN_JSP;
				//將用戶登陸信息放到用戶登陸記錄對象中
				sysOperateRecord.setOperateContent("用戶名不存在,登陸失敗");
				//operateType表示日誌類型:1表示登陸,2表示其它
				sysOperateRecord.setOperateType(1);
				sysOperateRecord.setOperateIp(ip);
				sysOperateRecord.setUserId(sysUser.getUserId());
				sysOperateRecord.setUserName(sysUser.getFullname());
				sysOperateRecord.setOperateTime(new Timestamp(System.currentTimeMillis()));
				//將用戶登陸記錄存放到用戶登陸記錄表中
				sysOperateRecordService.add(sysOperateRecord);
			}catch (IncorrectCredentialsException e) {
				//密碼錯誤
				forwardView = LOGIN_JSP;
				//將用戶登陸信息放到用戶登陸記錄對象中
				sysOperateRecord.setOperateContent("密碼錯誤,登陸失敗");
				//operateType表示日誌類型:1表示登陸,2表示其它
				sysOperateRecord.setOperateType(1);
				sysOperateRecord.setOperateIp(ip);
				sysOperateRecord.setUserId(sysUser.getUserId());
				sysOperateRecord.setUserName(sysUser.getFullname());
				sysOperateRecord.setOperateTime(new Timestamp(System.currentTimeMillis()));
				//將用戶登陸記錄存放到用戶登陸記錄表中
				sysOperateRecordService.add(sysOperateRecord);
			}catch (AuthenticationException e) {
                //認證失敗
                e.printStackTrace();
                forwardView = LOGIN_JSP;
				// System.out.println("登錄失敗-------------------");
				//將用戶登陸信息放到用戶登陸記錄對象中
				sysOperateRecord.setOperateContent("用戶名或密碼錯誤,登陸失敗");
				//operateType表示日誌類型:1表示登陸,2表示其它
				sysOperateRecord.setOperateType(1);
				sysOperateRecord.setOperateIp(ip);
				sysOperateRecord.setUserId(sysUser.getUserId());
				sysOperateRecord.setUserName(sysUser.getFullname());
				sysOperateRecord.setOperateTime(new Timestamp(System.currentTimeMillis()));
				//將用戶登陸記錄存放到用戶登陸記錄表中
				sysOperateRecordService.add(sysOperateRecord);
			}
		} else {
			// 若是驗證碼錯誤,返回用戶名和密碼,用戶不用再次輸入
			inputPassword = sysUser.getPwd();
			inputUserName = sysUser.getUserId();
			forwardView = LOGIN_JSP;
			// System.out.println("驗證碼失敗-------------------");
		}
		return SUCCESS;
	}

8:在主頁面使用標籤控制權限app

在頭部引入shiro標籤庫
<!-- shiro頭引入 -->
<%@ taglib uri="http://shiro.apache.org/tags" prefix="shiro"%>

<shiro:hasPermission name="userManagement">
    擁有userManagement權限的可見
</shiro:hasPermission>
相關文章
相關標籤/搜索