新增物理实验选课系统登录接口

old-package
lensfrex 2 years ago
parent f352b34b6f
commit 8877539fef
Signed by: lensfrex
GPG Key ID: 0F69A0A2FBEE98A0
  1. 9
      mywust-core/src/main/java/cn/linghang/mywust/core/api/PhysicsSystem.java
  2. 20
      mywust-core/src/main/java/cn/linghang/mywust/core/parser/physics/PhysicsIndexPageParser.java
  3. 5
      mywust-core/src/main/java/cn/linghang/mywust/core/parser/physics/xpath/PhysicsIndexXpath.java
  4. 63
      mywust-core/src/main/java/cn/linghang/mywust/core/request/PhysicsSystemRequestFactory.java
  5. 58
      mywust-core/src/main/java/cn/linghang/mywust/core/service/auth/PhysicsLogin.java
  6. 5
      mywust-network/src/main/java/cn/linghang/mywust/network/HttpRequest.java
  7. 6
      mywust-network/src/main/java/cn/linghang/mywust/network/HttpResponse.java
  8. 44
      mywust-test/src/test/java/WlsyLoginTest.java
  9. 5
      mywust-util/src/main/java/cn/linghang/mywust/util/StringUtil.java

@ -0,0 +1,9 @@
package cn.linghang.mywust.core.api;
public class PhysicsSystem {
public static final String PHYSICS_LOGIN_INDEX = "http://wlsy.wust.edu.cn/Page/BI/BI000.aspx";
public static final String PHYSICS_LOGIN_COOKIES_API = "http://wlsy.wust.edu.cn/Page/BI/BI000.aspx";
public static final String PHYSICS_MAIN_INDEX_URL = "http://wlsy.wust.edu.cn/Page/BI/BI0000.aspx";
}

@ -0,0 +1,20 @@
package cn.linghang.mywust.core.parser.physics;
import cn.linghang.mywust.core.exception.HtmlPageParseException;
import cn.linghang.mywust.core.parser.Parser;
import cn.linghang.mywust.core.parser.physics.xpath.PhysicsIndexXpath;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
public class PhysicsIndexPageParser implements Parser<String> {
public String parse(String html) throws HtmlPageParseException {
Document page = Jsoup.parse(html);
Elements linkElements = page.selectXpath(PhysicsIndexXpath.PHYSICS_LINK_XPATH);
if (linkElements.isEmpty()) {
throw new HtmlPageParseException();
}
return linkElements.get(0).attr("href");
}
}

@ -0,0 +1,5 @@
package cn.linghang.mywust.core.parser.physics.xpath;
public class PhysicsIndexXpath {
public static final String PHYSICS_LINK_XPATH = "//*[@id=\"rolemenu\"]/tbody/tr[1]/td[1]/a[2]";
}

@ -0,0 +1,63 @@
package cn.linghang.mywust.core.request;
import cn.linghang.mywust.core.api.PhysicsSystem;
import cn.linghang.mywust.network.HttpRequest;
import cn.linghang.mywust.util.StringUtil;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
public class PhysicsSystemRequestFactory extends RequestFactory {
public static HttpRequest loginIndexRequest() {
return makeHttpRequest(PhysicsSystem.PHYSICS_LOGIN_INDEX);
}
public static HttpRequest loginCookiesRequest(String username, String password, String cookies) {
byte[] queryData = StringUtil.generateQueryString(makeLoginQueryParam(username, password)).getBytes(StandardCharsets.UTF_8);
return makeHttpRequest(PhysicsSystem.PHYSICS_LOGIN_COOKIES_API, queryData, cookies);
}
public static HttpRequest mainIndexRequest(String cookies) {
return makeHttpRequest(PhysicsSystem.PHYSICS_MAIN_INDEX_URL, null, cookies);
}
public static HttpRequest physicsSystemIndexRequest(String redirect, String cookies) {
return makeHttpRequest(redirect, null, cookies);
}
private static Map<String, String> makeLoginQueryParam(String username, String password) {
// 这几个算是是写死了的,也能用
// 但其实最好还是从首页动态获取某些关键字段("__VIEWSTATE")
// 这种办法等后面有时间了再实现
Map<String, String> queryParams = new HashMap<>(12);
queryParams.put("__EVENTTARGET", "");
queryParams.put("__EVENTARGUMENT", "");
queryParams.put("__VIEWSTATE", VIEW_STATE);
queryParams.put("__VIEWSTATEGENERATOR", "F42971E6");
queryParams.put("hidUserID", "");
queryParams.put("hidUserPassWord", "");
queryParams.put("txtUserID", "请输入职工号或学号");
queryParams.put("txtUsername", username);
queryParams.put("txtPassword", password);
queryParams.put("btnLogin.x", "83");
queryParams.put("btnLogin.y", "29");
queryParams.put("cbSaveInfo", "on");
return queryParams;
}
private static final String VIEW_STATE =
"/wEPDwULLTEwNTgzMzY4NTgPZBYCZg9kFgICCQ9kFgJmD2QWBgINDw9kFgIeBVN0" +
"eWxlBZsBbGluZS1oZWlnaHQ6NThweDtwYWRkaW5nLWxlZnQ6NDVweDtwYWRkaW5n" +
"LXRvcDowcHg7d2lkdGg6MzE1cHg7aGVpZ2h0OjU0cHg7YmFja2dyb3VuZDp1cmwo" +
"Li4vLi4vUmVzb3VyY2UvQmFzaWNJbmZvL25ld0JHL+eUqOaIt+WQjS5wbmcpIG5v" +
"LXJlcGVhdCAwcHggMHB4OztkAg8PD2QWAh8ABZsBbGluZS1oZWlnaHQ6NThweDtw" +
"YWRkaW5nLWxlZnQ6NDVweDtwYWRkaW5nLXRvcDowcHg7d2lkdGg6MzE1cHg7aGVp" +
"Z2h0OjU0cHg7YmFja2dyb3VuZDp1cmwoLi4vLi4vUmVzb3VyY2UvQmFzaWNJbmZv" +
"L25ld0JHL+Wvhueggeepui5wbmcpIG5vLXJlcGVhdCAwcHggMHB4OztkAhkPDxYC" +
"HgRUZXh0BRvns7vnu5/orr/pl67kurrmrKHvvJozNjc2MDJkZBgBBR5fX0NvbnRy" +
"b2xzUmVxdWlyZVBvc3RCYWNrS2V5X18WBQULaW1nQnRuQ2xvc2UFCGxidGJTYXZl" +
"BQpsYnRuQ2FuY2VsBQhidG5Mb2dpbgUKY2JTYXZlSW5mb6K8UayJuWe2OSRVqLDo" +
"2J4wMKAT";
}

@ -0,0 +1,58 @@
package cn.linghang.mywust.core.service.auth;
import cn.linghang.mywust.core.exception.BasicException;
import cn.linghang.mywust.core.exception.PasswordWornException;
import cn.linghang.mywust.core.parser.physics.PhysicsIndexPageParser;
import cn.linghang.mywust.core.request.PhysicsSystemRequestFactory;
import cn.linghang.mywust.network.HttpRequest;
import cn.linghang.mywust.network.HttpResponse;
import cn.linghang.mywust.network.RequestClientOption;
import cn.linghang.mywust.network.Requester;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
public class PhysicsLogin {
private static final Logger log = LoggerFactory.getLogger(PhysicsLogin.class);
private final Requester requester;
private static final PhysicsIndexPageParser physicsIndexPageParser = new PhysicsIndexPageParser();
public PhysicsLogin(Requester requester) {
this.requester = requester;
}
public String getLoginCookie(String username, String password, RequestClientOption requestClientOption) throws IOException, BasicException {
// 直接登录,ASP.NET_SessionId其实在这步就能获取到,不需要再请求一遍首页获取
HttpRequest loginCookieRequest = PhysicsSystemRequestFactory.loginCookiesRequest(username, password, null);
HttpResponse loginCookieResponse = requester.post(loginCookieRequest, requestClientOption);
if (loginCookieResponse.getStatusCode() != HttpResponse.HTTP_REDIRECT_302) {
throw new PasswordWornException();
}
String loginCookies = loginCookieResponse.getCookies();
if (loginCookies == null) {
throw new PasswordWornException();
}
// 请求主页,获取实验选课系统的链接,顺便测试获取到的cookie是否有效,主页能否正常访问
HttpRequest indexRequest = PhysicsSystemRequestFactory.mainIndexRequest(loginCookies);
HttpResponse indexResponse = requester.get(indexRequest, requestClientOption);
if (indexResponse.getStatusCode() != HttpResponse.HTTP_OK || indexResponse.getBody() == null) {
throw new BasicException();
}
// 登录实验选课系统,因为之前使用的登录接口和真正的物理实验选课系统是两个不一样的系统,
// 因此需要再次带上cookie请求一遍真正的物理实验选课系统,cookie才能在后面的接口中生效
String indexHtml = new String(indexResponse.getBody());
String redirect = physicsIndexPageParser.parse(indexHtml);
HttpRequest systemIndexRequest = PhysicsSystemRequestFactory.physicsSystemIndexRequest(redirect, loginCookies);
requestClientOption.setFallowUrlRedirect(true);
requester.get(systemIndexRequest, requestClientOption);
return loginCookies;
}
}

@ -38,6 +38,11 @@ public class HttpRequest {
return this; return this;
} }
public HttpRequest addHeaders(String key, String value) {
this.headers.put(key, value);
return this;
}
@Override @Override
public String toString() { public String toString() {
final StringBuffer sb = new StringBuffer("HttpRequest{"); final StringBuffer sb = new StringBuffer("HttpRequest{");

@ -7,8 +7,14 @@ import java.util.Map;
@Data @Data
public class HttpResponse { public class HttpResponse {
public static final int HTTP_OK = 200; public static final int HTTP_OK = 200;
public static final int HTTP_RESOURCE_CREATED = 201;
public static final int HTTP_REDIRECT_301 = 301;
public static final int HTTP_REDIRECT_302 = 302;
public static final int HTTP_FORBIDDEN = 403; public static final int HTTP_FORBIDDEN = 403;
public static final int HTTP_NOT_FOUND = 404; public static final int HTTP_NOT_FOUND = 404;
public static final int HTTP_SERVER_ERROR = 500; public static final int HTTP_SERVER_ERROR = 500;
public static final int HTTP_SERVICE_UNAVAILABLE = 503; public static final int HTTP_SERVICE_UNAVAILABLE = 503;

@ -0,0 +1,44 @@
import cn.linghang.mywust.core.exception.BasicException;
import cn.linghang.mywust.core.service.auth.PhysicsLogin;
import cn.linghang.mywust.network.RequestClientOption;
import cn.linghang.mywust.network.Requester;
import cn.linghang.mywust.network.okhttp.SimpleOkhttpRequester;
import java.io.IOException;
import java.util.Scanner;
public class WlsyLoginTest {
public static void main(String[] args) throws BasicException, IOException {
new WlsyLoginTest().run();
}
private void run() throws BasicException, IOException {
System.out.println("物理实验登陆测试");
System.out.println("输入账号(学号)和密码,用“ ”(空格)分割");
Scanner scanner = new Scanner(System.in);
String input = scanner.nextLine();
String username = input.split(" ")[0];
String password = input.split(" ")[1];
System.out.println("账号:" + username);
System.out.println("密码:" + password);
Requester requester = new SimpleOkhttpRequester();
PhysicsLogin physicsLogin = new PhysicsLogin(requester);
RequestClientOption option = RequestClientOption.DEFAULT_OPTION;
RequestClientOption.Proxy proxy = new RequestClientOption.Proxy();
proxy.setAddress("127.0.0.1");
proxy.setPort(8794);
option.setProxy(proxy);
String cookies = physicsLogin.getLoginCookie(username, password, option);
System.out.printf("获取到的cookies: %s \n", cookies);
// System.out.printf("检查Cookies: %s", libraryLogin.checkCookie(cookies));
}
}

@ -2,6 +2,8 @@ package cn.linghang.mywust.util;
import com.google.common.base.Joiner; import com.google.common.base.Joiner;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -14,6 +16,9 @@ public class StringUtil {
* @return 生成的表单请求字符串 * @return 生成的表单请求字符串
*/ */
public static String generateQueryString(Map<String, String> queryParams) { public static String generateQueryString(Map<String, String> queryParams) {
// 自动对value值进行url编码
queryParams.forEach((k, v) -> queryParams.put(k, URLEncoder.encode(v, StandardCharsets.UTF_8)));
return Joiner.on('&') return Joiner.on('&')
.useForNull("") .useForNull("")
.withKeyValueSeparator('=') .withKeyValueSeparator('=')

Loading…
Cancel
Save