SSO(Single Sign on)单点登录系统

本文介绍SSO单点登录的基本原理,并通过具体代码示例详细解释其实现过程。用户首次访问应用系统时,若未登录,则被重定向至认证系统;认证通过后,用户获得认证凭据ticket,后续访问其他应用系统时无需重复登录。

SSO单点登录

  1. 原理:①当用户第一次访问应用系统1的时候,因为还没有登录,会被引导到认证系统中进行登录;根据用户提供的登录信息,认证系统进行身份校验,如果通过校验,应该返回给用户一个认证的凭据--ticket;用户再访问别的应用的时候就会将这个ticket带上,作为自己认证的凭据,应用系统接受到请求之后会把ticket送到认证系统进行校验,检查ticket的合法性。如果通过校验,用户就可以在不用再次登录的情况下访问应用系统2和应用系统3了。
  2. 逐步解析原理
  • ①用户第一次访问应用系统时,因为没登录,所以要到认证系统中进行登录。这里实现是通过过滤器,过滤系统1的所有请求,看是否存在凭证(凭证保存在了cookie中)。系统1,2..中过滤器代码如下:
    
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws IOException, ServletException {
        HttpServletRequest request2 = (HttpServletRequest) request;
        HttpServletResponse response2 = (HttpServletResponse) response;
        // 通票名称
        String token = "token";
        boolean flag = true;
        // 凭证通过Cookie实现
        // Cookie的获取
        Cookie[] cookies = request2.getCookies();
        if (cookies == null) {
            // 不存在cookie,即不存在凭证,跳转到登录界面
            // 重定向到登录界面
            response2.sendRedirect("/itdage-sso/login.jsp");
        } else {
            // 存在cookie
            for (Cookie cookie : cookies) {
                // 因为前端cookie不止一个,所以判断有没有名字是token的cookie
                if (token.equals((cookie.getName()))) {
                    //有token,从redis中获取对应的对象,因为SSO中session不能共享,在这用redis代替session存储登录的对象信息。
                    //redis可以设置过期时间,也是key-value格式存储,完美替代session。
                    Jedis jedis = new Jedis("localhost");
                    String objStr = jedis.get(cookie.getValue());
                    //如果没有token的值还得跳转到登录界面
                    if(objStr == null){
                        response2.sendRedirect("/itdage-sso/login.jsp");
                        flag = false;
                        break;
                    }
                    //从redis中取出value,此处存储value用的是json字符串格式,所有取出时用json转为对象
                    Gson gson = new Gson();
                    User user = gson.fromJson(objStr, User.class);
                    //将user设置到session中(单个系统中session还是能用的)
                    HttpSession session = request2.getSession();
                    session.setAttribute("user", user);
                    //放行
                    chain.doFilter(request2, response2);
                    //不在执行下面的跳转,否则会报错
                    flag = false;
                }
            }
            //不存在token,则跳转
            if(flag){
                response2.sendRedirect("/itdage-sso/login.jsp");
            }
        }
    }
    
  • ②根据用户提供的登录信息,认证系统进行身份校验,如果通过校验,应该返回给用户一个认证的凭据--ticket;
    
    //SSO登录部分后端代码
    @Controller
    public class LoginController {
    
        @Resource
        private LoginService loginService;
        @Resource
        private Result result;
    
        private Gson gson = new Gson();
    
        private Jedis jedis = new Jedis("localhost");
        @ResponseBody
        @RequestMapping(value="/login", method = RequestMethod.POST)
        public Result Login(User user, HttpServletRequest request, HttpServletResponse response){
            //调用数据库验证,也可写死用户名和密码
            List list = loginService.getList(user);
            if(list.size()>0){
                //密码正确,登录成功,保存用户信息
                HttpSession session = request.getSession();
                //验证验证码是否正确
                String vCode = (String)session.getAttribute("vCode");
                if(vCode.equalsIgnoreCase(user.getvCode())){
                    //验证成功标志
                    result.setState(1);
                    //SSO下要将用户信息存入redis中,redis是session的一个很好的替代品,设置redis的有效时间为30'
                    //生成凭证,要唯一
                    String token = "Sso_Token" + list.get(0).getUsername() + System.currentTimeMillis();
                    //将用户信息转为Json字符串存入redis,对应上面的从redis取出。
                    String value = gson.toJson(list.get(0));
                    //将用户信息存入redis中
                    jedis.set(token, value);
                    //设置token_key有效期为30分钟
                    jedis.expire(token, 30*60);
                    //将token设置到cookie中,因为前端访问后台会自动携带者cookie,所有cookie是存储凭证的好地方。
                    Cookie cookie = new Cookie("token", token);
                    //这句话很重要,设置cookie有效区间为整个根项目(全局)
                    cookie.setPath("/");
                    response.addCookie(cookie);
                }else{
                    //验证码不正确
                    result.setObject(user);
                    result.setState(2);
                }
            }else{
                //密码错误
                result.setObject(user);
                result.setState(3);
            }
            return result;
        }
    }
    


3. 此时登录成功后要重定向到用户一开始访问的url,用户登录成功后,再访问其他系统时,会带着生成的cookie,然后过滤器中验证了cookie(凭证)有效,就不用登录啦!
4. 可以结合这个网站理解上面的代码。39.106.45.93/itdage/index.jsp(自己写的小项目)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值