概述
使用Forest+Jsoup对正方教务系统登陆(Java实现)
什么是 Forest?
Forest 是一个开源的 Java HTTP 客户端框架,它能够将 HTTP 的所有请求信息(包括 URL、Header 以及 Body 等信息)绑定到您自定义的 Interface 方法上,能够通过调用本地接口方法的方式发送 HTTP 请求。
开源地址:Gitee地址
官网:http://forest.dtflyx.com/
项目环境:
基于SpringBoot的引入(主要因为官网有SpringBoot的starter)的Pom.xml代码:
<dependencies>
<!-- SpringBoot的引入-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Jsoup的Xpath引入-->
<dependency>
<groupId>cn.wanghaomiao</groupId>
<artifactId>JsoupXpath</artifactId>
<version>2.2</version>
</dependency>
<!--Forest的引入-->
<dependency>
<groupId>com.dtflys.forest</groupId>
<artifactId>forest-spring-boot-starter</artifactId>
<version>1.5.11</version>
</dependency>
</dependencies>
这里还引入了一个Gitee上的自动识别教务系统的验证码的项目
这个项目比较老了,但可以自动识别验证码并且返回验证码所携带的cookie,我这个项目也是基于它的二次开发
地址:https://gitee.com/suseonline/OrcJwglCode
最后整体的项目结构:
正式开始
大致流程:
第一步:
根据Forest官网的文档,我们先创建一个LoginInterface接口:
import com.dtflys.forest.Forest;
import com.dtflys.forest.annotation.*;
import com.dtflys.forest.callback.OnSuccess;
import com.dtflys.forest.http.ForestRequest;
import org.springframework.stereotype.Component;
import java.util.Map;
@Component
public interface LoginInterface {
/**
* 定义登陆请求
* @param headerMap
*/
@Request(
url = "{url}",
type = "post",
contentType = "application/x-www-form-urlencoded"
)
public ForestRequest<?> login(@Var("url")String url, @Header Map<String,Object> headerMap, @Body Map<String,Object> user);
@Request(
url = "{url}",
type = "get")
public ForestRequest<?> get(@Var("url")String url,@Header Map<String,Object> headerMap);
}
其中
参数 | 所需要的值 |
---|---|
url | 学校的登陆地址 |
HeaderMap | 要设置的头信息 |
user | 登陆的表单信息 |
这里特别注意要设置contentType的格式为:application/x-www-form-urlencoded,因为正方的登陆系统是表单提交!
还要注意返回类型都需要是ForestRequest<?>,因为Forest框架是遇到重定向的时候是会自动重定向的新的链接的,而这样没法携带Cookie并且第二次的请求类型也不一样,会直接报错,所以等下我们需要手动来执行请求!
这样我们需要的请求接口就写好了,等下只需要用@Autowired注解引入即可
第二步
1.创建一个controller,里面引入我们所需要的类和接口,并且编写一个test方法:
@Autowired
private SecurityCodeService securityCodeService;
@Autowired
private LoginInterface loginInterface;
@Autowired
private LoginService loginService;
@GetMapping("/test")
public void test(String username,String password) throws Exception
2.然后在test方法首先请求验证码并且自动识别,并且获取cookie
这里我直接使用上面的那个开源框架的方法识别的:
//直接设置一个请求请求验证码
String[] cookies = securityCodeService.downloadImage("http://*.*.*.*:*/CheckCode.aspx", "CheckCode.png");
//解析验证码
String checkCode = securityCodeService.getAllOcr("CheckCode.png");
//打印验证码和cookie
System.out.println("checkCode=" + checkCode );
System.out.println("cookies=" + cookies[1] );
这里需要需要注意的是,在downloadImage方法中会返回一个String的数组,其中第二个是cookie,也就是Session的ID值,我们等下登陆的时候需要将这个设置上去,不然验证码会和登陆信息一直对应不上!!!
3.设置头信息:
//设置请求头
Map<String,Object> headerMap = new HashMap<>();
//设置来源
headerMap.put("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9");//带上参数页
headerMap.put("Cookie", cookies[1]);//带上参数页
headerMap.put("Connection", "keep-alive");//带上参数页
headerMap.put("Content-Type", "application/x-www-form-urlencoded");//带上参数页
headerMap.put("Host", "*.*.*.*:*");//带上参数页
headerMap.put("Origin", "http://*.*.*.*:*");//带上参数页
headerMap.put("Upgrade-Insecure-Requests", "1");//带上参数页
headerMap.put("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36");//带上参数页
headerMap.put("Referer", "http://*.*.*.*:*/default2.aspx");//带上referer 参数页
//http://*.*.*.*:*/CheckCode.aspx 中的*.*.*.*:*是教务系统的地址
这里的cookie就是沿用了上面验证码的cookie,然后正方教务系统的Referer其实就是登陆页面的url.
4.设置登陆信息
这里登陆信息中有注释的为关键,其他留空即可,不知道的可以自己在浏览器中F12去看一下表单提交
//创建登陆信息
Map<String,Object> userMap = new HashMap<>();
//设置登陆信息
userMap.put("Button1", "");
userMap.put("RadioButtonList1", "");//登陆账号类型
userMap.put("TextBox2", password);//密码
userMap.put("Textbox1", "");
userMap.put("__VIEWSTATE", VIEWSTATE);
userMap.put("hidPdrs", "");
userMap.put("hidsc", "");
userMap.put("lbLanguage", "");
userMap.put("txtSecretCode",checkCode);//验证码
userMap.put("txtUserName", username);//学号
其中有的正方版本的VIEWSTATE值是会过一段时间变的,所以需要使用Jsoup动态的获取一下:
//获取固定的VIEWSTATE
String VIEWSTATE = loginService.getVIEWSTATE();
//获取VIEWSTATE的方法
public String getVIEWSTATE(){
Document parse = Jsoup.parse(Forest.get("http://*.*.*.*:*/default2.aspx").executeAsString());
Elements select = parse.select("#form1 > input[type=hidden]");
return select.attr("value");
}
5.执行请求并且获取状态码
直接上代码
//获取forestRequest
ForestRequest<?> forestRequest = loginInterface.login("http://*.*.*.*:*/default2.aspx", headerMap, userMap);
//设置不自动重定向执行请求
ForestResponse forestResponse = forestRequest.autoRedirects(false).execute(ForestResponse.class);
//获取状态码
int status = forestResponse.getStatusCode();
这里状态码为302(也就是重定向时),表示着成功,200说明失败!!
6.手动重定向
if (status == 302) {
//当响应是302时为响应成功!
//获取响应后的新地址
ForestHeader location = forestResponse.getHeader("location");
System.out.println("location=" + location.getValue());
//设置请求头
Map<String, Object> suMap = new HashMap<>();
suMap.put("Cookie", cookies[1]);
suMap.put("Host", "*.*.*.*:*");
suMap.put("Referer", "http://*.*.*.*:*/default2.aspx");
//将新地址进行请求,执行get请求
ForestRequest<?> forestRequest1 = loginInterface.get("http://*.*.*.*:*/" + location.getValue(),suMap);
//执行get请求
ForestResponse getResponse = forestRequest1.autoRedirects(false).execute(ForestResponse.class);
System.out.println("成功的页面:"+getResponse.getContent());
}
这里cookie还是沿用前面的,然后注意这里一定要使用Get请求,不然会报405错误!
7.验证
启动并且测试,在浏览器中输入http://localhost:8080/test?username=学号&password=密码,在控制台中看到这个,就代表已经登陆成功了!:
注意事项:
1.验证码识别并不是百分之百成功,成功率为百分之90
2.使用controller而不是使用Spring测试的原因是controller可以动态的输入不同的学号和密码.
最后:
此教程只用于学习,用于其他用途与作者无关,使用开源框架若有侵犯请指出,必修改。
转载请携带本教程的作者:老昊.
最后
以上就是敏感彩虹为你收集整理的使用Forest+Jsoup对正方教务系统登陆(Java实现)使用Forest+Jsoup对正方教务系统登陆(Java实现)项目环境:正式开始注意事项:最后:的全部内容,希望文章能够帮你解决使用Forest+Jsoup对正方教务系统登陆(Java实现)使用Forest+Jsoup对正方教务系统登陆(Java实现)项目环境:正式开始注意事项:最后:所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复