同济统一身份认证登录 1 系统
需求
为 1 系统的通知公告内容存档。参见 Github 项目。然而,请求内容需要 Cookies
,列表如下
1 | { |
否则会提示 session
不存在。那么,如何获取这两个 Cookies
就是我们这篇文章的主线。
过程
访问: https://1.tongji.edu.cn
首先,访问 https://1.tongji.edu.cn
,因为之前没有登录过,因此会被重定向到登录界面 https://iam.tongji.edu.cn
。
然而,这其中更细节的过程是什么?
使用 curl
进行测试。
1 | # -i 的意思是展示请求头 |
居然没有被重定向,而返回的是 200 OK
。推测:从 1.tongji.edu.cn
重定向到其他网站应该是通过 js
实现的。
在浏览器中进一步排查,使用的方法比较原始。在 Console
中输入 debugger
,会逐点暂停,可以观察到每一步的变化。
在 app.23886001cadcb91ff1bc.js
中,存在
1 | if (o) |
执行到此,地址栏会被替换为 https://1.tongji.edu.cn/ssologin
。
而后可能会进行是否登录的验证。如果没有登录过,在这一函数
1 | created: function() { |
跳转到:https://1.tongji.edu.cn/api/ssoservice/system/loginIn
跳转到 https://1.tongji.edu.cn/api/ssoservice/system/loginIn
方法是 GET
,返回的非平凡的内容有:
- Cookie:
JESSIONID
- 返回头中的
Location
注意,1.tongji
有一个 JSESSION
,iam.tongji
也有一个,两个是不一样的。
因为返回的状态码是 302
,重定向,因此返回头中的 Location
字段存放了下一个要请求的地址。
跳转到 https://iam.tongji.edu.cn/idp/oauth2/authorize?xxx
方法是 GET
,返回的非平凡内容有:
- Cookie:
_idp_authn_lc_key
- Cookie:
SESSION
- 返回头中的
Location
跳转到 https://iam.tongji.edu.cn:443/idp/AuthnEngine?xxx
方法是 GET
,返回的非平凡内容有:
- 返回头中的
Location
跳转到 https://iam.tongji.edu.cn:443/idp/authcenter/ActionAuthChain?xxx
这一步似乎已经不需要了,直接会跳转到不含 443 的部分。
方法是 GET
,返回的非平凡内容有:
- 返回头中的
Location
跳转到 https://iam.tongji.edu.cn/idp/authcenter/ActionAuthChain?xxx
方法是 GET
,返回 200 OK
,不需要额外处理。等待输入。
稍适休息
前面的步骤都可以用一个 session
搞定,因为 session
会自动搞定重定向和 Cookie
的事情。换句话说,Cookie
不用显式写在请求头中。
目前为止,我们获得了什么呢?
JSESSIONID
SESSION
_idp_authn_lc_key
可以回顾一下这些 Cookie
都是在哪步获得的。
接下来,需要进行登录操作。如果在浏览器中点击登录,页面就会跳转,能获取到的第一个页面是向 AuthnEngine?
发送的请求。然而要是真的向它第一次发送请求,就会有问题:获取不到后续必要的 Cookie
,换言之,就是验证失败了。为什么呢?
通过一步步排查 js
,发现在点击按钮后,在 secondAuth.js?date=202211232022
中会有这样一个函数发送网络请求:
1 | function doSubmit(usernameId) { |
向 https://iam.tongji.edu.cn/idp/authcenter/ActionAuthChain?xxx
发送请求
具体发送什么,上面的代码块注释已经说的很清楚了。要补充的一点是,需要设置好 Content-type
和 Content-Length
,不然不会得到 Set-Cookie
字段。
如果登录成功,会返回:
1 | { |
如果登录失败,会返回一个 XML
格式内容,提示要加强认证,也就是手机号或者邮箱接收验证码;或者是登录失败,还有 %d
次尝试机会。要是触发了加强认证,用邮箱是比较好解决的。
如果加强认证
向 https://iam.tongji.edu.cn/idp/sendCheckCode.do
发送请求,请求发送验证码。
方法为 POST
,内容是 url 编码的学号和类别。类别有:sms
和 email
,分别表示手机和邮箱。
如何从邮箱中获得验证码就不再赘述了。本质上是一个简单的 IMAP
服务。
向 https://iam.tongji.edu.cn/idp/AuthnEngine?xxx
发送请求
该有的还得有,给这个链接发送内容也是必要的。
发送的内容是一样的,再发送一次,可以得到
- Cookie:
_idp_session
- Location
这里注意,如果不需要加强认证,连接中的一个参数是:currentAuth=urn_oasis_names_tc_SAML_2.0_ac_classes_SMSUsernamePassword
;如果需要加强认证,对应的参数是:currentAuth=urn_oasis_names_tc_SAML_2.0_ac_classes_BAMUsernamePassword
。
SMS
应该是 Short Message Service 的意思,而 BAM
多半是 Basic Authentication Method
的意思。
跳转到 https://iam.tongji.edu.cn:443/idp/profile/OAUTH2/AuthorizationCode/SSO?xxx
注意需要重新设置一下请求头,不要再带着
Content-xxx
了!
方法是 GET
,可以得到
- Cookie:
_idp_authn_lc_key
是不是有些眼熟? - Location
跳转到 https://1.tongji.edu.cn/api/ssoservice/system/loginIn?xxx
终于到了 1 系统的地界了!
我们已经有 JSESSIONID
了。跳转到的这个链接是不是很眼熟(看看第二个 section)?由于之前获取到的 JSESSIONID
并没有过期,所以我们可以使用原 Cookie
来访问。
当前链接会返回一个 302
,给我们重定向到下面的链接。
跳转到 http://1.tongji.edu.cn/ssologin?token=xxx&uid=yyy&ts=timestamp
和前面跳转到 iam
不同,这次我们跳转到了 1 系统,这个链接同时包含了
1 | { |
这三个东西很重要,后续请求的时候需要它,来获得 sessionid
。
结束了。当前链接会返回一个 200 OK
,然而,我们还缺少一个 sessionid
没有获得呢!
注意到 Network
中有一个向 https://1.tongji.edu.cn/api/sessionservice/session/login
发送的 POST
请求,设置了这一 Cookie
。
向 https://1.tongji.edu.cn/api/sessionservice/session/login
发送请求
发送的是 POST
请求,发送的内容就是刚刚提到的三元组。
返回的非平凡内容有:
- Cookie:
sessionid
结束
到此为止,我们获得了全部需要的 Cookies
,完结撒花。
至于说如何进行内容的加密、编码,以及如何模拟请求,会有的。