问题分析
通过HttpClient获取网页数据源,通过Jsoup解析数据。先模拟登录统一身份认证平台,再通过单点登录方式登录正方教务系统,最后获取相关信息。模拟浏览器正常操作,封装请求头信息获取SESSIONID。
解决方案
Maven
<dependency><groupId>com.baidu.aip</groupId><artifactId>java-sdk</artifactId><version>4.8.0</version></dependency><dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.2</version></dependency><dependency><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.11.3</version></dependency><dependency><groupId>mons</groupId><artifactId>commons-lang3</artifactId><version>3.4</version></dependency><dependency><groupId>org.json</groupId><artifactId>json</artifactId><version>0810</version></dependency><dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.56</version></dependency>
登录统一身份认证平台
登录请求表单数据
密钥与加密密码均为Base64编码
常见加密:
1)数据加密标准(DES Data Encryption Standard):DES(密钥长度64位)(ECB模式)
2)分组密码算法:AES(密钥长度在128位及以上)(GCM或CBC模式)
3)流密码算法:AES(密钥长度在128位及以上)(OFB或CTR模式)、chacha20
4)哈希算法:SHA2、SHA3
5)密钥交换算法:DSA/DH(密钥长度2048位及以上)、ECDH(密钥长度223及以上)
6)HMAC(基于哈希的消息验证码)算法:HMAC-SHA2
7)非对称加密算法:RSA(2048位及以上)、ECC(256位以上)
DEC解密
此统一身份认证平台密码加密采用DES/ECB/PKCS7Padding方式加密。
相关加密解密方法,自行百度。
参考:https://shentuzhigang./article/details/107323907
密钥获取
在登录页面HTML代码中可以找到
模拟登录
package cn.edu.zstu.myzstu.spyder.sso;import cn.edu.zstu.myzstu.model.Student;import cn.edu.zstu.myzstu.utils.DESUtil;import cn.edu.zstu.myzstu.utils.httpclient.HTTPResponse;import cn.edu.zstu.myzstu.utils.httpclient.HttpClientUtils;import org.jsoup.Jsoup;import org.jsoup.nodes.Document;import org.jsoup.select.Elements;import org.ponent;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;/*** @Author ShenTuZhiGang* @Version 1.0.0* @Date -03-20 18:04*/@Componentpublic class SSOLoginer {private final String LOGIN_URL="https://sso./login";public boolean login(String username,String password){Document doc = Jsoup.parse(HttpClientUtils.doGetRequest(LOGIN_URL,null,null));String currentLoginType = doc.select("#current-login-type").html();String loginCroypto = doc.select("#login-croypto").html();String ssoSecond = doc.select("#sso-second").html();String userId = doc.select("#user-id").html();String userObjectId = doc.select("#user-object-id").html();String lphoneNumber = doc.select("#phone-number").html();String loginRuleType = doc.select("#login-rule-type").html();String loginPageFlowKey = doc.select("#login-page-flowkey").html();String captchaUrl = doc.select("#captcha-url").html();String redirectUri = doc.select("#redirect-uri").html();String loginBackUri = doc.select("#login-back-uri").html();String loginErrorCode = doc.select("#login-error-code").html();String recaptchaInvisible = doc.select("#recaptcha-invisible").html();Map<String,String> params=new HashMap<>();params.put("username",username);params.put("type",currentLoginType);params.put("_eventId","submit");params.put("geolocation","");params.put("execution",loginPageFlowKey);params.put("captcha_code","");params.put("croypto",loginCroypto);params.put("password", DESUtil.encrypt(loginCroypto,password));HTTPResponse httpResponse = HttpClientUtils.doPostRequest(LOGIN_URL, null, params);System.out.println(loginCroypto);System.out.println(DESUtil.encrypt(loginCroypto,password));System.out.println(httpResponse);return true;}}
注:HttpClient封装工具类,自行百度。
参考:https://shentuzhigang./article/details/104274609
登录正方教务系统
单点登录抓包
单点登录
package cn.edu.zstu.myzstu.spyder.edu;import cn.edu.zstu.myzstu.spyder.sso.SSOLoginer;import cn.edu.zstu.myzstu.utils.httpclient.HttpClientUtils;import org.springframework.beans.factory.annotation.Autowired;import org.ponent;import java.util.ArrayList;import java.util.List;/*** @Author ShenTuZhiGang* @Version 1.0.0* @Date -07-13 23:36*/@Componentpublic class EduSSOLoginer {@Autowiredprivate SSOLoginer ssoLoginer=new SSOLoginer();public boolean login(String username,String password){if(ssoLoginer.login(username,password)){String location= HttpClientUtils.doGetRequest("https://sso./login?service=http%3A%2F%2Fjw.%2Fsso%2Fjasiglogin",null,null);int i;List<String> list = new ArrayList<>();for(i=0 ;i<6;i++){//如果是重定向,则继续请求。if(location.contains("http")&&location.length()<150){list.add(location);location = HttpClientUtils.doGetRequest(location,null,null);}else{break;}}System.out.println(i);for (String str:list) {System.out.println(str);}return true;}return false;}}
测试
@Testpublic void Gradetest4() throws Exception {System.out.println("Gradetest4");EduSpyder eduSpyder = new EduSpyder();EduSSOLoginer eduSSOLoginer = new EduSSOLoginer();GradeParser gradeParser = new GradeParser();List<Grade> data = null;try {if(eduSSOLoginer.login("username","password")) {data = gradeParser.parse(eduSpyder.crawlGrades(new Student()));}} catch (Exception e) {throw e;}List<Grade> scoreList= data;for(Grade score:scoreList){System.out.println(score);}System.out.println(scoreList.size());}
//获取成绩信息页面public String crawlGrades(Student stu) {Map<String,String>scoreParams=new HashMap<>();scoreParams.put("xnm","");scoreParams.put("xqm","");scoreParams.put("_search","false");scoreParams.put("nd",""+new Date().getTime());scoreParams.put("queryModel.showCount","100");scoreParams.put("queryModel.currentPage","1");scoreParams.put("queryModel.sortName","");scoreParams.put("queryModel.sortOrder","asc");scoreParams.put("time","1");try {String scoreResponse = HttpClientUtils.doPostRequest(CHECK_GRADE_URL,null,scoreParams).getContent();return scoreResponse;}catch (Exception e){e.printStackTrace();}return null;}
注:成绩页面解析与成绩类等,自行编写。
参考:https://shentuzhigang./article/details/104262854
运行结果
参考文章
https://shentuzhigang./article/details/107323907
https://shentuzhigang./article/details/103996741
https://shentuzhigang./article/details/104262854
JAVA——基于HttpClient的通过单点登录方式(统一身份认证平台)登录正方教务系统[1999-]基本解决方案