1. 程式人生 > >SpringMVC攔截器實現登入認證(2017修正版)

SpringMVC攔截器實現登入認證(2017修正版)

     當使用到springmvc的做網頁工程的時候,總會遇到需要判斷登陸許可權的,一般的做法是每次登陸的話,傳送給後臺,後臺返回一個唯一的token,以便標識使用者每一次請求的許可權,如果沒有登陸成功,則token為空,訪問任意網址都會跳到登陸介面,所以網上查了,有很多部落格說了,例如這位前輩:http://blog.csdn.net/u014427391/article/details/51419521,我的基本程式碼都是參考它的。

      注意: 不過我發現了網上所有的登陸許可權認證,都忽略了一個問題,如果你的專案中有js/css等其他程式碼的話,是會都攔截到,就會一直陷入死迴圈中,導致無法進入主介面,需要把這些js和css等介面的所需的檔案,也進行判斷才能順利攔截。

(還有訪問登陸介面的路徑、點選登陸按鈕訪問後臺的路徑,都需要判斷),其他的路徑的話,如果沒有token就返回主介面:

            

       所以攔截器需要按照如下方式寫,程式碼如下:(具體攔截那些路徑,可以根據自己專案的js/css/image資源的路徑配置)

package com.rmsClient.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.rmsClient.util.Constants;

/**
 * 登陸許可權:攔截器
 * 
 * @author qiulinhe
 *
 *         2017年1月18日 下午2:40:36
 */
public class LoginInterceptor implements HandlerInterceptor {

	/**
	 * Handler執行之前呼叫這個方法
	 */
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		// 獲取請求的URL
		String url = request.getRequestURI();

		// 注意:一些靜態檔案不能攔截,否則會死迴圈,知道記憶體耗盡
		// URL:login.jsp是公開的;這個demo是除了login.jsp是可以公開訪問的,其它的URL都進行攔截控制
		// /RMSClient/WEB-INF/view/register/login.html
		// 地址為/RMSClient/media/js/lib/jquery-1.7.2.min.js
		// 地址為/RMSClient/media/css/base.css
		// 地址為/RMSClient/media/css/login.css
		// 地址為/RMSClient/media/js/lib/html5shiv.js
		// 地址為/RMSClient/media/js/server/login.js
		if (url.indexOf("/RMSClient/login") >= 0 || url.indexOf("/register/login.html") > 0
				|| url.indexOf("/media") > 0 || url.indexOf("/user/login") > 0) {
			return true;
		}
		// 獲取Session,判斷是否能拿到token,如果沒有的話,就需要跳轉到主介面
		HttpSession session = request.getSession();

		String token = (String) session.getAttribute(Constants.TOKEN);
		System.out.println("得到的token為:" + token);
		if (token != null) {
			return true;
		}
		// 不符合條件的,跳轉到登入介面
		request.getRequestDispatcher("/WEB-INF/view/register/login.html").forward(request, response);

		// response.sendRedirect("/WEB-INF/view/register/login.html");

		return false;
	}

	/**
	 * Handler執行完成之後呼叫這個方法
	 */
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exc)
			throws Exception {

	}

	/**
	 * Handler執行之後,ModelAndView返回之前呼叫這個方法
	 */
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
	}

}

            其他的需要配置spring.xml裡面:
<?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:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-4.3.xsd 
       http://www.springframework.org/schema/context 
       http://www.springframework.org/schema/context/spring-context.xsd 
       http://www.springframework.org/schema/tx 
       http://www.springframework.org/schema/tx/spring-tx.xsd
          http://www.springframework.org/schema/mvc
       http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- 配置掃描的包 -->
    <context:component-scan base-package="com.rmsClient.*" />

    <!-- 註冊HandlerMapper、HandlerAdapter兩個對映類 -->
    <mvc:annotation-driven />

    <!-- 訪問靜態資源 -->
    <mvc:default-servlet-handler />
    
    <!-- 檢視解析器 -->
    <bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/view/"></property>
        <property name="suffix" value=".html"></property>
    </bean>
    
    <!-- 攔截器 -->
  <mvc:interceptors>
	<!-- 多個攔截器,順序執行 -->
	<mvc:interceptor>
		<mvc:mapping path="/**" />
		<!-- 登陸許可權攔截器 -->
		<bean class="com.rmsClient.interceptor.LoginInterceptor"></bean>
	</mvc:interceptor>
  </mvc:interceptors> 
    

</beans>

           自此就完成了登陸的驗證,希望後人少走彎路,還有網上的部落格前輩們總結的很好,不過還是需要自己摸索和實踐才行。

===========================分割線,2017年3月2日13:30:35====================

          上述的攔截有一個問題是,如果沒有登入許可權的,跳轉到登陸介面,我是直接訪問login.html的檔案,瀏覽器的地址並沒有更換成登陸的@RequestMapping(value = "/login"地址,所以需要重定向來解決,如下程式碼修改一下:

package com.rmsClient.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.rmsClient.util.Constants;
import com.rmsClient.util.LogUtil;

/**
 * 登陸許可權:攔截器
 * 
 * @author qiulinhe
 *
 *         2017年1月18日 下午2:40:36
 */
public class LoginInterceptor implements HandlerInterceptor {

	/**
	 * Handler執行之前呼叫這個方法
	 */
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		// 獲取請求的URL
		String url = request.getRequestURI();

		// 獲取Session,判斷是否能拿到token,如果沒有的話,就需要跳轉到主介面
		HttpSession session = request.getSession();
		String token = (String) session.getAttribute(Constants.TOKEN);

		// swagger的路徑也不需要攔截
		// 注意:一些靜態檔案不能攔截,否則會死迴圈,知道記憶體耗盡
		// URL:login.jsp是公開的;這個demo是除了login.jsp是可以公開訪問的,其它的URL都進行攔截控制
		// /RMSClient/WEB-INF/view/register/login.html
		// 地址為/RMSClient/media/js/lib/jquery-1.7.2.min.js
		// 地址為/RMSClient/media/css/base.css
		// 地址為/RMSClient/media/css/login.css
		// 地址為/RMSClient/media/js/lib/html5shiv.js
		// 地址為/RMSClient/media/js/server/login.js
		if (url.indexOf("/RMSClient/login") >= 0 || url.indexOf("/RMSClient/useradmin/login") >= 0
				|| url.indexOf("/register/login.html") >= 0 || url.indexOf("/swagger") >= 0
				|| url.indexOf("/media") >= 0 || url.indexOf("/user/login") >= 0
				|| url.indexOf("/RMSClient/WEB-INF/view/") >= 0 || url.indexOf("/RMSClient/view/") >= 0
				|| url.indexOf("/RMSClient/index") >= 0) {

			return true;
		} else if (url.indexOf("/RMSClient/main") >= 0) {
			if (token != null) {
				return true;

			} else {
				// 不符合條件的,跳轉到登入介面
				LogUtil.error("沒有登陸許可權,跳轉到登陸介面");
				response.sendRedirect(request.getContextPath() + "/login");//這是非常重要的重定向,需要加上全部路徑

				return false;
			}
		}

		if (token != null) {
			return true;

		}

		// 不符合條件的,跳轉到登入介面
		LogUtil.error("沒有登陸許可權,跳轉到登陸介面");
		// request.getRequestDispatcher("/WEB-INF/view/user/login.html").forward(request,
		// response);

		response.sendRedirect(request.getContextPath() + "/login");

		return false;
	}

	/**
	 * Handler執行完成之後呼叫這個方法
	 */
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception exc)
			throws Exception {

	}

	/**
	 * Handler執行之後,ModelAndView返回之前呼叫這個方法
	 */
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
	}

}