SpringMVC+Cookie+Session實現自動登入
阿新 • • 發佈:2019-01-28
實現自動登入其實並不是特別的困難,下面來介紹我所實現的自動登入的一種方式,首先,必須提到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
3.autoLogin Method<%@ 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>
注:這個意思也就是說,每次到index頁面的時候首先是跳入到這個方法裡邊,通過這個方法判斷cookie和session中儲存的相關資料是否正確,如果正確的話就跳入到登入成功頁面,不正確或者cookie、session失效的話就跳入login頁面。@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"; }
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實現自動登入效果的程式碼!