最近需要将内部系统与简道云做对接,在实现单点登录时参考官方文档时比较繁琐,技术支持人员也说的不够清楚,其实就是参考下面这幅图的调用过程,其中第2,3步都是访问的公司内部系统接口,通过这两次的请求来确认用户身份,进行登录验证。
初看这张图时,没有明白怎么在第三步验证用户的信息,其实就是在第二步请求内部接口时,对请求直接进行重定向,并同时带入用户的信息,然后在第三步接收重定向带来的参数,用此进行登录的校验。
下面是基于Java代码的实现,只需要在controller中新增两个方法即可。
@Slf4j
@Controller
@NoArgsConstructor
@AllArgsConstructor
class SSOController extends BaseController {
@Autowired
private SSOConfig ssoConfig;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
@Autowired private SSOService ssoService; @Autowired private IUserService userService; /** * 第二步 * 处理重定向请求的控制器方法 * * @param url 重定向的目标 URL * @param user 当前发起登录请求的用户名 * @param req HttpServletRequest 对象,用于获取请求信息 * @param resp HttpServletResponse 对象,用于发送响应 * @throws Exception 如果在处理请求过程中发生异常 */ @GetMapping("/api/redirect") public void redirect(@RequestParam String url, @RequestParam String user, HttpServletRequest req, HttpServletResponse resp) throws Exception { // 获取当前请求的会话对象 HttpSession session = req.getSession(); // 将当前发起登录请求的用户名存储在会话中 session.setAttribute("username", user); // 记录日志,打印当前用户名 log.info(user); // 记录日志,打印当前用户的 JSON 字符串表示 log.info(JSONUtil.toJsonStr(super.getCurrentUser())); // 执行重定向操作,将用户重定向到指定的 URL resp.sendRedirect(url); } /** * 第三步 * 处理单点登录认证请求的控制器方法 * * @param request 认证请求参数 * @param state 认证状态参数 * @param httpServletResponse HttpServletResponse 对象,用于发送响应 * @param req HttpServletRequest 对象,用于获取请求信息 * @throws IOException 如果在处理请求过程中发生 I/O 异常 */ @GetMapping("/sso") void authn( @RequestParam(name = "request", defaultValue = "") String request, @RequestParam(name = "state", defaultValue = "") String state, HttpServletResponse httpServletResponse, HttpServletRequest req ) throws IOException { // 获取当前请求的会话对象 HttpSession session = req.getSession(); // 从会话中获取请求用户的信息,如果不存在则默认为 "root" Object username = session.getAttribute("username"); if (username == null) { username = "root"; } // 根据用户名查询用户信息 User user = userService.findByName(String.valueOf(username)); // 如果用户不存在,抛出异常 if (user == null) { throw new FebsException("该用户名不存在"); } try { // 模拟延迟,这里可以根据实际需要进行调整或移除 Thread.sleep(2000); } catch (InterruptedException e) { // 如果线程被中断,抛出运行时异常 throw new RuntimeException(e); } // 根据认证请求和用户的 JdyCode 获取认证响应 String response = this.ssoService.getResponse(request, user.getJdyCode()); // 构造重定向 URL,将认证响应和状态参数传递给 ACS 服务器 httpServletResponse.sendRedirect( String.format( "%s?response=%s&state=%s&redirect_uri=https://www.jiandaoyun.com/app/xxxxxxxxx/entry/xxxxxxxx", this.ssoConfig.getAcs(), response, state ) ); } |
}