论如何优雅的将自己的服务接入学校的 CAS 统一认证系统
起因
前几天跟同学聊起一个希望建立校友交流论坛的想法,讨论之中有人表示如果能用学校的统一认证系统登录的话,就可以大大简化注册门槛。于是我开始研究学校的统一认证系统起来……
了解原理
首先我希望找一个使用统一认证系统的学校服务进行测试,在这里,我选择了学校的一站式服务平台,当在尚未登录账号是访问该网站,则会被跳转至统一认证系统进行认证:
可以看到此时的网页链接为 https://cas.xaufe.edu.cn/login?service=http%3A%2F%2Fmy.xaufe.edu.cn%2Fcjmh%2FcasAuth%3FredirectUrl%3Dmy.xaufe.edu.cn%2Fnewcjmh
,配合尝试登录时浏览器产生的网络流:
我们可以得知,该验证系统在登录通过后会 302 跳转到 service 字段所指向的网址,并在 GET 请求中携带一个 ticket
,如此一来,我们就大致得知了这套统一认证系统的大致使用流程。但是截至现在,我们仍未知道 ticket
的作用,为此,我查询了大量资料,最终,在 这个网站 得到了我想要的答案:
也就是说,当服务器拿到 ticket
以后,会立刻向 CAS 服务器的 /serviceValidate
路由发起一个 GET 请求,并携带 service
和 ticket
参数,最后,服务器将会返回用户信息。
当我们知道了这些全部原理后,我们便可以开始将自己的服务对接到这套统一认证系统中。
实践环节
通过开发一个 Spring Boot Web 应用,我尝试对接了 CAS 系统,但是,在实践环节中,我遇到了几个问题:
首先,我发现 CAS 系统的 service
字段允许提交的网址存在访问控制,当我们尝试使用一个不在白名单内的服务地址时,便会产生访问错误:
但是后来我发现,这只是因为我没有在 service 中提供 http://
头,加上以后,问题便得到了解决(这也要归功于学校为了方便可能允许了所有 HTTP 服务使用认证)
接下来,当我获得 ticket
并试图访问 /serviceValidate
路由时,我得到了一个 403 错误:
这也就意味着,需要通过校园网络才能正常验证。但是,由于学校提供了 WebVPN,因此我们只需要通过 WebVPN 访问该路由即可。
但当我手动从 WebVPN 访问该路由,并携带正确的 ticket
时,我却总是得到一个无法识别 ticket 的错误。后来经过查询,我得知可能是因为 ticket
从发放到验证的过程有一个 timeout,必须在指定时间内进行验证,否则就会导致 ticket 失效。
因此最后,我编写了一个简单的 Controller:该 Controller 负责识别 ticket 并通过 WebVPN 访问 /serviceValidate
进行验证:
在这个过程中,由于 WebVPN 也同样需要登录,方便起见,我直接抓取了 WebVPN 的 cookie,以绕过登录过程(其实由于 WebVPN 服务也使用统一认证系统,因此这里可以进行两次验证 —— 一次登录 WebVPN,一次登录自己的服务)
最后,在 localhost:8080
运行 Spring Boot 服务,并访问 https://cas.xaufe.edu.cn/login?service=http://localhost:8080/check
,我成功得到了用户信息:
至此,我们成功将自己的服务接入到了 CAS 认证系统。
最后
其实这套系统还有其不足的地方,但是无论如何,通过这么一阵子下来,我们成功找到了对接服务器 CAS 统一认证系统的方法,这也方便了日常的使用。