基于Redis的单点登录实现方案

版权声明:欢迎转载,转载请标明转载地址 https://blog.csdn.net/u010520146/article/details/86542205

一.单点登录流程分析

1.客户端统一拦截过滤器

在这里插入图片描述

流程分析:

1.在对需要进行授权登录的url连接,访问统一被上放的过滤器流程所拦截
2.进入过滤器,首先判断当前域名下是否有cookie,如果存在,则判断该cookie的值作为key在redis中是否存在,如果存在则进入进行,不存在则进入服务端的登录授权界面.
3.如果当前域名下的cookie值不存在,则判断当前链接是否带有一个参数值为ticket的值,如果存在,则设置该值为cookie,然后重定向到本地址.

2.服务端流程

在这里插入图片描述

分析:

1.登录接口:用户名密码验证成功后,设置cookie,设置redis缓存,登录成功
2.登录页面:先判断是否有cookie以及redis缓存,如果满足,则重定向返回backurl以及附加参数ticket值为当前的cookie,如果不满足,则进入登录界面
3.退出登录:删除redis缓存,删除cookie
4.为了防止别人拿着带着ticket的链接去其他浏览器进行伪造登录,则可以对其ticket存入redis中,客户端对其进行一次性消费.

二.客户端与服务端cookie同步

1.js脚本更新

可通过html加入js脚本访问服务端,服务端再对其cookie重置时长

2.增长服务端cookie时长

可通过增长服务端cookie时长,如果客户端退出了,redis缓存将清理,再次访问服务端登录接口,服务端查询不到redis缓存,则对其cookie进行删除.但是这种不能算是完全意义上的同步.

三.关键代码

1.客户端过滤器filter
 String cookieName = CookieUtil.getCookie(Constans.COOKIE_SSO, request);
        if(cookieName!=null&& !cookieName.equals("")){
            //验证cookie的有效性
            User user = tokenManagerInter.getUserInfo(cookieName);
            if(user!=null){
                //验证成功,继续执行
                //TODO 重置cookie时间,缓存时间
                filterChain.doFilter(servletRequest,servletResponse);
            }else {
                //验证失败,删除无效cookie
                CookieUtil.deleteCookie(Constans.COOKIE_SSO,response, "/");
                //返回登录界面
                String qstr = makeQueryString(request); // 将所有请求参数重新拼接成queryString
                String backUrl=request.getRequestURL() + qstr; // 回调url
                String location = "127.0.0.1/login?backUrl=" + URLEncoder.encode(backUrl, "utf-8");
                response.sendRedirect(location);
            }
        }else {
            String vtParam = pasreVtParam(request); // 从请求中
            if (vtParam == null) {
                // 请求中中没有vtParam,引导浏览器重定向到服务端执行登录校验
                //返回登录界面
                String qstr = makeQueryString(request); // 将所有请求参数重新拼接成queryString
                String backUrl=request.getRequestURL() + qstr; // 回调url
                String location = "127.0.0.1/login?backUrl=" + URLEncoder.encode(backUrl, "utf-8");
                response.sendRedirect(location);
            } else if (vtParam.length() == 0) {
                // 有vtParam,但内容为空,表示到服务端loginCheck后,得到的结果是未登录
                response.sendError(403);
            } else {
                // 让浏览器向本链接发起一次重定向,此过程去除vtParam,将vt写入cookie
                redirectToSelf(vtParam);
            }
        }
2.服务端登录界面

先判断当前是否有cookie,如果没有,则进入登录界面,如果存在,则判断是否有redis缓存存在,如果不存在,则进入登录界面,如果存在,则重定向到backurl中去,同时带着ticket返回客户端

 @Override
    public String login(String backUrl, ModelMap map) {
        String cookie = CookieUtil.getCookie(Constans.COOKIE_SSO, request);
        //判断有无cookie
        if(cookie==null){
            //无cookie,进入登录界面
            map.put("backUrl", backUrl);
            return "login";
        }else {
            //当前存在cookie
            if(tokenManagerInter.checkToken(cookie)){
                //缓存存在
                if (backUrl != null) {
                    try {
                        response.sendRedirect(StringUtils.appendUrlParameter(backUrl, Constans.PARAGRAM_VT, cookie));
                    } catch (IOException e) {
                        e.printStackTrace();
                        logger.error("登录重定向失败:"+e);
                    }
                    return null;
                } else {
                    AccountUser user = tokenManagerInter.getUserInfo(cookie);
                    if(user!=null){
                        map.put("user", user);
                    }
                    map.put("vt", cookie);
                    return "loginSuccess";
                }
            }else {
                //缓存不存在,删除cookie,返回登录界面
                CookieUtil.deleteCookie(Constans.COOKIE_SSO,response,"/");
                map.put("backUrl", backUrl);
                return "login";
            }
        }
    }
3.服务端登录接口

验证完用户名密码后设置cookie,增加redis缓存,重定向到backurl去.

 				//设置cookie
                String uuid = UUID.randomUUID().toString().replaceAll("-","");
                Cookie cookie = new Cookie(Constans.COOKIE_SSO, uuid);
                cookie.setMaxAge(Constans.COOKIE_EXPIRE_TIME);//设置cookie时间
                cookie.setPath("/");
                response.addCookie(cookie);
                //存入redis中
                System.out.println("创建uuid:"+uuid);
                accountUser.setUuid(uuid);
                result.setModel(accountUser);
                boolean creatToken = tokenManagerInter.createToken(accountUser);
                System.out.println("创建token:"+creatToken);
                if(!creatToken){
                    return resultUtil.setErrResult(ReturnCodeBase.ERR5002);
                }
4.退出登录接口

退出登录时候,检查cookie是否存在,然后删除redis缓存,删除cookie,重定向到登录界面

 		String cookie = CookieUtil.getCookie(Constans.COOKIE_SSO, request);
        if (cookie != null && !cookie.equals("")) {
            tokenManagerInter.deleteToken(cookie);
            CookieUtil.deleteCookie(Constans.COOKIE_SSO, response, "/");
        }
        if (backUrl != null && !backUrl.equals("")) {
            try {
               return "redirect:"+Constans.URL.PREFIX+"login?backUrl=" + URLEncoder.encode(backUrl, "utf-8");
            } catch (UnsupportedEncodingException e) {
                logger.error("退出登录重定向失败:" + e);
            }
        }
        return "redirect:/login";

猜你喜欢

转载自blog.csdn.net/u010520146/article/details/86542205