1. 程式人生 > >關於登入許可權的設定--用過濾器解決的方法

關於登入許可權的設定--用過濾器解決的方法

需求:在專案開發中,按照正常的思路:使用者必須登入了才能進入到後臺,如何知道後臺的地址而直接訪問後臺,那麼該專案可以說是非常的差勁了。由於開發需要,我這幾天學習和解決了這個問題。現在分享出現,希望能給大家帶來幫助!()

1、寫SessionFilter (自定義)過濾器,要實現Filter介面

import java.io.IOException;
import java.util.regex.Pattern;
import java.net.URLEncoder;
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 org.apache.commons.lang.StringUtils;

public class SessionFilter implements Filter{

   /**要檢查的 session 的名稱 */
   private String sessionKey;
    
   /**需要排除(不攔截)的URL的正則表示式 */
   private Pattern excepUrlPattern;
    
   /**檢查不通過時,轉發的URL */
   private String forwardUrl;

   public void init(FilterConfig cfg) throws ServletException{
       System.out.println("SessionFilter的啟動");
       sessionKey= cfg.getInitParameter("sessionKey");
       String excepUrlRegex = cfg.getInitParameter("excepUrlRegex");
       if (!StringUtils.isBlank(excepUrlRegex)){
           excepUrlPattern= Pattern.compile(excepUrlRegex);
       }
       forwardUrl= cfg.getInitParameter("forwardUrl");
   }

   public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,
       ServletException {
       System.out.println("執行SessionFilter過濾");
       //如果 sessionKey 為空,則直接放行(個人覺得在此這個判斷條件沒有用)
       if (StringUtils.isBlank(sessionKey)){
           chain.doFilter(req,res);
           return;
       }

        /* 請求 http://127.0.0.1:8080/sm/index.jsp?&a=1&b=2 時
         * request.getRequestURL(): http://127.0.0.1:8080/sm/index.jsp
         * request.getContextPath(): /sm 
         * request.getServletPath():/index.jsp
         * request.getRequestURI(): /sm/index.jsp
         * request.getQueryString():a=1&b=2
         */
       HttpServletRequest request = (HttpServletRequest) req;
       HttpServletResponse response = (HttpServletResponse) res;
       String servletPath = request.getServletPath();
       System.out.println("servletPath="+servletPath);
       //如果請求的路徑與forwardUrl相同,或請求的路徑是排除的URL時,則直接放行
       if (servletPath.equals(forwardUrl)|| 
               excepUrlPattern.matcher(servletPath).matches()) {
           chain.doFilter(req,res);
           return;
       }

  //注意:adminName為使用者登入名,必須在登入資訊傳到後臺時放到Session

  //裡,我的專案在@Controller的登入使用者傳到後臺時當判斷使用者名稱和密碼正確

  //後立馬到Session裡,作用是用來判斷Session如果還有效,返回不為空,可以在後臺繼續操作;如果超時
  //了,返回null,則跳到登入頁面

       Object sessionObj = request.getSession().getAttribute("adminName");
       System.out.println("sessionObj="+sessionObj);
       //如果Session為空,則跳轉到指定頁面
       if (sessionObj== null){
           String contextPath = request.getContextPath();
           String redirect = servletPath + "?" +StringUtils.defaultString(request.getQueryString());
           System.out.println("contextPath="+contextPath+",redirect="+redirect);
           response.sendRedirect(contextPath+ StringUtils.defaultIfEmpty(forwardUrl, "/")
                           +"?redirect=" +URLEncoder.encode(redirect, "UTF-8"));
       }else {
           chain.doFilter(req,res);
       }
   }

   public void destroy(){
       System.out.println("SessionFilter的銷燬");
   }
}

文字有一處要注意:即

 Object sessionObj = request.getSession().getAttribute("adminName");

中的“adminName”要在後臺有設定,否則不起作用,比如我在Controller中這樣設定

2、在web.xml中配置如下過濾器資訊(重點在如何哪些需要攔截,哪些不需要攔截)

<!-- 檢查使用者是否登入了系統的過濾器配置 開始 -->
	<filter>
		<filter-name>SessionFilter</filter-name>
		<filter-class>com.py.util.wrb.SessionFilter</filter-class>
		<init-param>
			<description>
			將當前登入的使用者的資訊儲存在session 中時使用的key,如果沒有配置此引數,則該過濾器不起作用
			</description>
			<param-name>sessionKey</param-name>
			<param-value>adminName</param-value>
		</init-param>
		<init-param>
			<description>
			 如果使用者未登入(即在session 中 key 為 sessionKey 的屬性不存在或為空),則將請求重定向到該 url。
			 該url 不包含web應用的 ContextPath。如果不配置此引數,則在使用者未登入系統的情況下,
			 直接重定向到web應用的根路徑(/)
     		</description>
			<param-name>forwardUrl</param-name>
			<param-value>/index.jsp</param-value>
		</init-param>
		<init-param>
			<description>
         	  不需要進行攔截的url 的正則表示式,即:如果當前請求的 url 的 servletPath 能匹配該正則表示式,則直接放行(即使未登入系統)。
        	  此引數的值一般為loginServlet 和 registServlet 等。另外,引數redirectUrl 的值不用包含在該正則表示式中,因為 redirectUrl 對應的 url 會被自動放行。
       		  還有一點需要說明的是,該引數的值不包含web應用的ContextPath。
     		</description>
			<param-name>excepUrlRegex</param-name>
			<!-- 不需要攔截的路徑 
				(login_login_execute|login_2_login).do
                會在後面有詳細的解釋
			-->
			<param-value>/(jumpIndex|loginAdmin)</param-value>
		</init-param>
	</filter>
<!-- /* 表示所有的都要進行過濾-->
	<filter-mapping>
		<filter-name>SessionFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

耐心講解:打個比方,如果你登入你的系統要輸入這樣的地址進入登入介面:

http://127.0.0.1:8080/sm/index.jsp

那麼forwardUrl應該是這樣寫,程式碼頁面的登入頁面(forwardUrl可自定義名稱,當然要見詞知意最好,下同)

<param-name>forwardUrl</param-name>
<param-value>/index.jsp</param-value>

在一個系統中,我們一般把登入頁面放在web-inf的外面,否則直接訪問不了(個人見解),為了起到保護作用,我們在登入頁面點選登入,要做一些路徑跳轉,有多個跳轉就有多少個路徑,直到後臺的主介面,這些路徑也必須不能攔截,否則你登入不到後臺。如下,這裡說明登入到後臺要經過jumpIndex和loginAdmin路徑,“|”代表“或”。

<description>
         	  不需要進行攔截的url 的正則表示式,即:如果當前請求的 url 的 servletPath 能匹配該正
                則表示式,則直接放行(即使未登入系統)。
        	  此引數的值一般為loginServlet 和 registServlet 等。另外,引數redirectUrl 的值不用
              包含在該正則表示式中,因為 redirectUrl 對應的 url 會被自動放行。
       		  還有一點需要說明的是,該引數的值不包含web應用的ContextPath。
</description>
<param-name>excepUrlRegex</param-name>
<param-value>/(jumpIndex|loginAdmin)</param-value>

3、為了方便測試,最好設定Session的有效時間短一點,如何設定Session有效時間百度有一大堆,我是在web.xml重配置的,如:我設定有效時間為1分鐘

<session-config>
		<session-timeout>1</session-timeout>
</session-config>

這樣可以在Session失效後直接登入後臺看是否進得去

看是否能進入。進不去,說明過濾器起作用了。

至此完成,有什麼問題可以留言,我會及時回覆!後面我會繼續完善這篇文章,希望各位能給點指點,謝謝!

宣告:我通過百度上找很多資料,結合自己專案做的,我希望能對很多菜鳥有所幫助。