Java 如何使用并行性来加速URL GET请求?
我所遇到的问题要求我向网站发送请求,并检查特定密码是否正确。这有点类似于CTF问题,但我使用蛮力生成正确的密码密钥,因为网站会反馈特定密钥是否在正确的轨道上。为了将密钥视为“几乎有效”,它必须是正确密钥的子字符串 我已经天真地实现了这一点,但是预期的解决方案使用简单的并行性来加速这个过程。我将如何在Java中实现这一点Java 如何使用并行性来加速URL GET请求?,java,url,Java,Url,我所遇到的问题要求我向网站发送请求,并检查特定密码是否正确。这有点类似于CTF问题,但我使用蛮力生成正确的密码密钥,因为网站会反馈特定密钥是否在正确的轨道上。为了将密钥视为“几乎有效”,它必须是正确密钥的子字符串 我已经天真地实现了这一点,但是预期的解决方案使用简单的并行性来加速这个过程。我将如何在Java中实现这一点 import java.net.*; import java.io.*; import java.nio.charset.StandardCharsets; public cl
import java.net.*;
import java.io.*;
import java.nio.charset.StandardCharsets;
public class Main {
static boolean check(StringBuilder s) throws IOException{
String test = "https://example.com?pass=";
String q = URLEncoder.encode(s.toString(), StandardCharsets.UTF_8);
URL site = new URL(test+q);
URLConnection yc = site.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
//System.out.println(inputLine);
if (inputLine.contains("Incorrect password!")) {
return false;
}
if (inputLine.contains("the correct password!")) {
System.out.println(s);
System.exit(0);
}
}
return true;
}
static void gen(StringBuilder s) throws IOException {
if (!check(s)) {
return;
}
for (int i = 33; i<127; i++) {
int len = s.length();
gen(s.append((char) i));
s.setLength(len);
}
}
public static void main(String[] args) throws IOException, InterruptedException {
gen(new StringBuilder("start"));
}
}
import java.net.*;
导入java.io.*;
导入java.nio.charset.StandardCharset;
公共班机{
静态布尔检查(StringBuilders)引发IOException{
字符串测试=”https://example.com?pass=";
字符串q=URLEncoder.encode(s.toString(),StandardCharsets.UTF_8);
URL站点=新URL(测试+q);
URLConnection yc=site.openConnection();
BufferedReader in=新的BufferedReader(新的InputStreamReader(yc.getInputStream());
字符串输入线;
而((inputLine=in.readLine())!=null){
//系统输出打印LN(输入线);
if(inputLine.contains(“密码不正确!”){
返回false;
}
if(inputLine.contains(“正确的密码!”){
系统输出打印项次;
系统出口(0);
}
}
返回true;
}
静态void gen(StringBuilder s)引发IOException{
如果(!检查){
回来
}
对于(int i=33;iHi),请使用RecursiveTask、ForkJoinPool进行并行处理。以下代码不是您自己的最终修改
public class Test {
public static void main(String[] args) {
ForkJoinPool forkJoinPool=new ForkJoinPool(parallelism);
forkJoinPool.invoke(new PasswordKeyValidatorTask(new StringBuilder("start")));
}
public static class PasswordKeyValidatorTask extends RecursiveTask<StringBuilder> {
private static final long serialVersionUID = 3113310524830439302L;
private StringBuilder password;
public PasswordKeyValidatorTask(StringBuilder password) {
this.password = password;
}
@Override
protected StringBuilder compute() {
try {
if (!valid(password)) {
List<PasswordKeyValidatorTask> subtasks = new ArrayList<PasswordKeyValidatorTask>();
for (int i = 33; i < 127; i++) {
PasswordKeyValidatorTask task = new PasswordKeyValidatorTask(password.append((char) i));
subtasks.add(task);
}
subtasks.stream().forEach(t -> t.fork());
return subtasks.stream().map(t -> t.join()).findFirst().orElse(null);
}
} catch (Exception e) {
}
return password;
}
boolean valid(StringBuilder s) throws IOException {
String test = "https://samplewebsite.com?pass=";
String q = URLEncoder.encode(s.toString(), StandardCharsets.UTF_8);
URL site = new URL(test + s);
URLConnection yc = site.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream()));
String inputLine;
while ((inputLine = in.readLine()) != null) {
// System.out.println(inputLine);
if (inputLine.contains("Incorrect password!")) {
return false;
}
if (inputLine.contains("the correct password!")) {
System.out.println(s);
}
}
return true;
}
}
公共类测试{
公共静态void main(字符串[]args){
ForkJoinPool ForkJoinPool=新的ForkJoinPool(并行性);
invoke(新的PasswordKeyValidator任务(新的StringBuilder(“开始”));
}
公共静态类PasswordKeyValidator任务扩展了RecursiveTask{
私有静态最终长serialVersionUID=3113010524830439302L;
私有密码;
公共密码KeyValidator任务(StringBuilder密码){
this.password=密码;
}
@凌驾
受保护的StringBuilder compute(){
试一试{
如果(!有效(密码)){
列表子任务=新建ArrayList();
对于(int i=33;i<127;i++){
PasswordKeyValidator任务=新的PasswordKeyValidator任务(password.append((char)i));
子任务。添加(任务);
}
子任务.stream().forEach(t->t.fork());
返回子任务.stream().map(t->t.join()).findFirst().orElse(null);
}
}捕获(例外e){
}
返回密码;
}
布尔有效(StringBuilders)引发IOException{
字符串测试=”https://samplewebsite.com?pass=";
字符串q=URLEncoder.encode(s.toString(),StandardCharsets.UTF_8);
URL站点=新URL(测试+s);
URLConnection yc=site.openConnection();
BufferedReader in=新的BufferedReader(新的InputStreamReader(yc.getInputStream());
字符串输入线;
而((inputLine=in.readLine())!=null){
//系统输出打印LN(输入线);
if(inputLine.contains(“密码不正确!”){
返回false;
}
if(inputLine.contains(“正确的密码!”){
系统输出打印项次;
}
}
返回true;
}
}
}好的,我研究了更多关于并行性的知识,决定使用ForkJoin/RecursiveAction。使用并行性可以将代码执行时间从200秒减少到43秒左右(在我的计算机上)
import java.util.*;
导入java.util.concurrent.*;
导入java.net.http.*;
导入java.net。*;
导入java.nio.charset.StandardCharset;
导入java.io.*;
公开课爆满{
静态类验证程序扩展了RecursiveAction{
公共密码;
公共验证器(StringBuilder p){
密码=p;
}
公共静态布尔有效(StringBuilders)引发IOException、InterruptedException{
HttpClient=HttpClient.newHttpClient();
字符串测试=”https://example.com?pass=“+URLEncoder.encode(s.toString(),StandardCharsets.UTF_8);
HttpRequest request=HttpRequest.newBuilder().uri(uri.create(test)).GET().build();
HttpResponse response=client.send(请求,HttpResponse.BodyHandlers.ofString());
String text=response.body();
if(text.contains(“密码不正确!”){
返回false;
}
if(text.contains(“正确的密码!”){
系统输出打印项次;
系统出口(0);
}
返回true;
}
@凌驾
受保护的void compute(){
试一试{
如果(!valid(password))返回;
ArrayList c=新的ArrayList();
对于(int i=33;i<127;i++){
StringBuilder t=新的StringBuilder(密码).append((char)i);
c、 添加(新验证器(t));
}
ForkJoinTask.invokeAll(c);
}
捕获(IOException | InterruptedException被忽略){
}
}
}
公共静态void main(字符串[]args){
ForkJoinPool ForkJoinPool=新的ForkJoinPool();
invoke(新的验证器(新的StringBuilder(“开始”));
}
}
当我最初编写这段代码时,我使用了.fork()
,但这一点都没有帮助。事实上,它使它的执行速度与顺序代码一样慢。我收集了所有验证器
对象,并使用了ForkJoinTask.invokeAll()
。这个小小的差异导致了几乎200%的加速。你看到了吗
import java.util.*;
import java.util.concurrent.*;
import java.net.http.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.io.*;
public class cracked4 {
static class Validator extends RecursiveAction {
public StringBuilder password;
public Validator(StringBuilder p) {
password = p;
}
public static boolean valid(StringBuilder s) throws IOException, InterruptedException {
HttpClient client = HttpClient.newHttpClient();
String test = "https://example.com?pass=" + URLEncoder.encode(s.toString(), StandardCharsets.UTF_8);
HttpRequest request = HttpRequest.newBuilder().uri(URI.create(test)).GET().build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
String text = response.body();
if (text.contains("Incorrect password!")) {
return false;
}
if (text.contains("the correct password!")) {
System.out.println(s);
System.exit(0);
}
return true;
}
@Override
protected void compute() {
try {
if (!valid(password)) return;
ArrayList<Validator> c = new ArrayList<>();
for (int i = 33; i < 127; i++) {
StringBuilder t = new StringBuilder(password).append((char) i);
c.add(new Validator(t));
}
ForkJoinTask.invokeAll(c);
}
catch (IOException | InterruptedException ignored) {
}
}
}
public static void main(String[] args) {
ForkJoinPool forkJoinPool = new ForkJoinPool();
forkJoinPool.invoke(new Validator(new StringBuilder("start")));
}
}