sso单点登录的原理详解

单点登录全称Single Sign On(以下简称SSO),是指在多系统应用群中登录一个系统,便可在其他所有系统中得到授权而无需再次登录,包括单点登录与单点注销两部分。

单点登录

相比于单系统登录,sso需要一个独立的认证中心,只有认证中心能接受用户的用户名密码等安全信息,其他系统不提供登录入口,只接受认证中心的间接授权。间接授权通过令牌实现,sso认证中心验证用户的用户名密码没问题,创建授权令牌,在接下来的跳转过程中,授权令牌作为参数发送给各个子系统,子系统拿到令牌,即得到了授权,可以借此创建局部会话,局部会话登录方式与单系统的登录方式相同。

sso-client
​

@Controller
public class HelloController {
 @Value("${sso.server.url}")
 private String ssoServerUrl;
 /**
 * 无需登录就可以访问
 * @return
 */
 @ResponseBody
 @RequestMapping("/hello")
 public String hello() {
 return "hello";
 }
 /**
 * 需要验证的连接
 * @param model
 * @param token 只要是ssoserver登陆成功回来就会带上
 * @return
 */
 @GetMapping("/employees")
 public String employees(Model model, HttpSession session,@RequestParam(value="token",required = false) String token) {
     if (!StringUtils.isEmpty(token)) {
         // 去ssoserver登录成功调回来就会带上
         //TODO 1、去ssoserver获取当前token真正对应的用户信息
         RestTemplate restTemplate = new RestTemplate();
         // 使用restTemplate进行远程请求
         ResponseEntity<String> forEntity =
        restTemplate.getForEntity("http://ssoserver.com:8080/userInfo?token=" +         token,String.class);
         // 拿到数据
         String body = forEntity.getBody();
         // 设置到session中
         session.setAttribute("loginUser",body);
     }
     Object loginUser = session.getAttribute("loginUser");
     if (loginUser == null ){
         // 没有登录重定向到登陆页面,并带上当前地址
         return "redirect:" + ssoServerUrl + "?redirect_url=http://client1.com:8081/employees";
 } else {
     List<String> emps = new ArrayList<>();
     emps.add("张三");
     emps.add("李四");
     model.addAttribute("emps",emps);
     return "list";
     }
 }
}

​
sso-server
@Controller
public class LoginController {
 @Autowired
 StringRedisTemplate redisTemplate;
 /**
 * 根据token从redis中查询用户信息
 * @param token
 * @return
 */
 @ResponseBody
 @GetMapping("/userInfo")
 public String userInfo(@RequestParam("token") String token) {
 String s = redisTemplate.opsForValue().get(token);
 return s;
 }
 @GetMapping("login.html")
 public String login(@RequestParam("redirect_url") String url, Model model,
 @CookieValue(value = "sso_token",required = false)String
sso_token) {
 if (!StringUtils.isEmpty(sso_token)) {
 //说明有人之前登录过,给浏览器留下了痕迹
 return "redirect:" + url + "?token=" + sso_token;
 }
 // 添加url到model地址中,在前端页面进行取出
 model.addAttribute("url",url);
 return "login";
 }
 /**
 * 登录
 * @param username
 * @param password
 * @param url client端带过来的地址
 * @return
 */
 @PostMapping("/doLogin")
 public String doLogin(@RequestParam("username") String username,
 @RequestParam("password") String password,
 @RequestParam("url") String url,
 HttpServletResponse response){
 // 账号密码不为空
 if (!StringUtils.isEmpty(username) && !StringUtils.isEmpty(password)) {
 // 登陆成功
 // 把登录成功的用户存起来
 String uuid = UUID.randomUUID().toString().replace("-","");
 redisTemplate.opsForValue().set(uuid,username);
 // 将uuid存入cookie
 Cookie token = new Cookie("sso_token",uuid);
 response.addCookie(token);
 // 保存到cookie
 return "redirect:" + url + "?token=" + uuid;
 }
 // 登录失败,展示登录页
 return "login";
 }
}

单点注销

sso认证中心一直监听全局会话的状态,一旦全局会话销毁,监听器将通知所有注册系统执行注销操作

  1. 用户向系统1发起注销请求

  2. 系统1根据用户与系统1建立的会话id拿到令牌,向sso认证中心发起注销请求

  3. sso认证中心校验令牌有效,销毁全局会话

  4. sso认证中心向所有注册系统发起注销请求

  5. sso认证中心引导用户至登录页面

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值