修改重定向问题导致的登录cookie获取不正确的问题,新增旧版bkjx系统登录方式(官网可用,此处仍不可用)

old-package
lensfrex 2 years ago
parent 4bb358cc05
commit 6f35b17acc
Signed by: lensfrex
GPG Key ID: 0F69A0A2FBEE98A0
  1. 6
      mywust-core/pom.xml
  2. 21
      mywust-core/src/main/java/cn/linghang/mywust/core/api/Bkjx.java
  3. 15
      mywust-core/src/main/java/cn/linghang/mywust/core/api/JwcApiUrl.java
  4. 8
      mywust-core/src/main/java/cn/linghang/mywust/core/api/UnionAuth.java
  5. 58
      mywust-core/src/main/java/cn/linghang/mywust/core/service/auth/UnionLogin.java
  6. 68
      mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/AuthRequestFactory.java
  7. 41
      mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/AuthRequestGenerator.java
  8. 98
      mywust-core/src/main/java/cn/linghang/mywust/core/service/undergraduate/JwcLogin.java
  9. 6
      mywust-network-okhttp/pom.xml
  10. 22
      mywust-network-okhttp/src/main/java/cn/linghang/mywust/network/okhttp/RedirectInterceptor.java
  11. 24
      mywust-network-okhttp/src/main/java/cn/linghang/mywust/network/okhttp/SimpleOkhttpRequester.java
  12. 37
      mywust-network/src/main/java/cn/linghang/mywust/network/HttpRequest.java
  13. 15
      mywust-network/src/main/java/cn/linghang/mywust/network/HttpResponse.java
  14. 41
      mywust-test/src/test/java/JwcLegacyLoginTest.java
  15. 8
      mywust-test/src/test/java/JwcLoginTest.java
  16. 35
      mywust-util/src/main/java/cn/linghang/mywust/util/PasswordEncoder.java
  17. 6
      mywust-util/src/main/java/cn/linghang/mywust/util/StringUtil.java

@ -23,6 +23,12 @@
<version>0.0.1-dev</version> <version>0.0.1-dev</version>
</dependency> </dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.36</version>
</dependency>
<dependency> <dependency>
<groupId>net.sourceforge.jregex</groupId> <groupId>net.sourceforge.jregex</groupId>
<artifactId>jregex</artifactId> <artifactId>jregex</artifactId>

@ -0,0 +1,21 @@
package cn.linghang.mywust.core.api;
import lombok.Getter;
/**
* <p>Bkjx本科教学系统对应的API常量列表拼音咱就别吐槽了吧...</p>
* <p>其实是本科生用的教务处系统</p>
*/
@Getter
public class Bkjx {
public static final String BKJX_SSO_SERVICE = "http://bkjx.wust.edu.cn/jsxsd/sso.jsp";
public static final String BKJX_SESSION_COOKIE_API = "http://bkjx.wust.edu.cn/jsxsd/sso.jsp?ticket=%s";
public static final String BKJX_TEST_API = "http://bkjx.wust.edu.cn/jsxsd/xxwcqk/xxwcqk_idxOnzh.do";
public static class Legacy {
public static final String BKJX_INDEX = "http://bkjx.wust.edu.cn";
public static final String BKJX_DATA_STRING_API = "http://bkjx.wust.edu.cn/Logon.do?method=logon&flag=sess";
public static final String BKJX_SESSION_COOKIE_API = "http://bkjx.wust.edu.cn/Logon.do?method=logon";
}
}

@ -1,15 +0,0 @@
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,8 @@
package cn.linghang.mywust.core.api;
public class UnionAuth {
/**
* 统一认证登录验证的api地址请求之后可进一步获取service ticket来对具体的服务进行登录获取Cookies
*/
public static final String UNION_AUTH_API = "https://auth.wust.edu.cn/lyuapServer/v1/tickets";
}

@ -0,0 +1,58 @@
package cn.linghang.mywust.core.service.auth;
import cn.linghang.mywust.core.api.UnionAuth;
import cn.linghang.mywust.core.exception.BasicException;
import cn.linghang.mywust.core.exception.PasswordWornException;
import cn.linghang.mywust.core.service.undergraduate.AuthRequestFactory;
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.PasswordEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.net.URL;
/**
* 统一认证登录
*/
public class UnionLogin {
Logger log = LoggerFactory.getLogger(UnionLogin.class);
private final Requester requester;
public UnionLogin(Requester requester) {
this.requester = requester;
}
public String getServiceTicket(String username, String password, String serviceUrl, RequestClientOption requestOption) throws IOException, BasicException {
String encodedPassword = PasswordEncoder.encodePassword(password);
// 获取ticket granting ticket(TGT),以获取ServiceTicket
HttpRequest TGTRequest = AuthRequestFactory.unionLoginTGTRequest(username, encodedPassword, serviceUrl);
HttpResponse unionAuthResponse = requester.post(new URL(UnionAuth.UNION_AUTH_API), TGTRequest, requestOption);
String redirectAddress = unionAuthResponse.getHeaders().get("Location");
if (redirectAddress == null) {
throw new PasswordWornException();
}
// 获取服务ticket(service ticket,ST)
HttpRequest serviceTicketRequest = AuthRequestFactory.loginTicketRequest(serviceUrl);
HttpResponse serviceTicketResponse =
requester.post(new URL(redirectAddress.replace("http:", "https:")), serviceTicketRequest, requestOption);
byte[] serviceTicketResponseData = serviceTicketResponse.getBody();
if (serviceTicketResponseData == null) {
log.warn("获取服务st出错,serviceTicketResponseData == null");
throw new BasicException();
}
return new String(serviceTicketResponseData);
}
}

@ -0,0 +1,68 @@
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 AuthRequestFactory {
public static HttpRequest unionLoginTGTRequest(String username, String password, String service) {
Map<String, String> requestForm = new HashMap<>(4);
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<>(1);
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 DEFAULT_HTTP_REQUEST;
}
private static final HttpRequest DEFAULT_HTTP_REQUEST = new HttpRequest();
public static class Legacy {
public static HttpRequest dataStringRequest() {
return DEFAULT_HTTP_REQUEST;
}
public static HttpRequest ticketRedirectRequest(String encode) {
Map<String, String> queryParams = new HashMap<>();
queryParams.put("userAccount", "");
queryParams.put("userPassword", "");
queryParams.put("encoded", encode);
String queryString = StringUtil.generateQueryString(queryParams);
Map<String, String> extendHeaders = new HashMap<>();
extendHeaders.put("Referer", "http://bkjx.wust.edu.cn/");
extendHeaders.put("Origin", "http://bkjx.wust.edu.cn");
HttpRequest httpRequest = new HttpRequest();
httpRequest.setHeaders(extendHeaders);
httpRequest.setData(queryString.getBytes(StandardCharsets.UTF_8));
return httpRequest;
}
}
}

@ -1,41 +0,0 @@
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,65 +1,113 @@
package cn.linghang.mywust.core.service.undergraduate; package cn.linghang.mywust.core.service.undergraduate;
import cn.linghang.mywust.core.api.JwcApiUrl; import cn.linghang.mywust.core.api.Bkjx;
import cn.linghang.mywust.core.exception.BasicException; import cn.linghang.mywust.core.exception.BasicException;
import cn.linghang.mywust.core.exception.PasswordWornException; import cn.linghang.mywust.core.exception.PasswordWornException;
import cn.linghang.mywust.core.service.auth.UnionLogin;
import cn.linghang.mywust.network.HttpRequest; import cn.linghang.mywust.network.HttpRequest;
import cn.linghang.mywust.network.HttpResponse; import cn.linghang.mywust.network.HttpResponse;
import cn.linghang.mywust.network.RequestClientOption; import cn.linghang.mywust.network.RequestClientOption;
import cn.linghang.mywust.network.Requester; import cn.linghang.mywust.network.Requester;
import cn.linghang.mywust.util.PasswordEncoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
public class JwcLogin { public class JwcLogin {
// 默认5秒超时 private static final Logger log = LoggerFactory.getLogger(JwcLogin.class);
private static final int DEFAULT_TIMEOUT = 5;
private final Requester requester; private final Requester requester;
public JwcLogin(Requester requester) { private final UnionLogin unionLogin;
public JwcLogin(Requester requester, UnionLogin unionLogin) {
this.requester = requester; this.requester = requester;
this.unionLogin = unionLogin;
} }
public String getLoginCookie(String username, String password, RequestClientOption requestOption) throws IOException, BasicException { /**
// 获取ticket granting ticket(TGT) * <p>旧版的登录方式既相当于直接登录<a href="http://bkjx.wust.edu.cn">bkjx系统</a></p>
HttpRequest TGTRequest = AuthRequestGenerator.unionLoginTGTRequest(username, password, JwcApiUrl.JWC_SSO_SERVICE); * <p>注意这种登录方式的密码和新版可能是不一样的</p>
* <p>不过不论使用哪种登录方式获取到的cookie都是可用的</p>
*
* @return 获取到的Cookies
*/
public String getLoginCookieLegacy(String username, String password, RequestClientOption requestOption) throws IOException, BasicException {
// 获取某段神秘的dataStr(反正官网代码是这么叫的)
HttpRequest dataStringRequest = AuthRequestFactory.Legacy.dataStringRequest();
HttpResponse dataStringResponse = requester.post(new URL(Bkjx.Legacy.BKJX_DATA_STRING_API), dataStringRequest, requestOption);
if (dataStringResponse.getBody() == null) {
throw new BasicException();
}
HttpResponse unionAuthResponse = requester.post(new URL(JwcApiUrl.UNION_AUTH_API), TGTRequest, requestOption); String dataString = new String(dataStringResponse.getBody());
String redirectAddress = unionAuthResponse.getHeaders().get("Location"); // 获取登录ticket
if (redirectAddress == null) { String encoded = PasswordEncoder.legacyPassword(username, password, dataString);
throw new PasswordWornException(); HttpRequest ticketRequest = AuthRequestFactory.Legacy.ticketRedirectRequest(encoded);
ticketRequest.setCookies(dataStringResponse.getCookies());
HttpResponse ticketResponse = requester.post(new URL(Bkjx.Legacy.BKJX_SESSION_COOKIE_API), ticketRequest, requestOption);
if (ticketResponse.getBody() == null) {
throw new BasicException();
} }
// 获取服务ticket(service ticket,st) // 使用跳转得到的链接获取cookies
HttpRequest serviceTicketRequest = AuthRequestGenerator.loginTicketRequest(JwcApiUrl.JWC_SSO_SERVICE); String sessionRedirect = ticketResponse.getHeaders().get("Location");
if (sessionRedirect == null) {
throw new PasswordWornException();
}
HttpRequest sessionRequest = AuthRequestFactory.Legacy.dataStringRequest();
HttpResponse serviceTicketResponse = HttpResponse sessionResponse = requester.get(new URL(sessionRedirect), sessionRequest, requestOption);
requester.post(new URL(redirectAddress.replace("http:", "https:")), serviceTicketRequest, requestOption);
byte[] serviceTicketResponseData = serviceTicketResponse.getBody(); String cookies = sessionResponse.getCookies();
if (serviceTicketResponseData == null) { if (roughCheckCookie(cookies)) {
System.err.println("获取服务st出错,serviceTicketResponseData == null");
throw new BasicException(); throw new BasicException();
} }
String serviceTicket = new String(serviceTicketResponseData);
return cookies;
}
public String getLoginCookie(String username, String password, RequestClientOption requestOption) throws IOException, BasicException {
String serviceTicket = unionLogin.getServiceTicket(username, password, Bkjx.BKJX_SSO_SERVICE, requestOption);
// 获取登录cookie(session) // 获取登录cookie(session)
HttpRequest sessionRequest = AuthRequestGenerator.sessionCookieRequest(); HttpRequest sessionRequest = AuthRequestFactory.sessionCookieRequest();
HttpResponse sessionResponse = requester.get(new URL(String.format(JwcApiUrl.JWC_TICKET_API, serviceTicket)), sessionRequest, requestOption); HttpResponse sessionResponse = requester.get(new URL(String.format(Bkjx.BKJX_SESSION_COOKIE_API, serviceTicket)), sessionRequest, requestOption);
String cookies = sessionResponse.getCookies(); String cookies = sessionResponse.getCookies();
if (cookies == null || !cookies.contains("JSESSIONID") || !cookies.contains("SERVERID")) { if (roughCheckCookie(cookies)) {
System.err.println("获取服务session cookie出错,关键Cookie缺失");
System.err.println("Cookies: " + cookies);
throw new BasicException(); throw new BasicException();
} }
return cookies; return cookies;
} }
private void getLoginGTG(String username, String password) { private boolean roughCheckCookie(String cookies) throws BasicException {
return cookies == null || !cookies.contains("JSESSIONID") || !cookies.contains("SERVERID");
}
private static final int COOKIES_ERROR_RESPONSE_LENGTH =
("<script languge='javascript'>window.location.href=" +
"'https://auth.wust.edu.cn/lyuapServer/login?service=http%3A%2F%2Fbkjx.wust.edu.cn%2Fjsxsd%2Fxxwcqk%2Fxxwcqk_idxOnzh.do'" +
"</script>").length();
public boolean checkCookies(String cookies) throws IOException {
RequestClientOption option = new RequestClientOption();
option.setTimeout(5);
option.setProxy(null);
option.setFallowUrlRedirect(false);
HttpRequest testRequest = AuthRequestFactory.sessionCookieRequest();
testRequest.setCookies(cookies);
HttpResponse testResponse = requester.get(new URL(Bkjx.BKJX_TEST_API), testRequest, option);
// 判断响应长度是否为178个字,登录跳转响应长度
// 这种办法虽然在极端情况下可能会出错(而且还挺蠢的),但是是最快的办法中比较准确的了
return testResponse.getBody().length != COOKIES_ERROR_RESPONSE_LENGTH;
} }
} }

@ -43,6 +43,12 @@
<version>2.13.4</version> <version>2.13.4</version>
</dependency> </dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.36</version>
</dependency>
<dependency> <dependency>
<groupId>cn.linghang</groupId> <groupId>cn.linghang</groupId>
<artifactId>mywust-network</artifactId> <artifactId>mywust-network</artifactId>

@ -0,0 +1,22 @@
package cn.linghang.mywust.network.okhttp;
import okhttp3.Interceptor;
import okhttp3.Response;
import java.io.IOException;
public class RedirectInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
okhttp3.Request request = chain.request();
Response response = chain.proceed(request);
String location = response.headers().get("Location");
if (location != null) {
System.out.println(("Request redirected to:" + location));
}
return response;
}
}

@ -7,13 +7,14 @@ import cn.linghang.mywust.network.Requester;
import cn.linghang.mywust.util.StringUtil; import cn.linghang.mywust.util.StringUtil;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import okhttp3.*; import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException; import java.io.IOException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.Proxy; import java.net.Proxy;
import java.net.URL; import java.net.URL;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
@ -36,6 +37,8 @@ import java.util.concurrent.TimeUnit;
* @edit 2022-10-19 21:30 * @edit 2022-10-19 21:30
*/ */
public class SimpleOkhttpRequester implements Requester { public class SimpleOkhttpRequester implements Requester {
private static final Logger log = LoggerFactory.getLogger(SimpleOkhttpRequester.class);
private final boolean useSingletonClient; private final boolean useSingletonClient;
private static volatile OkHttpClient rootClient; private static volatile OkHttpClient rootClient;
@ -108,6 +111,8 @@ public class SimpleOkhttpRequester implements Requester {
builder.callTimeout(requestClientOption.getTimeout(), TimeUnit.SECONDS) builder.callTimeout(requestClientOption.getTimeout(), TimeUnit.SECONDS)
.readTimeout(requestClientOption.getTimeout(), TimeUnit.SECONDS) .readTimeout(requestClientOption.getTimeout(), TimeUnit.SECONDS)
.connectTimeout(requestClientOption.getTimeout(), TimeUnit.SECONDS) .connectTimeout(requestClientOption.getTimeout(), TimeUnit.SECONDS)
.followRedirects(requestClientOption.isFallowUrlRedirect())
.addInterceptor(new RedirectInterceptor())
.sslSocketFactory(TrustAllCert.getSSLSocketFactory(), TrustAllCert.getX509TrustManager()) .sslSocketFactory(TrustAllCert.getSSLSocketFactory(), TrustAllCert.getX509TrustManager())
.hostnameVerifier(TrustAllCert.getHostnameVerifier()); .hostnameVerifier(TrustAllCert.getHostnameVerifier());
@ -169,10 +174,10 @@ public class SimpleOkhttpRequester implements Requester {
} }
String contentType = headers.get("Content-Type"); String contentType = headers.get("Content-Type");
if (!"".equals(contentType)) { if (contentType == null || "".equals(contentType)) {
return MediaType.get(contentType);
} else {
return MediaType.get(DEFAULT_CONTENT_TYPE); return MediaType.get(DEFAULT_CONTENT_TYPE);
} else {
return MediaType.get(contentType);
} }
} }
@ -197,18 +202,23 @@ public class SimpleOkhttpRequester implements Requester {
requestBuilder.header("Cookie", requestCookie); requestBuilder.header("Cookie", requestCookie);
} }
byte[] data = httpRequest.getData();
if (data == null && requestMethod != RequestMethod.GET) {
data = new byte[]{0};
}
if (requestMethod == RequestMethod.GET) { if (requestMethod == RequestMethod.GET) {
requestBuilder.get(); requestBuilder.get();
} else if (requestMethod == RequestMethod.POST) { } else if (requestMethod == RequestMethod.POST) {
requestBuilder.post(RequestBody.create(this.getMediaType(httpRequest), httpRequest.getData())); requestBuilder.post(RequestBody.create(this.getMediaType(httpRequest), data));
} else if (requestMethod == RequestMethod.PUT) { } else if (requestMethod == RequestMethod.PUT) {
requestBuilder.put(RequestBody.create(this.getMediaType(httpRequest), httpRequest.getData())); requestBuilder.put(RequestBody.create(this.getMediaType(httpRequest), data));
} else if (requestMethod == RequestMethod.DELETE) { } else if (requestMethod == RequestMethod.DELETE) {
if (httpRequest.getData() != null) { if (httpRequest.getData() != null) {
requestBuilder.delete(RequestBody.create(this.getMediaType(httpRequest), httpRequest.getData())); requestBuilder.delete(RequestBody.create(this.getMediaType(httpRequest), data));
} else { } else {
requestBuilder.delete(); requestBuilder.delete();
} }

@ -2,10 +2,24 @@ package cn.linghang.mywust.network;
import lombok.Data; import lombok.Data;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
@Data @Data
public class HttpRequest { public class HttpRequest {
private static final Map<String, String> DEFAULT_HEADERS = initDefaultHeaders();
private static Map<String, String> initDefaultHeaders() {
Map<String, String> defaultHeaders = new HashMap<>();
defaultHeaders.put("Accept", "application/json, text/plain, */*");
defaultHeaders.put("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6");
defaultHeaders.put("Cache-Control", "no-cache");
defaultHeaders.put("Connection", "keep-alive");
defaultHeaders.put("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 Edg/106.0.1370.47");
return defaultHeaders;
}
private Map<String, String> urlParams; private Map<String, String> urlParams;
private Map<String, String> headers; private Map<String, String> headers;
@ -13,4 +27,27 @@ public class HttpRequest {
private String cookies; private String cookies;
private byte[] data; private byte[] data;
public HttpRequest() {
headers = new HashMap<>(DEFAULT_HEADERS);
}
public void setHeaders(Map<String, String> headers) {
this.headers.putAll(headers);
}
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("HttpRequest{");
sb.append("urlParams=").append(urlParams);
sb.append(", headers=").append(headers);
sb.append(", cookies='").append(cookies).append('\'');
sb.append(", data=");
if (data == null) sb.append("null");
else {
sb.append(new String(data));
}
sb.append('}');
return sb.toString();
}
} }

@ -2,7 +2,6 @@ package cn.linghang.mywust.network;
import lombok.Data; import lombok.Data;
import java.util.List;
import java.util.Map; import java.util.Map;
@Data @Data
@ -12,4 +11,18 @@ public class HttpResponse {
private String cookies; private String cookies;
private byte[] body; private byte[] body;
@Override
public String toString() {
final StringBuffer sb = new StringBuffer("HttpResponse{");
sb.append("headers=").append(headers);
sb.append(", cookies='").append(cookies).append('\'');
sb.append(", body=");
if (body == null) sb.append("null");
else {
sb.append(new String(body));
}
sb.append('}');
return sb.toString();
}
} }

@ -0,0 +1,41 @@
import cn.linghang.mywust.core.exception.BasicException;
import cn.linghang.mywust.core.service.auth.UnionLogin;
import cn.linghang.mywust.core.service.undergraduate.JwcLogin;
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 JwcLegacyLoginTest {
public static void main(String[] args) throws BasicException, IOException {
new JwcLegacyLoginTest().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);
Requester requester = new SimpleOkhttpRequester();
JwcLogin jwcLogin = new JwcLogin(requester, new UnionLogin(requester));
RequestClientOption option = new RequestClientOption();
option.setTimeout(5);
option.setProxy(null);
option.setFallowUrlRedirect(false);
String cookies = jwcLogin.getLoginCookieLegacy(username, password, option);
System.out.println(cookies);
}
}

@ -1,8 +1,9 @@
import cn.linghang.mywust.core.exception.BasicException; import cn.linghang.mywust.core.exception.BasicException;
import cn.linghang.mywust.core.service.auth.UnionLogin;
import cn.linghang.mywust.core.service.undergraduate.JwcLogin; import cn.linghang.mywust.core.service.undergraduate.JwcLogin;
import cn.linghang.mywust.network.RequestClientOption; import cn.linghang.mywust.network.RequestClientOption;
import cn.linghang.mywust.network.Requester;
import cn.linghang.mywust.network.okhttp.SimpleOkhttpRequester; import cn.linghang.mywust.network.okhttp.SimpleOkhttpRequester;
import cn.linghang.mywust.util.PasswordEncoder;
import java.io.IOException; import java.io.IOException;
import java.util.Scanner; import java.util.Scanner;
@ -25,14 +26,15 @@ public class JwcLoginTest {
System.out.println("账号:" + username); System.out.println("账号:" + username);
System.out.println("密码:" + password); System.out.println("密码:" + password);
JwcLogin jwcLogin = new JwcLogin(new SimpleOkhttpRequester()); Requester requester = new SimpleOkhttpRequester();
JwcLogin jwcLogin = new JwcLogin(requester, new UnionLogin(requester));
RequestClientOption option = new RequestClientOption(); RequestClientOption option = new RequestClientOption();
option.setTimeout(5); option.setTimeout(5);
option.setProxy(null); option.setProxy(null);
option.setFallowUrlRedirect(false); option.setFallowUrlRedirect(false);
String cookies = jwcLogin.getLoginCookie(username, PasswordEncoder.encodePassword(password), option); String cookies = jwcLogin.getLoginCookie(username, password, option);
System.out.println(cookies); System.out.println(cookies);
} }

@ -16,6 +16,8 @@ import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException; import java.security.spec.InvalidKeySpecException;
import java.security.spec.RSAPublicKeySpec; import java.security.spec.RSAPublicKeySpec;
import static java.lang.Integer.parseInt;
/** /**
* <h>密码加密工具类</h> * <h>密码加密工具类</h>
* *
@ -27,6 +29,7 @@ import java.security.spec.RSAPublicKeySpec;
* <p>- 将生成的字节数组转换成16进制字符串得到加密后的数据</p> * <p>- 将生成的字节数组转换成16进制字符串得到加密后的数据</p>
* <br> * <br>
* <p>希望不要再改登录方式了 [] </p> * <p>希望不要再改登录方式了 [] </p>
*
* @author : lensfrex * @author : lensfrex
* @description : 使用统一登陆的加密方法对密码进行加密的工具类 * @description : 使用统一登陆的加密方法对密码进行加密的工具类
* @create : 2022-09-18 14:42:06 * @create : 2022-09-18 14:42:06
@ -69,7 +72,7 @@ public class PasswordEncoder {
// 完成加密 // 完成加密
return Hex.encodeHexString(cipher.doFinal(reversedTextData)); return Hex.encodeHexString(cipher.doFinal(reversedTextData));
} catch (IllegalBlockSizeException | BadPaddingException e) { } catch (IllegalBlockSizeException | BadPaddingException e) {
// 会报错的地方都是因为算法不正确,这里都是固定的值,出错了就是程序写错了,在测试的时候就应该发现的问题 // 会报错的地方都是因为算法不正确,这里都是固定的值,出错了就是程序写错了,在测试的时候就应该发现的问题
// 对于调用者不必处理这种异常,但是开发测试的时候应该要打日志来发现问题 // 对于调用者不必处理这种异常,但是开发测试的时候应该要打日志来发现问题
System.err.println("加密出错"); System.err.println("加密出错");
@ -101,4 +104,34 @@ public class PasswordEncoder {
return null; return null;
} }
/**
* <p>使用旧版登录页的方法加密密码bkjx系统直接登录</p>
* <p>是直接照搬官网js代码的只是经过了一点小修改没有具体研究是什么加密方式大概率可能是自创的性能可能会有点差</p>
*
* @param dataString 加密前置字符串
* @param password 密码明文
* @return 加密后的密文
*/
public static String legacyPassword(String username, String password, String dataString) {
String[] parts = dataString.split("#");
String scode = parts[0];
String sxh = parts[1];
String code = username + "%%%" + password;
StringBuilder encoded = new StringBuilder();
for (int i = 0, codeLength = code.length(); i < codeLength; i++) {
if (i < 20) {
int endIndex = parseInt(sxh.substring(i, i + 1));
encoded.append(code.charAt(i)).append(scode, 0, endIndex);
scode = scode.substring(endIndex);
} else {
encoded.append(code.substring(i));
i = codeLength;
}
}
return encoded.toString();
}
} }

@ -27,11 +27,15 @@ public class StringUtil {
* @return 解析后可用的Cookie * @return 解析后可用的Cookie
*/ */
public static String parseCookie(List<String> cookieHeaders) { public static String parseCookie(List<String> cookieHeaders) {
if (cookieHeaders == null || cookieHeaders.isEmpty()) {
return null;
}
List<String> allCookies = new ArrayList<>(cookieHeaders.size()); List<String> allCookies = new ArrayList<>(cookieHeaders.size());
cookieHeaders.forEach((cookieHeader) -> allCookies.add(cookieHeader.split(";")[0])); cookieHeaders.forEach((cookieHeader) -> allCookies.add(cookieHeader.split(";")[0]));
return Joiner.on(';') return Joiner.on(';')
.useForNull("") .skipNulls()
.join(allCookies); .join(allCookies);
} }
} }

Loading…
Cancel
Save