redis緩存+session 實現單點登錄


一、單點登錄介紹

  單點登錄(Single Sign On),簡稱為 SSO,是目前比較流行的企業業務整合的解決方案之一。SSO的定義是在多個應用系統中,用戶只需要登錄一次就可以訪問所有相互信任的應用系統。

  同域下:單點登錄是巧用了Cookie頂域的特性。

  不同域下:如果是不同域呢?不同域之間Cookie是不共享的,怎么辦? 這個是使用CAS流程,單點登錄的標准流程。

  相關詳情:https://yq.aliyun.com/articles/636281 

         https://blog.csdn.net/qq_34246546/article/details/79493208

二、同域下的單點登錄:利用sessionID+cookie+redis

 注意:因為我們是通過cookie的頂域特性,所以需要通過域名訪問才能生成指定的cookie名稱mmall_login_token 的cookie

自定義域名相關集群和負載均衡:https://www.cnblogs.com/FondWang/p/11677319.html

1. cookie工具類

package com.mmall.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * cookie工具類
 */
@Slf4j
public class CookieUtil {
    private static final String COOKIE_DOMAIN = "wangjun.com"; //頂級域名
    private static final String COOKIE_NAME = "mmall_login_token";//cookieName

    /**
     * 從請求中讀取cookie
     * @param request
     * @return
     */
    public static String readLoginToken(HttpServletRequest request){
        Cookie[] cks = request.getCookies();
        if (cks != null){
            for (Cookie cookie : cks){
                log.info("read cookieName:{}, cookieValue:{}",cookie.getName(),cookie.getValue());
                if (StringUtils.equals(cookie.getName(),COOKIE_NAME)){
                    log.info("return cookieName:{}, cookieValue:{}",cookie.getName(),cookie.getValue());
                    return cookie.getValue();
                }
            }
        }
        return null;
    }

    /**
     * 寫入cookie
     * @param response
     * @param token
     */
    public static void writeLoginToken(HttpServletResponse response, String token){
        Cookie cookie = new Cookie(COOKIE_NAME, token);
        cookie.setDomain(COOKIE_DOMAIN);
        cookie.setPath("/"); //代表根目錄,根目錄以下的代碼和頁面可以獲取到cookie

        //單位秒,如果不設置maxage,cookie就不會寫入硬盤,而是寫入內存,只在當前頁面有效
        cookie.setMaxAge(60 * 60 * 24 * 365);
        log.info("write cookieName:{}, cookieValue:{}", cookie.getName(),cookie.getValue());
        response.addCookie(cookie);
    }

    /**
     * 刪除cookie
     * @param request
     * @param response
     */
    public static void delLoginToken(HttpServletRequest request, HttpServletResponse response){
        Cookie[] cks = request.getCookies();
        if (cks != null){
            for (Cookie cookie : cks){
                if (StringUtils.equals(cookie.getName(),COOKIE_NAME)){
                    cookie.setDomain(COOKIE_DOMAIN);
                    cookie.setPath("/");
                    cookie.setHttpOnly(true); //無法用腳本訪問cookie。當然不能全面防止,但可以提高安全性
                    cookie.setMaxAge(0);//設置為0,代表刪除此cookie
                    log.info("del cookieName:{}, cookieValue:{}", cookie.getName(),cookie.getValue());
                    response.addCookie(cookie);
                    return;
                }
            }
        }

    }
}
View Code

2. redis相關內容

  (1)使用集群:https://www.cnblogs.com/FondWang/p/11690791.html

  (2)單機redis:https://www.cnblogs.com/FondWang/p/11681222.html

3. json對象轉換

  作用:將登錄信息轉換陳json,存儲到redis中。

  https://www.cnblogs.com/FondWang/p/11703197.html

4. 登錄代碼

@Controller @RequestMapping("/user/") public class UserController { @Autowired private IUserService iUserService; /** * 用戶登錄 * @param username * @param password * @param session * @return
     */ @RequestMapping(value = "login.do",method = RequestMethod.POST) @ResponseBody public ServiceResponse<User> login(String username, String password, HttpSession session, HttpServletResponse httpServletResponse){ ServiceResponse<User> response = iUserService.login(username, password); if (response.isSuccess()){ CookieUtil.writeLoginToken(httpServletResponse,session.getId()); //將內容寫入cookie中 RedisShardedPoolUtil.setEx(session.getId(), JsonUtil.obj2String(response.getData()), Const.RedisCacheExtime.REDIS_SESSION_EXTIME); } return response; } /** * 登出 刪除session * @param httpServletRequest * @return
     */ @RequestMapping(value = "logout.do",method = RequestMethod.POST) @ResponseBody public ServiceResponse<String> logout(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) { String loginToken = CookieUtil.readLoginToken(httpServletRequest); //獲取cookie的sessionID,如果存在,刪除登出 CookieUtil.delLoginToken(httpServletRequest,httpServletResponse); //刪除cookie中對應的token用戶信息 RedisShardedPoolUtil.del(loginToken); //刪除對應redis的用戶信息 return ServiceResponse.createBySuccess("已登出"); } }

三、不同域下的單點登錄

  待更新

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM