攔截器的作用在於,比如我們輸入 xxx.com/admin 發起請求進入 網站后台或者其他后台頁面。我們的攔截器會在 Controller 調用之前進行攔截,至於什么攔截,由我們來寫。比如,判斷用戶是否登錄(可以通過 session 判斷),如果沒有登錄,我們讓它跳轉到登錄頁面。
轉載 https://liuyanzhao.com/6300.html
一、攔截器的基本使用
1、新建一個 攔截器
SecurityInterceptor.java
- package com.liuyanzhao.blog.Interceptor;
- import org.springframework.web.servlet.HandlerInterceptor;
- import org.springframework.web.servlet.ModelAndView;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- public class SecurityInterceptor implements HandlerInterceptor {
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
- System.out.println("SecurityInterceptor...preHandle...");
- //這里可以根據session的用戶來判斷角色的權限,根據權限來轉發不同的頁面
- if(request.getSession().getAttribute("userId") == null) {
- request.getRequestDispatcher("/login").forward(request,response);
- return false;
- }
- return true;
- }
- @Override
- public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
- }
- @Override
- public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
- }
- }
判斷是否有 userId 這個session,如果沒有(或者過期了)轉發到登錄頁面
2、配置 springmvc.xml
通過使用 mvc:interceptors 標簽來聲明需要加入到SpringMVC攔截器鏈中的攔截器。
- <mvc:interceptors>
- <mvc:interceptor>
- <mvc:mapping path="/admin"/>
- <bean class="com.liuyanzhao.blog.Interceptor.SecurityInterceptor"/>
- </mvc:interceptor>
- <mvc:interceptor>
- <mvc:mapping path="/admin/**"/>
- <bean class="com.liuyanzhao.blog.Interceptor.SecurityInterceptor"/>
- </mvc:interceptor>
- </mvc:interceptors>
只需兩步,我們已經能成功攔截 /admin 和其其前綴的如 /admin/article 等其他所有路徑啦。
二、登錄實現
登錄主要是驗證該用戶是否存在,密碼是否正確。然后添加 session 和頁面跳轉
1、登錄表單
login.jsp
- <%
- String username = "";
- String password = "";
- //獲取當前站點的所有Cookie
- Cookie[] cookies = request.getCookies();
- for (int i = 0; i < cookies.length; i++) {//對cookies中的數據進行遍歷,找到用戶名、密碼的數據
- if ("username".equals(cookies[i].getName())) {
- username = cookies[i].getValue();
- } else if ("password".equals(cookies[i].getName())) {
- password = cookies[i].getValue();
- }
- }
- %>
- <form name="loginForm" id="loginForm" method="post">
- <input type="text" name="username" id="user_login"
- class="input" value="<%=username%>" size="20" required/></label>
- <input type="password" name="password" id="user_pass"
- class="input" value="<%=password%>" size="20" required/>
- <input name="rememberme" type="checkbox" id="rememberme" value="1" /> 記住密碼
- <input type="button" name="wp-submit" id="submit-btn" class="button button-primary button-large" value="登錄" />
- </form>
為了代碼簡潔,這里去掉了多余的標簽和屬性。我這里是扒了 wordpress 的登錄頁面,這里也用到了 cookie 。
注意:這里的 form 表單里沒有 action 屬性,最終發送數據通過 ajax 。同樣,也沒有 submit 按鈕,為了防止 ajax+form+submit 導致 success 里無法頁面跳轉。
2、js 代碼
- <%--登錄驗證--%>
- $("#submit-btn").click(function () {
- var user = $("#user_login").val();
- var password = $("#user_pass").val();
- if(user=="") {
- alert("用戶名不可為空!");
- } else if(password==""){
- alert("密碼不可為空!");
- } else {
- $.ajax({
- async: false,//同步,待請求完畢后再執行后面的代碼
- type: "POST",
- url: '${pageContext.request.contextPath}/loginVerify',
- contentType: "application/x-www-form-urlencoded; charset=utf-8",
- data: $("#loginForm").serialize(),
- dataType: "json",
- success: function (data) {
- if(data.code==0) {
- alert(data.msg);
- } else {
- window.location.href="${pageContext.request.contextPath}/admin";
- }
- },
- error: function () {
- alert("數據獲取失敗")
- }
- })
- }
- })
這里 ajax 使用同步,防止出現后台沒有返回值,就執行了后面的js代碼,進而出現 ajax 執行 error:function() 里的代碼。數據類型使用 json,當然也可以使用 text,只不過 text 只能 返回普通的字符串。
最后,如果驗證通過,將跳轉到 xxx.com/admin 頁面(當然后台需要加入session,否則攔截器會攔截)。
3、控制器代碼
- //登錄頁面顯示
- @RequestMapping("/login")
- public ModelAndView loginView() {
- ModelAndView modelAndView = new ModelAndView();
- modelAndView.setViewName("/Admin/login");
- return modelAndView;
- }
- //登錄驗證
- @RequestMapping(value = "/loginVerify",method = RequestMethod.POST)
- @ResponseBody
- public String loginVerify(HttpServletRequest request, HttpServletResponse response) throws Exception {
- Map<String, Object> map = new HashMap<String, Object>();
- String username = request.getParameter("username");
- String password = request.getParameter("password");
- String rememberme = request.getParameter("rememberme");
- UserCustom userCustom = userService.getUserByNameOrEmail(username);
- if(userCustom==null) {
- map.put("code",0);
- map.put("msg","用戶名無效!");
- } else if(!userCustom.getUserPass().equals(password)) {
- map.put("code",0);
- map.put("msg","密碼錯誤!");
- } else {
- //登錄成功
- map.put("code",1);
- map.put("msg","");
- //添加session
- request.getSession().setAttribute("user", userCustom);
- //添加cookie
- if(rememberme!=null) {
- //創建兩個Cookie對象
- Cookie nameCookie = new Cookie("username", username);
- //設置Cookie的有效期為3天
- nameCookie.setMaxAge(60 * 60 * 24 * 3);
- Cookie pwdCookie = new Cookie("password", password);
- pwdCookie.setMaxAge(60 * 60 * 24 * 3);
- response.addCookie(nameCookie);
- response.addCookie(pwdCookie);
- }
- }
- String result = new JSONObject(map).toString();
- return result;
- }
這里登錄驗證方法內,getUserByNameOrEmail() 方法用來從數據庫里查找是否有該用戶(用戶名或者郵箱)。如果有,而且密碼正確,添加一條 session,要和攔截器里寫的一致哦。並將信息添加到 Map 中,然后轉成 JSON 數據,這里需要導入 對應JSON 的jar 哦。
- <dependency>
- <groupId>org.json</groupId>
- <artifactId>json</artifactId>
- <version>20170516</version>
- </dependency>
是
4、Service 和 DAO
這里就不貼 Service 和 Dao 的代碼了,主要就是根據 字符串查找用戶的操作啦。
三、注銷實現
注銷就比較簡單了,清除 session 就行了。
1、jsp 頁面
- <a href="${pageContext.request.contextPath}/admin/logout">退了</a>
2、控制器代碼
- //退出登錄
- @RequestMapping(value = "/admin/logout")
- public String logout(HttpSession session) throws Exception {
- session.removeAttribute("userId");
- session.invalidate();
- return "redirect:/login";
- }