zoukankan      html  css  js  c++  java
  • 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("已登出");
        }
    }

    三、不同域下的单点登录

      待更新

     

  • 相关阅读:
    移动端触摸右侧菜单栏,页面内容对应项滚动到最上方
    swiper使用中一些点的总结
    javaScript正则表达式入门
    javaScript之数组操作方法(一)
    初识vue
    焦点控制切换和轮播
    文本内容只显示两行,然后加...
    图片父容器高度不定的图片垂直居中
    css3图片垂直居中
    【C#】两个list根据某个元素比较差集
  • 原文地址:https://www.cnblogs.com/FondWang/p/11704737.html
Copyright © 2011-2022 走看看