1. 程式人生 > >基於SSH實現員工管理系統登入許可權的過濾器與攔截器的綜合使用

基於SSH實現員工管理系統登入許可權的過濾器與攔截器的綜合使用

需要實現的功能:判斷使用者是否已登入,未登入使用者禁止訪問任何頁面或action,自動跳轉到登入頁面。

過程很艱辛,雖然是挺簡單的應用,但是自己也弄了好久才有些許弄明白,結合網上搜索到的內容寫下這篇總結,待日後可回頭檢視。
剛開始是先搜了攔截器如何攔截未登入使用者的操作的,正是初生牛犢不怕虎,找到一篇文章就死懟,懟到後面發現不大對,雖然action是攔截掉了,但是jsp怎麼樣都攔截不到,直接輸入.jsp的url還是能訪問到網頁。苦思冥想,想不出如何做才行。後面發現攔截器本就不能攔截jsp頁面、圖片等其他資源,攔截器由spring管理,只對action起作用。
於是搜尋過濾器的內容,發現過濾器則能過濾所有內容,過濾器的範圍要大於攔截器。那就把兩者結合起來用吧,反正攔截器已寫好,只需寫過濾jsp頁面的過濾器即可。

過濾器filter實現:
配置web.xml

<filter>
        <filter-name>LoginFilter</filter-name>
        <filter-class>xu.ssh.filter.LoginFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>LoginFilter</filter-name>
        <url-pattern>*.jsp</url-pattern>
    </filter
-mapping>

程式碼:

package xu.ssh.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import
javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import xu.ssh.domain.Employee; public class LoginFilter implements Filter { @Override public void destroy() { // TODO Auto-generated method stub } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // 獲得在下面程式碼中要用的request,response,session物件 HttpServletRequest servletRequest = (HttpServletRequest) request; HttpServletResponse servletResponse = (HttpServletResponse) response; HttpSession session = servletRequest.getSession(); // 獲得使用者請求的URI String path = servletRequest.getRequestURI(); // System.out.println(path); // 從session裡取員工工號資訊 Employee employee = (Employee) session.getAttribute("existEmployee"); /* * 建立類Constants.java,裡面寫的是無需過濾的頁面 for (int i = 0; i < * Constants.NoFilter_Pages.length; i++) { if * (path.indexOf(Constants.NoFilter_Pages[i]) > -1) { * chain.doFilter(servletRequest, servletResponse); return; } } */ // 登陸頁面無需過濾 if (path.indexOf("/login.jsp") > -1) { chain.doFilter(servletRequest, servletResponse); return; } // 判斷如果沒有取到員工資訊,就跳轉到登陸頁面 if ("".equals(employee) || employee == null) { // 跳轉到登陸頁面 servletResponse.sendRedirect("/ssh_employee/login.jsp"); } else { // 已經登陸,繼續此次請求 chain.doFilter(request, response); } } @Override public void init(FilterConfig arg0) throws ServletException { // TODO Auto-generated method stub } }

配置中的filter-mapping,定義的是需過濾的請求型別,上面的配置即過濾所有對jsp頁面的請求。過濾器的實現與struts2、spring框架無關,在使用者請求被相應前執行,在過濾器中,可使用response.sendRedirect(“”)等方法
跳轉到需要的連結,如登入頁面、錯誤頁面等,不需要跳轉時,chain.doFilter(request, response);即可繼續執行使用者的請求。注意使用filter時避免連續兩次跳轉,否則會報java.lang.IllegalStateException錯誤,除非必要,不建議使用/*(過濾所有訪問)的配置方式,這樣配置,圖片、js檔案、css檔案等訪問都會被過濾

攔截器interceptor實現:
配置:struts.xml

<!-- 攔截器 --> 
        <interceptors>
            <interceptor name="myInterceptor" class="xu.ssh.action.MyInterceptor"></interceptor>
            <interceptor-stack name="myInterceptor">
                <interceptor-ref name="myInterceptor">
                    <param name="excludeMethods">login</param><!-- 不攔截的方法-->
                </interceptor-ref>
                <interceptor-ref name="defaultStack"></interceptor-ref>
            </interceptor-stack>
        </interceptors>
        <!-- 將上述攔截器設定為預設攔截器 ,這樣在後續同一個package內部的所有Action執行之前都會被login攔截。-->
        <default-interceptor-ref name="myInterceptor" /> 

程式碼:

package xu.ssh.action;

import org.apache.struts2.ServletActionContext;

import xu.ssh.domain.Employee;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;

public class MyInterceptor extends MethodFilterInterceptor{

    /**
     * @param args
     */

    @Override
    protected String doIntercept(ActionInvocation actionInvocation) throws Exception {

        Employee employee = (Employee) ServletActionContext.getRequest().getSession().getAttribute("existEmployee");

        if(employee!=null){
            // is logined ,have the userinfo in the session  
            return actionInvocation.invoke();//遞迴呼叫攔截器
        }else{
            //is not logged
            ActionSupport support = (ActionSupport) actionInvocation.getAction();
            support.addActionError("請先登入:)");
            return "loginfail";//返回到登入頁面
        }

    }

}

攔截器截獲使用者對action的訪問,如需要跳轉,只需如action一樣返回一個result,spring根據result的配置執行跳轉。如無需跳轉,可呼叫invocation.invoke();方法來執行使用者請求的action。攔截器在action之前開始,在action完成後結束(如被攔截,action根本不執行)

參考部落格
參考文件