持續學習&持續更新中…
守破離
【雷豐陽-谷粒商城 】【分布式高級篇-微服務架構篇】【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架構師 | 微服務 | 大型電商項目.
本文完,感謝您的關注支持!