實現自動登錄其實並不是特別的困難,下面來介紹我所實現的自動登錄的一種方式,首先,必須提到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實現自動登錄效果的代碼!