欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

SpringMVC+Cookie+Session实现自动登录

程序员文章站 2022-05-28 15:53:11
...

实现自动登录其实并不是特别的困难,下面来介绍我所实现的自动登录的一种方式,首先,必须提到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实现自动登录效果的代码!