SpringMVC+Cookie+Session實現自動登錄

實現自動登錄其實並不是特別的困難,下面來介紹我所實現的自動登錄的一種方式,首先,必須提到Cookie和Session,Cookie是保存在客戶端的而Session是保存在服務端的,每次客戶端通過遊覽器訪問服務端的時候,會有一個JSESSIONID作爲key值保存在Cookie中,服務端就這樣區分每一個客戶端的Session,在自動登錄的時候,Cookie保存了用戶名(自動保存JSESSIONID),然後在Session保存了有關於用戶的一些登錄信息,比如用戶名、密碼、登錄時間啥的。自動登錄的過程中涉及三個主要的方法(login、logout、autoLogin)以及兩個jsp頁面(index.jsp、login.jsp),下面直接給出代碼!!

1.index.jsp

<%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
    response.sendRedirect(basePath+"logincookie");
%>
注:這是index.jsp頁面的核心,讓進index頁面的用戶自動發送一個請求到自動登錄方法裏邊

2.login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<html>
<body>
<h2>Hello World!</h2>
<div style="align-content: center;">
    <form action="/login" method="post" >
        <input type="text" name="username" value="${user.username}"><br>
        <input type="text" name="password" value="${user.password}"><br>
        <input type="submit" value="點擊">
    </form>
</div>
</body>
</html>
3.autoLogin Method
@RequestMapping("/logincookie")
    public String autoLogin(HttpServletRequest request,HttpServletResponse response){
        System.out.println("進入了自動登錄的Controller!");
        Cookie[] cookies = request.getCookies();
        if(cookies==null){
            return "redirect:login";
        }
        HttpSession session = request.getSession(false);
        String sessionId = session.getId();

        for(Cookie cookie:cookies){
            if (cookie.getName().equals("JSESSIONID")) {
                if(!cookie.getValue().equals(sessionId)){
                    return "redirect:login";
                }
            }
        }

        for (Cookie cookie2:cookies){
            if(cookie2.getName().equals("username")&&cookie2.getValue()!=null){
                String cookieUsername = cookie2.getValue();
                try{
                    String realPassword = userService.getUserByUsername(cookieUsername).getPassword();
                    if (session.getAttribute("password").equals(realPassword)){
                        return "welcome";
                    }else{
                        return "redirect:login.jsp";
                    }

                }catch (NullPointerException e){
                    return "redirect:login.jsp";
                }

            }
        }

        return "redirect:login.jsp";
    }
注:這個意思也就是說,每次到index頁面的時候首先是跳入到這個方法裏邊,通過這個方法判斷cookie和session中保存的相關數據是否正確,如果正確的話就跳入到登錄成功頁面,不正確或者cookie、session失效的話就跳入login頁面。

4.login Method

@RequestMapping("/login")
    public String login(HttpServletRequest request,String username, String password, HttpServletResponse response){
         if(username.equals("admin") && password.equals("admin")){

             HttpSession session = request.getSession();
             session.setAttribute("username",username);
             session.setAttribute("password",password);

            Cookie usernameCookie = new Cookie("username",username);
            usernameCookie.setMaxAge(500);
            usernameCookie.setPath("/");
            response.addCookie(usernameCookie);

            Cookie[] cookies = request.getCookies();
            System.out.println("外部的SessionId:"+session.getId());
            for (Cookie cookie:cookies){
                if(cookie.getName().equals("JSESSIONID")){
                    System.out.println("Cookie裏邊的:"+session.getId());
                    cookie.setValue(session.getId());
                    cookie.setPath("/");
                    cookie.setMaxAge(500);
                    response.addCookie(cookie);
                }
            }
         }
        return "welcome";
    }
5.logout Method

@RequestMapping("/logout")
    public String logout(HttpServletRequest request,HttpServletResponse response){
        //刪除cookie
        Cookie usernameCookie = new Cookie("usernmae","");
        usernameCookie.setMaxAge(0);
        usernameCookie.setPath("/");
        response.addCookie(usernameCookie);
        request.getSession().removeAttribute("username");
        request.getSession().removeAttribute("password");
        return "redirect:login.jsp";
    }
其餘剩下的service層和dao層的代碼我就不給出了,很簡單無非是一些查詢!自動登錄有很多種實現方法,除了用cookie還可以用一種url傳遞jsessionid的方式,這種情況是在遊覽器禁用cookie可以使用的,其實沒有太大的區別,記住賬號密碼功能的實現也是類似的過程,無非是把保存在session或者cookie中的用戶信息,還原到輸入框當中,具體我這樣寫合不合規範我也不太清楚,至少功能原理上我算是摸了個八成熟!

----------------------------------------------------------------------------------------------------------------------------------分割線,上邊的內容是通過請求重定向到一個Controller中來完成自動登錄的驗證,然而實際上我們最好用SpringMVC的攔截器來做自動登錄的這個驗證,這裏Cookie存儲的是username,Session保存了一個User(用戶登錄的對象),下邊直接上代碼:

1.在springmvc.xml配置攔截器:

<mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/welcomepage"/>
            <bean class="com.demo.AuthorizedInterceptor.AuthorizedInterceptor"/>
        </mvc:interceptor>
    </mvc:interceptors>
2.創建一個java攔截器類,實現HandlerInterceptor接口:

package com.demo.AuthorizedInterceptor;

import com.demo.pojo.User;
import com.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

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

public class AuthorizedInterceptor implements HandlerInterceptor {

    @Autowired
    private UserService userService;

    /**
     * preHandle方法是進行處理器攔截用的,顧名思義,該方法在Controller處理之前進行調用,SpringMVC中的Interceptor攔截器是鏈式的,可以同時存在,
     多個Interceptor,然後SpringMVC會根據聲明的順序一個接一個的執行,而且所有的Interceptor中的preHandler方法都會在Controller方法之前調用
     如果返回的是false的話就能夠中斷這個請求
     * @param request
     * @param response
     * @param o
     * @return
     * @throws Exception
     */
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {
        System.out.println("進入了preHandle方法!!!!");
        //先從session拿取用戶
        Cookie[] cookies = request.getCookies();
        if(cookies==null){
            response.sendRedirect("redirect:login");
        }
        HttpSession session = request.getSession(false);
        String sessionId = session.getId();

        for(Cookie cookie:cookies){
            if (cookie.getName().equals("JSESSIONID")) {
                if(!cookie.getValue().equals(sessionId)){
                    response.sendRedirect("redirect:login");
                }
            }
        }

        for (Cookie cookie2:cookies){
            if(cookie2.getName().equals("username")&&cookie2.getValue()!=null){
                String cookieUsername = cookie2.getValue();
                try{
                    String realPassword = userService.getUserByUsername(cookieUsername).getPassword();
                    User user = (User) session.getAttribute("user");
                    if (user.getPassword().equals(realPassword)){
                        response.sendRedirect("redirect:welcome");
                    }else{
                        response.sendRedirect("redirect:login");
                    }
                }catch (NullPointerException e){
                    response.sendRedirect("redirect:login");
                }

            }
        }
        return true;

    }

    /**
     *這個方法只會在當前的這個Interceptor的preHandler方法返回值爲true的時候才執行。
     postHandler是進行處理器攔截用的。它的執行時間實在處理器進行處理之後,也就是在Controller
     的方法調用之後執行,但是他會在DispatcherServler進行視圖渲染之前執行,也就是說在這個方法中,
     你可以對返回的ModelAndView進行操作。
     *這個方法的鏈式結構跟正常訪問的方向是相反的,也就是說先聲明的Interceptor攔截器該方法反而會後調用,
     這裏與struts2裏面的攔截器的執行過程有點像。
     *只是struts2裏面的intercept方法中要手動調用的ActionInvocation的invoke方法,Struts2中調用
     ActionInvocation的invoke方法就是調用下一個Inteceptor或者是調用actio,然後在Interceptor之前
     調用的內容都寫在invoke之前,要在Interceptor之後調用的都卸載invoke方法之後
     *
     * @param httpServletRequest
     * @param httpServletResponse
     * @param o
     * @param modelAndView
     * @throws Exception
     */
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
        System.out.println("進入了postHandle方法!!!!");
    }

    /**
     *這個方法需要preHandler方法的返回值是true的時候纔會執行。該方法將整個請求完成之後
     * 也就是DispatcherServlet渲染了視圖才執行
     * 這個方法的主要用途是用於清理資源的,當然這個方法也只能在當前這個Interceptor的preHandler方法的返回值
     * 是true的時候纔會執行
     * @param httpServletRequest
     * @param httpServletResponse
     * @param o
     * @param e
     * @throws Exception
     */
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
        System.out.println("進入了afterCompletion方法!!!!");
    }
}
剩下的代碼就不給出了,與上邊的雷同!包括記住密碼和自動登錄多少天都是類似的無非是加上時間什麼的。下次會給出用Shiro實現自動登錄效果的代碼!



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章