当前位置: 代码迷 >> 综合 >> 简单的CAS单点登录
  详细解决方案

简单的CAS单点登录

热度:96   发布时间:2024-02-12 20:21:37.0

使用Redis+cookie实现简单的单点登录

在这里插入图片描述

1:用户第一次登陆A系统,发现未登陆,会携带上returnUrl跳转至CAS系统的登陆方法,在这个方法会验证此用户是否已经登陆(具有全局会话),如果没有登陆,就会跳转至CAS登陆页面,让用户登录

	@GetMapping("/login")public String test(HttpServletRequest request, HttpServletResponse response,Model model,String returnUrl) {model.addAttribute("returnUrl", returnUrl);// 需要判断当前用户是否在CAS登录过(获取存放在cookie中的全局会话)String userTicket = getCookie(request, COOKIE_USER_TICKET);// 判断这个会话是否有效boolean verifyUserTicket = verifyUserTicket(userTicket);if (verifyUserTicket) {// 如果有效则跳转至returnUrlString tmpTicket = setTemTicket();return "redirect:" + returnUrl + "?tmpTicket=" + tmpTicket;}return "login";}

2:用户在输入用户名,密码后,CAS校验通过了,就会创建全局会话,全局票证,临时票证(用于跳转至returnUrl后校验)

@PostMapping("doLogin")public String doLogin(HttpServletRequest request, HttpServletResponse response,Model model, String returnUrl,String password,String username) {if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {model.addAttribute("errMsg", "用户名或密码不能为空");return "login";}UserLoginBo userLoginBo = new UserLoginBo(username, password);Users users = userService.queryUsersByUsernameAndPassword(userLoginBo);if (users == null) {model.addAttribute("errMsg", "用户名或密码错误");return "login";}// 创建Redis会话String uniqueToken = UUID.randomUUID().toString().trim();UsersVo usersVO = new UsersVo();BeanUtils.copyProperties(users, usersVO);usersVO.setUserUniqueToken(uniqueToken);// Redis全局会话,(分布式)redisOperator.set(REDIS_USER_TOKEN + ":" + users.getId(),JsonUtils.objectToJson(usersVO));// 生成ticket全局门票,代表用户在CAS端登录过String userTicket = UUID.randomUUID().toString().trim();redisOperator.set(REDIS_USER_TICKET + ":" + userTicket,users.getId());setCookie(COOKIE_USER_TICKET, userTicket, response);
// CookieUtils.setCookie(request, response, COOKIE_USER_TICKET, userTicket, true);// 生成临时的门票,用于returnUrl的验证String temTicket = setTemTicket();return "redirect:" + returnUrl + "?tmpTicket=" + temTicket;}

校验temticket

@PostMapping("verifyTmpTicket")@ResponseBodypublic IMOOCJSONResult verifyTmpTicket(String tmpTicket,HttpServletRequest request) throws Exception{if (StringUtils.isBlank(tmpTicket)) {return IMOOCJSONResult.errorMsg("请重新登录");}// 从Redis中获取临时的门票,进行验证String redisTmpTicket = redisOperator.get(REDIS_TMP_TICKET + ":" + tmpTicket);if (StringUtils.isBlank(redisTmpTicket)) {return IMOOCJSONResult.errorMsg("票证已经过期");}if (!redisTmpTicket.equals(MD5Utils.getMD5Str(tmpTicket))) {return IMOOCJSONResult.errorMsg("票证不一致");}// 表示票证么有问题,删除临时的票证redisOperator.del(REDIS_TMP_TICKET + ":" + tmpTicket);// 从CAS的cookie中获取用户信息String userTicket = getCookie(request, COOKIE_USER_TICKET);if (StringUtils.isBlank(userTicket)) {return IMOOCJSONResult.errorMsg("票证有问题");}String userId = redisOperator.get(REDIS_USER_TICKET + ":" + userTicket);if (StringUtils.isBlank(userId)) {return IMOOCJSONResult.errorMsg("票证有问题");}// 利用cookie中的票证去Redis中拿用户信息String userInfo = redisOperator.get(REDIS_USER_TOKEN + ":" + userId);if (StringUtils.isBlank(userInfo)) {return IMOOCJSONResult.errorMsg("票证有问题");}return IMOOCJSONResult.ok(JsonUtils.jsonToPojo(userInfo, UsersVo.class));}
  相关解决方案