SpringMVC攔截器實現登入認證(2017修正版)
阿新 • • 發佈:2019-02-18
當使用到springmvc的做網頁工程的時候,總會遇到需要判斷登陸許可權的,一般的做法是每次登陸的話,傳送給後臺,後臺返回一個唯一的token,以便標識使用者每一次請求的許可權,如果沒有登陸成功,則token為空,訪問任意網址都會跳到登陸介面,所以網上查了,有很多部落格說了,例如這位前輩:http://blog.csdn.net/u014427391/article/details/51419521,我的基本程式碼都是參考它的。
注意: 不過我發現了網上所有的登陸許可權認證,都忽略了一個問題,如果你的專案中有js/css等其他程式碼的話,是會都攔截到,就會一直陷入死迴圈中,導致無法進入主介面,需要把這些js和css等介面的所需的檔案,也進行判斷才能順利攔截。
所以攔截器需要按照如下方式寫,程式碼如下:(具體攔截那些路徑,可以根據自己專案的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 {
}
}