【SpringBoot】廿一、SpringBoot中使用Cookie實現記住登錄

最近在做項目,甲方提出每次登錄都要輸入密碼,會很麻煩,要求實現一個記住登錄狀態的功能,於是便使用 Cookie 實現該功能

一、Cookie 簡介

Cookie,一種儲存在用戶本地終端上的數據,有時也用其複數形式 Cookies。類型爲“小型文本文件”,是某些網站爲了辨別用戶身份,進行 Session 跟蹤而儲存在用戶本地終端上的數據(通常經過加密),由用戶客戶端計算機暫時或永久保存的信息。

其實 Cookie 就是一個鍵和一個值構成的,隨着服務器端的響應發送給客戶端瀏覽器。然後客戶端瀏覽器會把 Cookie 保存起來,當下一次再訪問服務器時把 Cookie 再發送給服務器。

1、Cookie 是 HTTP 協議的規範之一,它是服務器和客戶端之間傳輸的小數據
2、首先由服務器通過響應頭把 Cookie 傳輸給客戶端,客戶端會將 Cookie 保存起來
3、當客戶端再次請求同一服務器時,客戶端會在請求頭中添加該服務器保存的 Cookie,發送給服務器
4、Cookie 就是服務器保存在客戶端的數據
5、Cookie 就是一個鍵值對
cookie示意圖

二、Cookie 使用

1、創建 Cookie

// Cookie 爲鍵值對數據格式
Cookie cookie_username = new Cookie("cookie_username", username);

2、設置 Cookie 持久時間

// 即:過期時間,單位是:秒(s)
cookie_username.setMaxAge(30 * 24 * 60 * 60);

3、設置 Cookie 共享路徑

// 表示當前項目下都攜帶這個cookie
cookie_username.setPath(request.getContextPath());

4、向客戶端發送 Cookie

// 使用 HttpServletResponse 對象向客戶端發送 Cookie
response.addCookie(cookie_username);

5、銷燬 Cookie

// 根據 key 將 value 置空
Cookie cookie_username = new Cookie("cookie_username", "");
// 設置持久時間爲0
cookie_username.setMaxAge(0);
// 設置共享路徑
cookie_username.setPath(request.getContextPath());
// 向客戶端發送 Cookie
response.addCookie(cookie_username);

三、進入正題

上面我們已經瞭解了 Cookie 是什麼,並且知道了 Cookie 的創建以及銷燬的方法,下面,我們就使用 Cookie 實現記住登錄狀態的功能,整個項目基於 SpringBoot 實現

1、註冊攔截器

/**
* 註冊攔截器
*/
@Configuration
public class WebConfigurer implements WebMvcConfigurer {

    @Autowired
    private LoginInterceptor loginHandlerInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        InterceptorRegistration ir = registry.addInterceptor(loginHandlerInterceptor);
        // 攔截路徑
        ir.addPathPatterns("/*");
        // 不攔截路徑
        List<String> irs = new ArrayList<String>();
        irs.add("/api/*");
        irs.add("/wechat/*");
        irs.add("/oauth");
        ir.excludePathPatterns(irs);
    }
}

我們攔截了所有的請求路徑,放開了 api、wechat 等請求路徑

這裏可能會有一個疑問,爲什麼不放開請求登錄界面的 api 請求路徑呢,原因是我們攔截登錄請求,當我們請求登錄界面時,我們已經登錄過,那麼我們就無需進入登錄界面,直接到主界面

我們使用了自定義的一個登錄攔截:LoginInterceptor,在第二步我們會詳細講解其中的實現原理

2、登錄攔截

/**
* 未登錄攔截器
*/
@Component
public class LoginInterceptor implements HandlerInterceptor {

    @Autowired
    private LoginDao dao;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 獲得cookie
        Cookie[] cookies = request.getCookies();
        // 沒有cookie信息,則重定向到登錄界面
        if (null == cookies) {
            response.sendRedirect(request.getContextPath() + "/login");
            return false;
        }
        // 定義cookie_username,用戶的一些登錄信息,例如:用戶名,密碼等
        String cookie_username = null;
        // 獲取cookie裏面的一些用戶信息
        for (Cookie item : cookies) {
            if ("cookie_username".equals(item.getName())) {
                cookie_username = item.getValue();
                break;
            }
        }
        // 如果cookie裏面沒有包含用戶的一些登錄信息,則重定向到登錄界面
        if (StringUtils.isEmpty(cookie_username)) {
            response.sendRedirect(request.getContextPath() + "/login");
            return false;
        }
        // 獲取HttpSession對象
        HttpSession session = request.getSession();
        // 獲取我們登錄後存在session中的用戶信息,如果爲空,表示session已經過期
        Object obj = session.getAttribute(Const.SYSTEM_USER_SESSION);
        if (null == obj) {
			// 根據用戶登錄賬號獲取數據庫中的用戶信息
        	UserInfo dbUser = dao.getUserInfoByAccount(cookie_username);
            // 將用戶保存到session中
            session.setAttribute(Const.SYSTEM_USER_SESSION, dbUser);
        }
        // 已經登錄
        return true;
    }
}

3、登錄請求

控制層

/**
  * 執行登錄
  */
 @PostMapping("login")
 @ResponseBody
 public String login(String username, String password, HttpSession session, HttpServletRequest request, HttpServletResponse response) {
     return service.doLogin(username.trim(), password.trim(), session, request, response).toJSONString();
 }

業務層

/**
 * 執行登錄
 */
public JSONObject doLogin(String username, String password, HttpSession session, HttpServletRequest request, HttpServletResponse response) {
	// 最終返回的對象
    JSONObject res = new JSONObject();
    res.put("code", 0);
    if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password)) {
        res.put("msg", "請輸入手機號或密碼");
        return res;
    }
    UserInfo dbUser = dao.getUserInfoByAccount(username);
    if (null == dbUser) {
        res.put("msg", "該賬號不存在,請檢查後重試");
        return res;
    }
    // 驗證密碼是否正確
    String newPassword = PasswordUtils.getMd5(password, username, dbUser.getSalt());
    if (!newPassword.equals(dbUser.getPassword())) {
        res.put("msg", "手機號或密碼錯誤,請檢查後重試");
        return res;
    }
    // 判斷賬戶狀態
    if (1 != dbUser.getStatus()) {
        res.put("msg", "該賬號已被凍結,請聯繫管理員");
        return res;
    }
    // 將登錄用戶信息保存到session中
    session.setAttribute(Const.SYSTEM_USER_SESSION, dbUser);
    // 保存cookie,實現自動登錄
    Cookie cookie_username = new Cookie("cookie_username", username);
    // 設置cookie的持久化時間,30天
    cookie_username.setMaxAge(30 * 24 * 60 * 60);
    // 設置爲當前項目下都攜帶這個cookie
    cookie_username.setPath(request.getContextPath());
    // 向客戶端發送cookie
    response.addCookie(cookie_username);
    res.put("code", 1);
    res.put("msg", "登錄成功");
    return res;
}

4、註銷登錄

/**
 * 退出登錄
 */
@RequestMapping(value = "logout")
public String logout(HttpSession session, HttpServletRequest request, HttpServletResponse response) {
    // 刪除session裏面的用戶信息
    session.removeAttribute(Const.SYSTEM_USER_SESSION);
    // 保存cookie,實現自動登錄
    Cookie cookie_username = new Cookie("cookie_username", "");
    // 設置cookie的持久化時間,0
    cookie_username.setMaxAge(0);
    // 設置爲當前項目下都攜帶這個cookie
    cookie_username.setPath(request.getContextPath());
    // 向客戶端發送cookie
    response.addCookie(cookie_username);
    return "login";
}

註銷登錄時,我們需要刪除 session 裏面的用戶信息,刪除 cookie 裏面的用戶信息,然後請求到登錄界面

四、總結

以上就是 SpringBoot 中使用 Cookie 實現記住登錄功能,在項目中還算是比較實用的功能,希望能對正在閱讀的你一點點幫助和啓發

如您在閱讀中發現不足,歡迎留言!!!

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