实现自动登录其实并不是特别的困难,下面来介绍我所实现的自动登录的一种方式,首先,必须提到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+"/";
%>
Hello World!
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配置拦截器:
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实现自动登录效果的代码!