匆忙写的教务处登录接口,坑还很多

old-package
lensfrex 2 years ago
parent e03fb17395
commit 4bb358cc05
Signed by: lensfrex
GPG Key ID: 0F69A0A2FBEE98A0
  1. 12
      mywust-core/pom.xml
  2. 15
      mywust-core/src/main/java/cn/linghang/mywust/core/api/JwcApiUrl.java
  3. 4
      mywust-core/src/main/java/cn/linghang/mywust/core/exception/BasicException.java
  4. 4
      mywust-core/src/main/java/cn/linghang/mywust/core/exception/PasswordWornException.java
  5. 41
      mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/AuthRequestGenerator.java
  6. 62
      mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/JwcLogin.java
  7. 6
      mywust-network-okhttp/pom.xml
  8. 27
      mywust-network-okhttp/src/main/java/cn/linghang/mywust/network/okhttp/SimpleOkhttpRequester.java
  9. 59
      mywust-network-okhttp/src/main/java/cn/linghang/mywust/network/okhttp/TrustAllCert.java
  10. 1
      mywust-network/src/main/java/cn/linghang/mywust/network/RequestClientOption.java
  11. 31
      mywust-test/pom.xml
  12. 39
      mywust-test/src/test/java/JwcLoginTest.java
  13. 7
      mywust-util/pom.xml
  14. 37
      mywust-util/src/main/java/cn/linghang/mywust/util/StringUtil.java

@ -17,6 +17,17 @@
<version>0.0.1-dev</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>cn.linghang</groupId>
<artifactId>mywust-util</artifactId>
<version>0.0.1-dev</version>
</dependency>
<dependency>
<groupId>net.sourceforge.jregex</groupId>
<artifactId>jregex</artifactId>
<version>1.2_01</version>
</dependency>
</dependencies>
<properties>
@ -24,5 +35,4 @@
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

@ -0,0 +1,15 @@
package cn.linghang.mywust.core.api;
import lombok.Getter;
@Getter
public class JwcApiUrl {
/**
* 统一认证登录验证的api地址请求之后可进一步获取ticket
*/
public static final String UNION_AUTH_API = "https://auth.wust.edu.cn/lyuapServer/v1/tickets";
public static final String JWC_SSO_SERVICE = "http://bkjx.wust.edu.cn/jsxsd/sso.jsp";
public static final String JWC_TICKET_API = "http://bkjx.wust.edu.cn/jsxsd/sso.jsp?ticket=%s";
}

@ -0,0 +1,4 @@
package cn.linghang.mywust.core.exception;
public class BasicException extends Exception {
}

@ -0,0 +1,4 @@
package cn.linghang.mywust.core.exception;
public class PasswordWornException extends BasicException {
}

@ -0,0 +1,41 @@
package cn.linghang.mywust.core.service.undergraduate;
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 AuthRequestGenerator {
public static HttpRequest unionLoginTGTRequest(String username, String password, String service) {
Map<String, String> requestForm = new HashMap<>();
requestForm.put("username", username);
requestForm.put("password", password);
requestForm.put("service", service);
requestForm.put("loginType", "");
String queryString = StringUtil.generateQueryString(requestForm);
HttpRequest request = new HttpRequest();
request.setData(queryString.getBytes(StandardCharsets.UTF_8));
return request;
}
public static HttpRequest loginTicketRequest(String service) {
Map<String, String> requestForm = new HashMap<>();
requestForm.put("service", service);
String queryString = StringUtil.generateQueryString(requestForm);
HttpRequest request = new HttpRequest();
request.setData(queryString.getBytes(StandardCharsets.UTF_8));
return request;
}
public static HttpRequest sessionCookieRequest() {
return new HttpRequest();
}
}

@ -1,7 +1,65 @@
package cn.linghang.mywust.core.service.undergraduate;
import cn.linghang.mywust.core.api.JwcApiUrl;
import cn.linghang.mywust.core.exception.BasicException;
import cn.linghang.mywust.core.exception.PasswordWornException;
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 java.io.IOException;
import java.net.URL;
public class JwcLogin {
public String getLoginCookie(String user, String password) {
return "";
// 默认5秒超时
private static final int DEFAULT_TIMEOUT = 5;
private final Requester requester;
public JwcLogin(Requester requester) {
this.requester = requester;
}
public String getLoginCookie(String username, String password, RequestClientOption requestOption) throws IOException, BasicException {
// 获取ticket granting ticket(TGT)
HttpRequest TGTRequest = AuthRequestGenerator.unionLoginTGTRequest(username, password, JwcApiUrl.JWC_SSO_SERVICE);
HttpResponse unionAuthResponse = requester.post(new URL(JwcApiUrl.UNION_AUTH_API), TGTRequest, requestOption);
String redirectAddress = unionAuthResponse.getHeaders().get("Location");
if (redirectAddress == null) {
throw new PasswordWornException();
}
// 获取服务ticket(service ticket,st)
HttpRequest serviceTicketRequest = AuthRequestGenerator.loginTicketRequest(JwcApiUrl.JWC_SSO_SERVICE);
HttpResponse serviceTicketResponse =
requester.post(new URL(redirectAddress.replace("http:", "https:")), serviceTicketRequest, requestOption);
byte[] serviceTicketResponseData = serviceTicketResponse.getBody();
if (serviceTicketResponseData == null) {
System.err.println("获取服务st出错,serviceTicketResponseData == null");
throw new BasicException();
}
String serviceTicket = new String(serviceTicketResponseData);
// 获取登录cookie(session)
HttpRequest sessionRequest = AuthRequestGenerator.sessionCookieRequest();
HttpResponse sessionResponse = requester.get(new URL(String.format(JwcApiUrl.JWC_TICKET_API, serviceTicket)), sessionRequest, requestOption);
String cookies = sessionResponse.getCookies();
if (cookies == null || !cookies.contains("JSESSIONID") || !cookies.contains("SERVERID")) {
System.err.println("获取服务session cookie出错,关键Cookie缺失");
System.err.println("Cookies: " + cookies);
throw new BasicException();
}
return cookies;
}
private void getLoginGTG(String username, String password) {
}
}

@ -48,6 +48,12 @@
<artifactId>mywust-network</artifactId>
<version>0.0.1-dev</version>
</dependency>
<dependency>
<groupId>cn.linghang</groupId>
<artifactId>mywust-util</artifactId>
<version>0.0.1-dev</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

@ -4,6 +4,7 @@ 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 cn.linghang.mywust.util.StringUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.*;
@ -15,6 +16,7 @@ import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;
/**
@ -105,7 +107,9 @@ public class SimpleOkhttpRequester implements Requester {
private OkHttpClient buildClient(OkHttpClient.Builder builder, RequestClientOption requestClientOption) {
builder.callTimeout(requestClientOption.getTimeout(), TimeUnit.SECONDS)
.readTimeout(requestClientOption.getTimeout(), TimeUnit.SECONDS)
.connectTimeout(requestClientOption.getTimeout(), TimeUnit.SECONDS);
.connectTimeout(requestClientOption.getTimeout(), TimeUnit.SECONDS)
.sslSocketFactory(TrustAllCert.getSSLSocketFactory(), TrustAllCert.getX509TrustManager())
.hostnameVerifier(TrustAllCert.getHostnameVerifier());
// 设置代理
RequestClientOption.Proxy proxyOption = requestClientOption.getProxy();
@ -159,8 +163,12 @@ public class SimpleOkhttpRequester implements Requester {
*/
private MediaType getMediaType(HttpRequest httpRequest) {
// 按照指定的Content-Type设置MediaType,不指定的话按form处理
String contentType = httpRequest.getHeaders().get("Content-Type");
MediaType mediaType;
Map<String, String> headers = httpRequest.getHeaders();
if (headers == null) {
return MediaType.get(DEFAULT_CONTENT_TYPE);
}
String contentType = headers.get("Content-Type");
if (!"".equals(contentType)) {
return MediaType.get(contentType);
} else {
@ -180,9 +188,14 @@ public class SimpleOkhttpRequester implements Requester {
Request.Builder requestBuilder = new Request.Builder().url(url);
Map<String, String> requestHeaders = httpRequest.getHeaders();
if (requestHeaders != null) {
requestHeaders.forEach(requestBuilder::header);
}
requestBuilder.header("Cookie", httpRequest.getCookies());
String requestCookie = httpRequest.getCookies();
if (requestCookie != null) {
requestBuilder.header("Cookie", requestCookie);
}
if (requestMethod == RequestMethod.GET) {
requestBuilder.get();
@ -218,7 +231,7 @@ public class SimpleOkhttpRequester implements Requester {
// 取所有的响应头,如果同一个响应头字段有多个值只拿第一个
Map<String, List<String>> responseHeaders = response.headers().toMultimap();
Map<String, String> headerMap = new HashMap<>();
Map<String, String> headerMap = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
responseHeaders.forEach((k, v) -> headerMap.put(k, v.get(0)));
httpResponse.setHeaders(headerMap);
@ -229,7 +242,9 @@ public class SimpleOkhttpRequester implements Requester {
httpResponse.setBody(body.bytes());
}
httpResponse.setCookies(response.header("Set-Cookie"));
// 提取Cookie
List<String> cookieHeaders = response.headers("Set-Cookie");
httpResponse.setCookies(StringUtil.parseCookie(cookieHeaders));
return httpResponse;
}

@ -0,0 +1,59 @@
package cn.linghang.mywust.network.okhttp;
import javax.net.ssl.*;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;
import java.util.Arrays;
public class TrustAllCert {
public static SSLSocketFactory getSSLSocketFactory() {
try {
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, getTrustManager(), new SecureRandom());
return sslContext.getSocketFactory();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static TrustManager[] getTrustManager() {
return new TrustManager[]{
new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) {
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
}
};
}
public static HostnameVerifier getHostnameVerifier() {
return (s, sslSession) -> true;
}
public static X509TrustManager getX509TrustManager() {
X509TrustManager trustManager = null;
try {
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore) null);
TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
throw new IllegalStateException("Unexpected default trust managers:" + Arrays.toString(trustManagers));
}
trustManager = (X509TrustManager) trustManagers[0];
} catch (Exception e) {
e.printStackTrace();
}
return trustManager;
}
}

@ -6,6 +6,7 @@ import lombok.Data;
public class RequestClientOption {
private Proxy proxy;
private long timeout;
private boolean fallowUrlRedirect = false;
@Data
public static class Proxy {

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.linghang</groupId>
<artifactId>mywust-test</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>cn.linghang</groupId>
<artifactId>mywust-core</artifactId>
<version>0.0.1-dev</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>cn.linghang</groupId>
<artifactId>mywust-network-okhttp</artifactId>
<version>1.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

@ -0,0 +1,39 @@
import cn.linghang.mywust.core.exception.BasicException;
import cn.linghang.mywust.core.service.undergraduate.JwcLogin;
import cn.linghang.mywust.network.RequestClientOption;
import cn.linghang.mywust.network.okhttp.SimpleOkhttpRequester;
import cn.linghang.mywust.util.PasswordEncoder;
import java.io.IOException;
import java.util.Scanner;
public class JwcLoginTest {
public static void main(String[] args) throws BasicException, IOException {
new JwcLoginTest().run();
}
private void run() throws BasicException, IOException {
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);
JwcLogin jwcLogin = new JwcLogin(new SimpleOkhttpRequester());
RequestClientOption option = new RequestClientOption();
option.setTimeout(5);
option.setProxy(null);
option.setFallowUrlRedirect(false);
String cookies = jwcLogin.getLoginCookie(username, PasswordEncoder.encodePassword(password), option);
System.out.println(cookies);
}
}

@ -23,5 +23,12 @@
<artifactId>commons-codec</artifactId>
<version>1.15</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version>
</dependency>
</dependencies>
</project>

@ -0,0 +1,37 @@
package cn.linghang.mywust.util;
import com.google.common.base.Joiner;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class StringUtil {
/**
* 将map转换成url请求表单格式的请求字符串类似于 user=admin&passwd=123456&time=11111 这种
*
* @param queryParams 请求参数
* @return 生成的表单请求字符串
*/
public static String generateQueryString(Map<String, String> queryParams) {
return Joiner.on('&')
.useForNull("")
.withKeyValueSeparator('=')
.join(queryParams);
}
/**
* 解析服务器相应的Set-Cookie的header值并拼成能够直接用于Cookie的header值
*
* @param cookieHeaders 服务器响应的Set-Cookie
* @return 解析后可用的Cookie
*/
public static String parseCookie(List<String> cookieHeaders) {
List<String> allCookies = new ArrayList<>(cookieHeaders.size());
cookieHeaders.forEach((cookieHeader) -> allCookies.add(cookieHeader.split(";")[0]));
return Joiner.on(';')
.useForNull("")
.join(allCookies);
}
}
Loading…
Cancel
Save