1. 程式人生 > >shiro自定義過濾器

shiro自定義過濾器

就是自定義過濾規則 一些特殊的請求路徑 需要進過自定義的過濾器 在自定義的過濾器中 認證規則是自己定的
spring檔案:
		<!-- 引入資料來源 -->
		<context:property-placeholder location="classpath:db.properties"/>
		<!-- 配置資料庫連線池 -->
		<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
		destroy-method="close">
		<property name="driverClassName" value="${jdbc.driver}" />
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />
		<property name="maxActive" value="10" />
		<property name="maxIdle" value="5" />
		</bean>
		
		<!-- 自定義的shiro 過濾器 -->
		<bean id="phoneFilter" class="cn.neusoft.filter.UserPhoneFilter">
			<property name="userdao" ref="userDao"></property>
		</bean>	
		
		<!-- Shiro的過濾器工廠BEAN : 間接地載入9個內建過濾器  -->
		<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">		
			<!-- 安全管理器 :Shiro的核心元件,相當於大腦  -->
			<property name="securityManager" ref="securityManager" />		
			<!-- 認證相關: 指定登陸頁面,當用戶未登陸時訪問資源,則自動跳轉到此頁面   -->
			<property name="loginUrl" value="/login.jsp" /> 
			<!-- 授權相關:指定錯誤頁面,當用戶登陸後訪問沒有許可權的資源時,自動跳轉到此頁面 -->
			<property name="unauthorizedUrl" value="/error.html" /> 
			
			<property name="filters">
					<map>
						<entry key="phone" value-ref="phoneFilter" />
					</map>
			</property>
			
			<!-- 過濾器鏈定義:指定頁面的訪問規則 -->
			<property name="filterChainDefinitions">
				<value>	
						/userphone/login.action =anon
						/user/login.action = anon
						/login.jsp =anon
						/user/all.action = authc
						<!-- 新增的許可權 -->
						/user/goadd.action =perms["add"]
						/user/add.action =perms["add"]
						<!-- 修改的許可權 -->
						/user/goedit.action =perms["update"]
						/user/update.action =perms["update"]
						<!-- 刪除的許可權 -->
						/user/delete.action =perms["delete"]
						/userphone/* =phone
						/userphone/select.action =authc
						/userphone/add.action=perms["add"]
						/userphone/update.action =perms["update"]
						/userphone/delete.action =perms["delete"]
						/*.html = authc					
						/*.action = authc
						/* = authc
				</value>
			</property>
				
		</bean>
		<!-- 安全管理器 -->
		<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
			<property name="realm" ref="userRealm"></property>
		</bean>
		
		
		<!-- 自定義Realm -->
		<bean id="userRealm" class="cn.neusoft.realm.UserRealm">
			<property name="userService" ref="userService"></property>
			<property name="user" ref="user"></property>
		</bean>
</beans>



我們自定義了一個phoneFilter 在過濾器鏈中匹配到時 就會到該過濾器中執行
public class UserPhoneFilter extends AuthenticationFilter{
    
    private UserDao userdao;
    public void setUserdao(UserDao userdao) {
        this.userdao = userdao;
    }

    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json; charset=utf-8"); 
        
        String sessionid = request.getParameter("sessionid");
        //1.沒有sessionid    2.有sessionid  資料庫沒資料    3.有sessionid 資料庫有資料  沒有使用者    4.有使用者   沒許可權執行
        
        //判斷sessionid是否存在    如不存在返回路徑錯誤
        if(sessionid.equals("")){
            Map map = jsonReturn(false,"沒有登入記錄,請重新登陸");
            try {
                response.getWriter().print(JSON.toJSONString(map));
                return false;
            } catch (IOException e) {
                
                e.printStackTrace();
            }
        }
        
        PhoneId phoneId = userdao.getsession(sessionid);
        if(phoneId==null){
          //如果sessionid存在    資料庫沒查到    返回身份過期
            Map map = jsonReturn(false,"登入資訊過期,請重新登入");
            try {
             response.getWriter().print(JSON.toJSONString(map));
             return false;
         } catch (IOException e) {
             e.printStackTrace();
         }
        }
        //資料庫中根據sessionid取登陸物件
       
        
       //不為空  從資料庫查到當前登陸物件
       User user = userdao.selectone(phoneId.getUid().toString());
       if(user==null){
           //通過使用者ID查不到  可能已刪除
           Map map = jsonReturn(false,"使用者資訊有問題,請重新登陸");
           try {
            response.getWriter().print(JSON.toJSONString(map));
            return false;
        } catch (IOException e) {
            e.printStackTrace();
        }
       }
       
        //------------------------------------------------------------------------------
        Subject subject = getSubject(request, response);
        UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(),user.getPassword());
        subject.login(token);
        //------------------------------------------------------------------------------
        String path = getPathWithinApplication(request);
        String string = path.substring(11, path.length());
        String caozuo = string.substring(0, string.indexOf("."));
        //------------------------------------------------------------------------------
        System.out.println(caozuo);
        System.out.println("第二過濾器!!");
        //物件也從資料庫查到了   出錯的唯一可能就是當前物件沒有許可權執行
        	if(subject.isPermitted(caozuo)){
        		return true;
        	}else{
        		Map map = jsonReturn(false,"該使用者沒有許可權執行當前資源");
        		try {
					response.getWriter().print(JSON.toJSONString(map));
				} catch (IOException e) {
				}
        		
        		return false;
        	}
	}
        
        
        

    //isAccessAllowed 方法返回false 執行
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse reponse) throws Exception {
       System.out.println("沒成功!!!!!!!!!");
       return false;
    }
    
    public Map jsonReturn(boolean type,String message){
        Map map = new HashMap<Boolean, String>();
        map.put("success", type);
        map.put("value", message);
        return map;
    }
}



在自定義的過濾器中 有兩個方法會先執行isAccessAllowed()方法 這個方法中如果放回false才會執行onAccessDenied() 如果放回true的話程式就會無條件執行 我們一般在isAccessAllowed()方法中執行授權 方法 subject.isPermitted(caozuo) 這個方法會執行授權方法執行成功的話放回true 執行失敗的話放回false 執行onAccessDenied()方法