安卓端借助Jsoup登录SRM大学Academia站点失败的技术求助
登录失败核心原因
- 你当前的实现完全跳过了登录流程的前置步骤,直接向
signin.ac接口发送POST请求,没有携带服务端预先下发的会话标识、表单校验令牌,这是请求被拒的核心原因。 - 这类带OAuth交互的SSO登录站点,完整链路是「GET登录页→获取会话Cookie+页面内嵌的隐藏动态参数→携带上述凭证POST账号密码→手动跟随OAuth授权链路的多次重定向,逐步收集跳转过程中下发的会话Cookie→最终拿到主站的有效登录态」,绝非单步POST就能完成。
- 手动传入
JSESSIONID无效,是因为这个会话ID必须是服务端在你首次访问登录页时下发、和你的请求指纹、表单令牌绑定的有效上下文,随便填充的ID没有对应会话记录,会直接被服务端拦截。 - 你代码里硬编码的
client_portal、dcc、serviceurl等参数都是页面动态生成的临时值,硬编码很容易因为参数过期、值不匹配导致校验失败。
修正后的实现代码
- 第一步:先发起GET请求访问登录页,建立初始会话
全程所有请求复用同一个Cookie集合,不要中途新建会话,同时自动解析登录页里的所有隐藏表单字段,不再硬编码参数值:// 全局维护统一的会话Cookie容器,全链路复用 Map<String, String> sessionCookies = new HashMap<>(); String fixedUA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36"; Map<String, String> loginParams = new HashMap<>(); try { // 先GET登录页,拿初始Cookie Connection.Response loginPageResp = Jsoup.connect("https://academia.srmist.edu.in/accounts/signin.ac") .userAgent(fixedUA) .method(Connection.Method.GET) .execute(); sessionCookies.putAll(loginPageResp.cookies()); // 解析登录页所有隐藏表单字段 Document loginPageDoc = loginPageResp.parse(); for (Element hiddenInput : loginPageDoc.select("form input[type=hidden]")) { loginParams.put(hiddenInput.attr("name"), hiddenInput.attr("value")); } // 填入账号密码 loginParams.put("username", 你的用户名); loginParams.put("password", 你的密码); } catch (IOException e) { e.printStackTrace(); } - 第二步:携带初始会话和表单参数发POST登录请求,手动处理OAuth重定向链路
关键是关闭自动重定向,逐步收集每一步跳转下发的Cookie,不跳过任何OAuth授权环节:try { Connection.Response postLoginResp = Jsoup.connect("https://academia.srmist.edu.in/accounts/signin.ac") .data(loginParams) .cookies(sessionCookies) .userAgent(fixedUA) // 关闭自动重定向,手动跟踪OAuth跳转 .followRedirects(false) .method(Connection.Method.POST) .execute(); sessionCookies.putAll(postLoginResp.cookies()); // 手动跟完所有跳转 String nextRedirect = postLoginResp.header("Location"); while (nextRedirect != null) { // 补全相对路径 if (nextRedirect.startsWith("/")) { nextRedirect = "https://academia.srmist.edu.in" + nextRedirect; } Connection.Response redirectStep = Jsoup.connect(nextRedirect) .cookies(sessionCookies) .userAgent(fixedUA) .followRedirects(false) .execute(); sessionCookies.putAll(redirectStep.cookies()); nextRedirect = redirectStep.header("Location"); } } catch (IOException e) { e.printStackTrace(); } - 第三步:用全链路收集的完整会话访问主站
try { Document homePage = Jsoup.connect("https://academia.srmist.edu.in/") .cookies(sessionCookies) .userAgent(fixedUA) .get(); Log.d("login", "已登录页面内容:" + homePage.text()); } catch (IOException e) { e.printStackTrace(); }
高频踩坑提醒
- 全程User-Agent必须保持一致,中途更换请求指纹会导致服务端判定会话不匹配,直接返回未登录页面。
- 不要每步请求都新建Cookie集合,也不要手动填充没有来源的
JSESSIONID,所有Cookie都必须是服务端在请求链路中实际下发的,否则会话校验永远无法通过。 - 一定要把
followRedirects设为false手动跟踪跳转,Jsoup默认的自动重定向逻辑有时候会遗漏重定向过程中设置的Cookie,导致最后会话不完整,即便跳转到了主站也是未登录状态。 - 不要硬编码表单参数值,登录页的动态参数必须从页面实际解析后携带,硬编码的固定值会随着服务端参数更新直接失效。
- 如果请求被WAF拦截,可以补充和浏览器一致的
Accept、Accept-Language请求头,降低被识别为爬虫的概率。
内容的提问来源于stack exchange,提问作者Shubham Sharma
相关产品推荐
相关产品推荐

