持续学习&持续更新中…
守破离
【雷丰阳-谷粒商城 】【分布式高级篇-微服务架构篇】【20】认证服务04—SSO单点登录
- xxl-sso
- 多系统-单点登录
- 单点登录流程原理图
- 单点登录流程简单实现
- 参考
xxl-sso
https://gitee.com/xuxueli0323/xxl-sso
xxl-sso是开源的一个单点登录框架
一个分布式单点登录框架。只需要登录一次就可以访问所有相互信任的应用系统。 拥有"轻量级、分布式、跨域、Cookie+Token均支持、Web+APP均支持"等特性;。现已开放源代码,开箱即用。
C:\Windows\System32\drivers\etc\hosts(模仿三个域名)
#模拟单点登录
127.0.0.1 xxlssoserver.com
127.0.0.1 client1.com
127.0.0.1 client2.com
打包之前修改这三个的配置文件:
举例:修改客户端:
修改完成打包命令:(打包所有)
启动服务器
启动两个客户端:
自己测试:
C:\Users\lenovo\Desktop\xxl-sso\xxl-sso-server\target>java -jar xxl-sso-server-1.1.1-SNAPSHOT.jar
C:\Users\lenovo\Desktop\xxl-sso\xxl-sso-samples\xxl-sso-web-sample-springboot\target>java -jar xxl-sso-web-sample-springboot-1.1.1-SNAPSHOT.jar --server.port=13000
C:\Users\lenovo\Desktop\xxl-sso\xxl-sso-samples\xxl-sso-web-sample-springboot\target>java -jar xxl-sso-web-sample-springboot-1.1.1-SNAPSHOT.jar --server.port=12000
http://xxlssoserver.com:8080/xxl-sso-server/login
http://client1.com:12000/xxl-sso-web-sample-springboot/
http://client2.com:13000/xxl-sso-web-sample-springboot/
上面这三个地址,无论访问哪个都要求登录,并且一处登录,处处可用
多系统-单点登录
Single Sign On 一处登陆、处处可用(运行)
单点登录流程原理图
单点登录流程简单实现
认证服务:ssoserver.com:8080
@Controller
public class LoginController {@AutowiredStringRedisTemplate redisTemplate;/*** TODO 开放接口给其他系统,让它们用来查询 token 对应的用户信息,判断该用户是否登录过,实现单点登录*/@ResponseBody@GetMapping("/userInfo")public String userInfo(@RequestParam("token") String token){String s = redisTemplate.opsForValue().get(token);return s;}@GetMapping("/login.html")public String loginPage(@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;}model.addAttribute("url",url);return "login";}@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);// 给浏览器留下登录痕迹Cookie sso_token = new Cookie("sso_token",uuid);response.addCookie(sso_token);//登录成功,跳回之前页面,并带上tokenreturn "redirect:"+url+"?token="+uuid;}//登录失败,展示登录页return "login";}
}
客户端1:client1.com:8081
@Controller
public class HelloController {@Value("${sso.server.url}")String ssoServerUrl;/*** 无需登录就可访问* @return*/@ResponseBody@GetMapping("/hello")public String hello(){return "hello";}/*** TODO 如下判断,可以抽取出来放在一个Filter中,放在任何系统中,实现单点登录*//*** 感知这次是在 ssoserver 登录成功跳回来的。* @param model* @param session* @param token 只要去ssoserver登录成功跳回来就会带上* @return*/@GetMapping("/employees")public String employees(Model model, HttpSession session,@RequestParam(value = "token",required = false) String token){//if(!StringUtils.isEmpty(token)){//TODO 应该去ssoserver获取当前token真正对应的用户信息// 如果我们并不知道ssoserver的redis地址,也就是说客户端并不知道认证服务器将用户信息保存在哪里// 我们就得用令牌去认证服务器再查一次用户信息,查询用户信息成功,表明登录成功RestTemplate restTemplate = new RestTemplate();ResponseEntity<String> forEntity = restTemplate.getForEntity("http://ssoserver.com:8080/userInfo?token=" + token, String.class);String body = forEntity.getBody();session.setAttribute("loginUser",body);}Object loginUser = session.getAttribute("loginUser");if(loginUser==null){//没登录,跳转到登录服务器进行登录//跳转过去以后,使用url上的查询参数标识我们自己是哪个页面//redirect_url=http://client1.com:8080/employeesreturn "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";}}
}
客户端2:client1.com:8082
@Controller
public class HelloController {@Value("${sso.server.url}")String ssoServerUrl;@GetMapping("/boss")public String boss(Model model, HttpSession session,@RequestParam(value = "token",required = false) String token){if(!StringUtils.isEmpty(token)){RestTemplate restTemplate = new RestTemplate();ResponseEntity<String> forEntity =restTemplate.getForEntity("http://ssoserver.com:8080/userInfo?token=" + token, String.class);String body = forEntity.getBody();session.setAttribute("loginUser",body);}Object loginUser = session.getAttribute("loginUser");if(loginUser==null){return "redirect:"+ssoServerUrl+"?redirect_url=http://client2.com:8082/boss";}else{List<String> boss = new ArrayList<>();boss.add("666");boss.add("777");model.addAttribute("boss",boss);return "list";}}}
参考
雷丰阳: Java项目《谷粒商城》Java架构师 | 微服务 | 大型电商项目.
本文完,感谢您的关注支持!