最近需要将内部系统与简道云做对接,在实现单点登录时参考官方文档时比较繁琐,技术支持人员也说的不够清楚,其实就是参考下面这幅图的调用过程,其中第2,3步都是访问的公司内部系统接口,通过这两次的请求来确认用户身份,进行登录验证。
初看这张图时,没有明白怎么在第三步验证用户的信息,其实就是在第二步请求内部接口时,对请求直接进行重定向,并同时带入用户的信息,然后在第三步接收重定向带来的参数,用此进行登录的校验。
下面是基于Java代码的实现,只需要在controller中新增两个方法即可。
@Slf4j
@Controller
@NoArgsConstructor
@AllArgsConstructor
class SSOController extends BaseController {
@Autowired
private SSOConfig ssoConfig;
@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
)
);
}
}