-
-
一次Web探测服务器技术学习总结
-
发表于: 2021-11-20 14:51 25175
-
最近有一个学习需求,获取域名相应服务器的标题、服务器名、服务器语言、服务器版本等基本信息,为此开始了相关方面的学习和开发,下面是学习过程,本文分为三个部分:
本文第二节讲解本次项目的基本背景知识
本文第三节主要为项目实践,代码开发过程
本文第四节主要介绍一些网络上常见的Web探测的一些方案,并介绍一个自动化的信息获取框架,并完成复现过程
完成一个服务器的基本信息获取,仅仅需要简单的Java HTTP编程知识、Java正则匹配式知识即可
HTTP是一种超文本传输协议,是基于TCP协议之上的一种请求-响应请求协议
浏览器访问某个网站时发送的HTTP请求-响应,当浏览器希望访问某个网站时,浏览器和网站服务器之间先建立TCP连接,且服务器总是使用80端口和加密端口443,然后浏览器向服务器发送一个HTTP请求,服务器收到之后,返回一个HTTP响应,响应中包含了HTML的网页内容,浏览器解析HTML后就给用户显示网页,详细流程图如下所示:
HTTP请求的格式是固定的,由HTTP Header和HTTP Body两部分组成
Get请求和Post请求:
如果是Get请求,那么该HTTP请求只有HTTP Header,没有HTTP Body
如果是POST请求,那么该HTTP请求带有Body,以一个空行分隔,一个典型的带Body的HTTP请求如下:
POST请求通常要设置Content-Type
表示Body
的类型,Content-Length
表示Body的长度,这样服务器可以根据请求的Header和Body做出正确的响应
GET请求的参数必须附加在URL上,并以URLEncode
方式编码,例如:http://www.example.com/?a=1&b=K%26R,参数分别是a=1
和b=K&R
,因为URL的长度限制,GET
请求的参数不能太多,POST
请求的参数就没有长度限制,POST请求的参数必须放在Body
中,POST请求的参数不一定是URL编码,可以按任意1格式编码,只需要在Content-Type
中正确设置即可。发送JSON
的POST
请求:
HTTP响应也是由Header
和Body
两部分组成,一个典型的HTTP响应如下:
响应的第一行是 HTTP版本 响应代码 响应说明
当浏览器收到第一个HTTP响应后,它解析HTML,又会发送一系列HTTP请求,例如,GET /logo.jpg HTTP/1.1
请求一个图片,服务器响应图片请求后,会直接把二进制内容图片发送给浏览器
因此服务器总是被动地接收客户端的一个HTTP请求,然后响应它,客户端则根据需求发送若干个HTTP请求
HTTP 1.0 是每次发送一个HTTP请求,客户端都需要先建立一个新的TCP连接,收到服务器响应后,关闭这个TCP连接
HTTP 1.1协议允许在一个TCP连接中反复发送——响应,这样能大大提升效率
HTTP 2.0 允许客户端在没有收到响应的时候,发送多个HTTP请求,服务器返回响应的时候,不一定按顺序返回,只要双方识别出哪个响应对应哪个请求,就可以做到并行发送和接收
HTTP客户端编程:
JAVA 11开始引入新的HttpClient
,使用链式调用的API,能大大简化HTTP的处理
首先需要创建一个全局HttpClient
实例,因为HttpClient
内部使用线程池优化多个HTTP连接,可以复用:
使用GET
请求获取文本内容
要使用POST
请求,我们要准备好发送的Body数据并正确设置Content-Type
:
这个主要解决一些网址多级别重定向的设置
这里我们就介绍下本文需要用到的一些字段,更详细的可以去参考下面的链接
Curl 学习参考链接:
https://www.ruanyifeng.com/blog/2019/09/curl-reference.html
https://www.ruanyifeng.com/blog/2011/09/curl.html
https://cizixs.com/2014/05/14/curl-automate-http/
我们开始编写获取服务器的项目工程,我们可以在IDEA上新建一个项目工程
细粒度获取:
版本顺序识别:
细粒度获取:
粗粒度获取
测试结果显示:
上文我们初步实现了一个基本的服务器信息获取的项目,经过调研,我总结了一下目前网上的一些常用的方案,并复现了一个自动化的框架
这里我总结调研了网络上常用的一些网站语言测试框架,并总结如下:
这里介绍github上一位老哥开源的框架,使用后发现效果不错,github网址:W11scan网址
由于W11scan是作者从一个纯净的ubuntu上安装的,因此我们最好选用ubuntu系统,这里我们测试的是ubuntu18.0
我们在安装requirements.txt中模块时,可能会提示一些模块的版本过低,我们可以采用pip安装,或单独安装这些模块
我们需要让mongodb在65521端口上运行,先停止mongodb
再启动
我们启动时可能会报错误
解决办法:
我们可以发现此时我们的数据库已经监听在65521端口上了
接着导入指纹
接着输入mongo --port 65521
进入mongodb shellshow dbs
查看是否有w11scan数据库创建,有则创建成功。
接着对结果进行全文索引。 依然在mongodb shell状态下
完成后exit
退出
修改config.py,按照提示配置redis、mongodb用户名密码(如果按上面操作进行的,默认即可)
2.生成django的session
然后我们可以新建任务,开始检测
我们可以发现我们的节点指纹就在不断的检测:
我们只需要等待时间,就可以将我们需要的信息扫描显示出来
我们安装完成之后再次使用:
本文主要从Web探测技术方面学习,初步完成了对服务器版本的一些信息进行获取,然后总结调研了当下的一些网站获取的方式,并在这里为大家复现了一个github上大佬的开源框架,文中可能存在一些不足,希望各位大佬指教,后续研究完成,实例代码会上传个人github:github网址
HTTP学习:
Curl学习:
W11scan学习:
- 一次Web探测服务器技术学习总结
- 一、前言
- 二、基础知识
- 1. HTTP网络编程
- (1)HTTP简介
- <1> HTTP请求
- <2> HTTP响应
- (2)HTTP编程
- 2. Curl 工具的使用
- (1)Curl基本命令
- <1> 查看网页源码
- <2>自动跳转
- <3>显示头信息
- <4>显示通信过程
- <5>发送表单信息
- <6>User Agent字段
- (2)Curl Java代码使用
- 三、项目模块代码
- 1.对象类
- 2.功能函数
- (1)服务器信息获取函数
- (2) 标题获取函数
- (3)获取url编码格式
- (4)正则匹配式
- (5)服务器版本和服务器名获取
- (6)服务器语言获取
- 3.测试函数
- 四、服务器信息探测框架
- 1.网站自动化识别语言框架
- 2.W11scan工具的使用
- (1)工具介绍
- (2)安装步骤
- <1>安装python3、pip,下载软件并安装依赖
- <2>安装redis、mongodb、导出指纹数据
- <3>软件config配置
- <4>运行WEB端
- <5>运行节点
- (3)使用
- 五、实验总结
- 六、参考文献
第一行:请求方法 路径 HTTP版本 例如,GET
/
HTTP
/
1.1
表示使用GET请求,路径是
/
,版本是HTTP
/
1.1
后续各行的每一行是固定的Header:Value格式,我们称为HTTP Header,服务器依靠某些特定的Header来识别客服端请求
Host:表示请求的域名
User
-
Agent:表示客户端自身标识信息,不同的浏览器有不同的标识,服务器依靠User
-
Agent判断客户端类型是IE还是Chrome,是Firefox还是一个Python爬虫
Accept:表示客户端能处理的HTTP响应格式,
*
/
*
表示任意格式,text
/
*
表示任意文本,image
/
png表示PNG格式的图片
Accept
-
Language:表示客户端接收的语言,多种语言按优先级排序,服务器依靠该字段给用户返回特定语言的网页版本
第一行:请求方法 路径 HTTP版本 例如,GET
/
HTTP
/
1.1
表示使用GET请求,路径是
/
,版本是HTTP
/
1.1
后续各行的每一行是固定的Header:Value格式,我们称为HTTP Header,服务器依靠某些特定的Header来识别客服端请求
Host:表示请求的域名
User
-
Agent:表示客户端自身标识信息,不同的浏览器有不同的标识,服务器依靠User
-
Agent判断客户端类型是IE还是Chrome,是Firefox还是一个Python爬虫
Accept:表示客户端能处理的HTTP响应格式,
*
/
*
表示任意格式,text
/
*
表示任意文本,image
/
png表示PNG格式的图片
Accept
-
Language:表示客户端接收的语言,多种语言按优先级排序,服务器依靠该字段给用户返回特定语言的网页版本
POST
/
login HTTP
/
1.1
Host: www.example.com
Content
-
Type
: application
/
x
-
www
-
form
-
urlencoded
Content
-
Length:
30
username
=
hello&password
=
123456
POST
/
login HTTP
/
1.1
Host: www.example.com
Content
-
Type
: application
/
x
-
www
-
form
-
urlencoded
Content
-
Length:
30
username
=
hello&password
=
123456
POST
/
login HTTP
/
1.1
Content
-
Type
: application
/
json
Content
-
Length:
38
{
"username"
:
"bob"
,
"password"
:
"123456"
}
POST
/
login HTTP
/
1.1
Content
-
Type
: application
/
json
Content
-
Length:
38
{
"username"
:
"bob"
,
"password"
:
"123456"
}
HTTP
/
1.1
200
OK
Content
-
Type
: text
/
html
Content
-
Length:
133251
<!DOCTYPE html>
<html><body>
<h1>Hello<
/
h1>
...
HTTP
/
1.1
200
OK
Content
-
Type
: text
/
html
Content
-
Length:
133251
<!DOCTYPE html>
<html><body>
<h1>Hello<
/
h1>
...
1xx
:表示一个提示性响应,例如
101
表示将切换协议,常见于WebSocket连接;
2xx
:表示一个成功的响应,例如
200
表示成功,
206
表示只发送了部分内容;
3xx
:表示一个重定向的响应,例如
301
表示永久重定向,
303
表示客户端应该按指定路径重新发送请求;
4xx
:表示一个因为客户端问题导致的错误响应,例如
400
表示因为Content
-
Type
等各种原因导致的无效请求,
404
表示指定的路径不存在;
5xx
:表示一个因为服务器问题导致的错误响应,例如
500
表示服务器内部故障,
503
表示服务器暂时无法响应。
1xx
:表示一个提示性响应,例如
101
表示将切换协议,常见于WebSocket连接;
2xx
:表示一个成功的响应,例如
200
表示成功,
206
表示只发送了部分内容;
3xx
:表示一个重定向的响应,例如
301
表示永久重定向,
303
表示客户端应该按指定路径重新发送请求;
4xx
:表示一个因为客户端问题导致的错误响应,例如
400
表示因为Content
-
Type
等各种原因导致的无效请求,
404
表示指定的路径不存在;
5xx
:表示一个因为服务器问题导致的错误响应,例如
500
表示服务器内部故障,
503
表示服务器暂时无法响应。
HTTP
/
1.1
200
OK
Content
-
Type
: image
/
jpeg
Content
-
Length:
18391
????JFIFHH??XExifMM?i&??X?...(二进制的JPEG图片)
HTTP
/
1.1
200
OK
Content
-
Type
: image
/
jpeg
Content
-
Length:
18391
????JFIFHH??XExifMM?i&??X?...(二进制的JPEG图片)
URL url
=
new URL(
"http://www.example.com/path/to/target?a=1&b=2"
);
HttpURLConnection conn
=
(HttpURLConnection) url.openConnection();
conn.setRequestMethod(
"GET"
);
conn.setUseCaches(false);
conn.setConnectTimeout(
5000
);
/
/
请求超时
5
秒
/
/
设置HTTP头:
conn.setRequestProperty(
"Accept"
,
"*/*"
);
conn.setRequestProperty(
"User-Agent"
,
"Mozilla/5.0 (compatible; MSIE 11; Windows NT 5.1)"
);
/
/
连接并发送HTTP请求:
conn.connect();
/
/
判断HTTP响应是否
200
:
if
(conn.getResponseCode() !
=
200
) {
throw new RuntimeException(
"bad response"
);
}
/
/
获取所有响应Header:
Map
<String,
List
<String>>
map
=
conn.getHeaderFields();
for
(String key :
map
.keySet()) {
System.out.println(key
+
": "
+
map
.get(key));
}
/
/
获取响应内容:
BufferedReader reader
=
new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line
=
reader.readLine();
while
(line !
=
null){
...
}
URL url
=
new URL(
"http://www.example.com/path/to/target?a=1&b=2"
);
HttpURLConnection conn
=
(HttpURLConnection) url.openConnection();
conn.setRequestMethod(
"GET"
);
conn.setUseCaches(false);
conn.setConnectTimeout(
5000
);
/
/
请求超时
5
秒
/
/
设置HTTP头:
conn.setRequestProperty(
"Accept"
,
"*/*"
);
conn.setRequestProperty(
"User-Agent"
,
"Mozilla/5.0 (compatible; MSIE 11; Windows NT 5.1)"
);
/
/
连接并发送HTTP请求:
conn.connect();
/
/
判断HTTP响应是否
200
:
if
(conn.getResponseCode() !
=
200
) {
throw new RuntimeException(
"bad response"
);
}
/
/
获取所有响应Header:
Map
<String,
List
<String>>
map
=
conn.getHeaderFields();
for
(String key :
map
.keySet()) {
System.out.println(key
+
": "
+
map
.get(key));
}
/
/
获取响应内容:
BufferedReader reader
=
new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line
=
reader.readLine();
while
(line !
=
null){
...
}
static HttpClient httpClient
=
HttpClient.newBuilder().build();
static HttpClient httpClient
=
HttpClient.newBuilder().build();
import
java.net.URI;
import
java.net.http.
*
;
import
java.net.http.HttpClient.Version;
import
java.time.Duration;
import
java.util.
*
;
public
class
Main {
/
/
全局HttpClient:
static HttpClient httpClient
=
HttpClient.newBuilder().build();
public static void main(String[] args) throws Exception {
String url
=
"https://www.sina.com.cn/"
;
HttpRequest request
=
HttpRequest.newBuilder(new URI(url))
/
/
设置Header:
.header(
"User-Agent"
,
"Java HttpClient"
).header(
"Accept"
,
"*/*"
)
/
/
设置超时:
.timeout(Duration.ofSeconds(
5
))
/
/
设置版本:
.version(Version.HTTP_2).build();
HttpResponse<String> response
=
httpClient.send(request, HttpResponse.BodyHandlers.ofString());
/
/
HTTP允许重复的Header,因此一个Header可对应多个Value:
Map
<String,
List
<String>> headers
=
response.headers().
map
();
for
(String header : headers.keySet()) {
System.out.println(header
+
": "
+
headers.get(header).get(
0
));
}
System.out.println(response.body().substring(
0
,
1024
)
+
"..."
);
}
}
import
java.net.URI;
import
java.net.http.
*
;
import
java.net.http.HttpClient.Version;
import
java.time.Duration;
import
java.util.
*
;
public
class
Main {
/
/
全局HttpClient:
static HttpClient httpClient
=
HttpClient.newBuilder().build();
public static void main(String[] args) throws Exception {
String url
=
"https://www.sina.com.cn/"
;
HttpRequest request
=
HttpRequest.newBuilder(new URI(url))
/
/
设置Header:
.header(
"User-Agent"
,
"Java HttpClient"
).header(
"Accept"
,
"*/*"
)
/
/
设置超时:
.timeout(Duration.ofSeconds(
5
))
/
/
设置版本:
.version(Version.HTTP_2).build();
HttpResponse<String> response
=
httpClient.send(request, HttpResponse.BodyHandlers.ofString());
/
/
HTTP允许重复的Header,因此一个Header可对应多个Value:
Map
<String,
List
<String>> headers
=
response.headers().
map
();
for
(String header : headers.keySet()) {
System.out.println(header
+
": "
+
headers.get(header).get(
0
));
}
System.out.println(response.body().substring(
0
,
1024
)
+
"..."
);
}
}
String url
=
"http://www.example.com/login"
;
String body
=
"username=bob&password=123456"
;
HttpRequest request
=
HttpRequest.newBuilder(new URI(url))
/
/
设置Header:
.header(
"Accept"
,
"*/*"
)
.header(
"Content-Type"
,
"application/x-www-form-urlencoded"
)
/
/
设置超时:
.timeout(Duration.ofSeconds(
5
))
/
/
设置版本:
.version(Version.HTTP_2)
/
/
使用POST并设置Body:
.POST(BodyPublishers.ofString(body, StandardCharsets.UTF_8)).build();
HttpResponse<String> response
=
httpClient.send(request, HttpResponse.BodyHandlers.ofString());
String s
=
response.body();
String url
=
"http://www.example.com/login"
;
String body
=
"username=bob&password=123456"
;
HttpRequest request
=
HttpRequest.newBuilder(new URI(url))
/
/
设置Header:
.header(
"Accept"
,
"*/*"
)
.header(
"Content-Type"
,
"application/x-www-form-urlencoded"
)
/
/
设置超时:
.timeout(Duration.ofSeconds(
5
))
/
/
设置版本:
.version(Version.HTTP_2)
/
/
使用POST并设置Body:
.POST(BodyPublishers.ofString(body, StandardCharsets.UTF_8)).build();
HttpResponse<String> response
=
httpClient.send(request, HttpResponse.BodyHandlers.ofString());
String s
=
response.body();
curl www.baidu.com
curl
-
o [文件名] www.baidu.com
/
/
使用
-
o参数,相当于使用wget命令
curl www.baidu.com
curl
-
o [文件名] www.baidu.com
/
/
使用
-
o参数,相当于使用wget命令
curl
-
L www.baidu.com
curl
-
L www.baidu.com
curl
-
i www.baidu.com
/
/
获取响应头的信息
curl
-
-
trace output.txt www.baidu.com
/
/
使用trace可以获取更加详细的信息
curl
-
i www.baidu.com
/
/
获取响应头的信息
curl
-
-
trace output.txt www.baidu.com
/
/
使用trace可以获取更加详细的信息
curl
-
v www.baidu.com
-
v参数可以显示一次http通信的整个过程,包括端口连接和http request头信息
curl
-
v www.baidu.com
-
v参数可以显示一次http通信的整个过程,包括端口连接和http request头信息
curl example.com
/
form.cgi?data
=
xxx
/
/
GET方法相对简单,只要把数据附在网址后面就行
curl
-
X POST
-
-
data
"data=xxx"
example.com
/
form.cgi
/
/
POST方法必须把数据和网址分开,curl就要用到
-
-
data参数
curl example.com
/
form.cgi?data
=
xxx
/
/
GET方法相对简单,只要把数据附在网址后面就行
curl
-
X POST
-
-
data
"data=xxx"
example.com
/
form.cgi
/
/
POST方法必须把数据和网址分开,curl就要用到
-
-
data参数
这个字段是用来表示客户端的设备信息。服务器有时会根据这个字段,针对不同设备,返回不同格式的网页
curl
-
-
user
-
agent
"[User Agent]"
[URL]
/
/
也可以用
-
A 来替代
-
-
user
-
agent
这个字段是用来表示客户端的设备信息。服务器有时会根据这个字段,针对不同设备,返回不同格式的网页
curl
-
-
user
-
agent
"[User Agent]"
[URL]
/
/
也可以用
-
A 来替代
-
-
user
-
agent
/
*
*
功能说明
*
Curl指令的java代码
*
输入函数:curl指令
*
返回参数:curl指令的返回值
*
例子:curl [option] [url]
*
curl url
/
/
获取url的html
*
curl
-
A
"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.0)"
url
/
/
使用指定的浏览器去访问
*
curl
-
I url
/
/
返回header信息
*
*
/
public static String execCurl(String[] cmds,String chartname) {
ProcessBuilder process
=
new ProcessBuilder(cmds);
Process p;
try
{
p
=
process.start();
BufferedReader reader
=
new BufferedReader(new InputStreamReader(p.getInputStream(),chartname));
StringBuilder builder
=
new StringBuilder();
String line;
while
((line
=
reader.readLine()) !
=
null) {
builder.append(line);
builder.append(System.getProperty(
"line.separator"
));
}
return
builder.toString();
} catch (IOException e) {
System.out.
print
(
"error"
);
e.printStackTrace();
}
return
null;
}
/
*
*
功能说明
*
Curl指令的java代码
*
输入函数:curl指令
*
返回参数:curl指令的返回值
*
例子:curl [option] [url]
*
curl url
/
/
获取url的html
*
curl
-
A
"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.0)"
url
/
/
使用指定的浏览器去访问
*
curl
-
I url
/
/
返回header信息
*
*
/
public static String execCurl(String[] cmds,String chartname) {
ProcessBuilder process
=
new ProcessBuilder(cmds);
Process p;
try
{
p
=
process.start();
BufferedReader reader
=
new BufferedReader(new InputStreamReader(p.getInputStream(),chartname));
StringBuilder builder
=
new StringBuilder();
String line;
while
((line
=
reader.readLine()) !
=
null) {
builder.append(line);
builder.append(System.getProperty(
"line.separator"
));
}
return
builder.toString();
} catch (IOException e) {
System.out.
print
(
"error"
);
e.printStackTrace();
}
return
null;
}
String[] cmds
=
{
"curl"
,
"-A"
,
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36"
,
"-L"
,
"-i"
,domain};
String result_html
=
execCurl(cmds,charset);
String[] cmds
=
{
"curl"
,
"-A"
,
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36"
,
"-L"
,
"-i"
,domain};
String result_html
=
execCurl(cmds,charset);
public
class
WebInfo {
public String domain
=
"";
public String ip
=
"";
public String title
=
"";
public String http_server
=
"";
public String http_server_version
=
"";
public String language
=
"";
public String set_Cookie
=
"";
public String X_Powered_By
=
"";
/
/
服务器加密的状态
public Boolean isServerCrypto
=
false;
public String charset
=
"";
public WebInfo(){}
public String toString(){
String
str
=
"";
str
=
str
+
this.domain
+
"\t"
;
str
=
str
+
this.ip
+
"\t"
;
str
=
str
+
this.title
+
"\t"
;
str
=
str
+
this.http_server
+
"\t"
;
str
=
str
+
this.http_server_version
+
"\t"
;
str
=
str
+
this.language
+
"\t"
;
return
str
;
}
public boolean checkComplete() {
return
this.title !
=
null && this.title.length() >
0
&& this.http_server !
=
null && this.http_server.length() >
0
&& this.language !
=
null && this.language.length() >
0
;
}
public
class
WebInfo {
public String domain
=
"";
public String ip
=
"";
public String title
=
"";
public String http_server
=
"";
public String http_server_version
=
"";
public String language
=
"";
public String set_Cookie
=
"";
public String X_Powered_By
=
"";
/
/
服务器加密的状态
public Boolean isServerCrypto
=
false;
public String charset
=
"";
public WebInfo(){}
public String toString(){
String
str
=
"";
str
=
str
+
this.domain
+
"\t"
;
str
=
str
+
this.ip
+
"\t"
;
str
=
str
+
this.title
+
"\t"
;
str
=
str
+
this.http_server
+
"\t"
;
str
=
str
+
this.http_server_version
+
"\t"
;
str
=
str
+
this.language
+
"\t"
;
return
str
;
}
public boolean checkComplete() {
return
this.title !
=
null && this.title.length() >
0
&& this.http_server !
=
null && this.http_server.length() >
0
&& this.language !
=
null && this.language.length() >
0
;
}
/
/
使用curl获取服务器信息,输入url
public static void getServerInfo(WebInfo wi,String domain) throws IOException {
String charset
=
"utf-8"
;
charset
=
getCharset(domain);
/
/
System.out.println(
"charset:"
+
charset);
if
(!matcherChar(charset,
"gb"
)){
charset
=
"utf-8"
;
}
/
/
-
L 跟随跳转
-
i 打印详细信息
String[] cmds
=
{
"curl"
,
"-A"
,
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36"
,
"-L"
,
"-i"
,domain};
String result_html
=
execCurl(cmds,charset);
/
/
获取的header和html信息
/
/
System.out.println(result_html);
if
(!result_html.isEmpty()){
wi.title
=
getTitle(result_html);
}
else
{
System.out.println(
"无法获取域名的html"
);
}
strName(wi,result_html);
LanguageCheck(wi);
NormalLanguageTest(wi);
ExceptionCheck(wi);
/
/
CheckStatus(wi);
}
/
/
使用curl获取服务器信息,输入url
public static void getServerInfo(WebInfo wi,String domain) throws IOException {
String charset
=
"utf-8"
;
charset
=
getCharset(domain);
/
/
System.out.println(
"charset:"
+
charset);
if
(!matcherChar(charset,
"gb"
)){
charset
=
"utf-8"
;
}
/
/
-
L 跟随跳转
-
i 打印详细信息
String[] cmds
=
{
"curl"
,
"-A"
,
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36"
,
"-L"
,
"-i"
,domain};
String result_html
=
execCurl(cmds,charset);
/
/
获取的header和html信息
/
/
System.out.println(result_html);
if
(!result_html.isEmpty()){
wi.title
=
getTitle(result_html);
}
else
{
System.out.println(
"无法获取域名的html"
);
}
strName(wi,result_html);
LanguageCheck(wi);
NormalLanguageTest(wi);
ExceptionCheck(wi);
/
/
CheckStatus(wi);
}
/
*
*
功能说明
*
Curl指令的java代码
*
输入函数:curl指令
*
返回参数:curl指令的返回值
*
例子:curl [option] [url]
*
curl url
/
/
获取url的html
*
curl
-
A
"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.0)"
url
/
/
使用指定的浏览器去访问
*
curl
-
I url
/
/
返回header信息
*
*
/
public static String execCurl(String[] cmds,String chartname) {
ProcessBuilder process
=
new ProcessBuilder(cmds);
Process p;
try
{
p
=
process.start();
BufferedReader reader
=
new BufferedReader(new InputStreamReader(p.getInputStream(),chartname));
StringBuilder builder
=
new StringBuilder();
String line;
while
((line
=
reader.readLine()) !
=
null) {
builder.append(line);
builder.append(System.getProperty(
"line.separator"
));
}
return
builder.toString();
} catch (IOException e) {
System.out.
print
(
"error"
);
e.printStackTrace();
}
return
null;
}
/
*
*
功能说明
*
Curl指令的java代码
*
输入函数:curl指令
*
返回参数:curl指令的返回值
*
例子:curl [option] [url]
*
curl url
/
/
获取url的html
*
curl
-
A
"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.0)"
url
/
/
使用指定的浏览器去访问
*
curl
-
I url
/
/
返回header信息
*
*
/
public static String execCurl(String[] cmds,String chartname) {
ProcessBuilder process
=
new ProcessBuilder(cmds);
Process p;
try
{
p
=
process.start();
BufferedReader reader
=
new BufferedReader(new InputStreamReader(p.getInputStream(),chartname));
StringBuilder builder
=
new StringBuilder();
String line;
while
((line
=
reader.readLine()) !
=
null) {
builder.append(line);
builder.append(System.getProperty(
"line.separator"
));
}
return
builder.toString();
} catch (IOException e) {
System.out.
print
(
"error"
);
e.printStackTrace();
}
return
null;
}
/
*
*
函数说明:
*
getTitle(String webcontent):
*
输入参数:web页面信息html
*
返回结果:标题
*
*
/
public static String getTitle(String webContent){
Pattern pattern
=
Pattern.
compile
(
"<title>.*?</title>"
,Pattern.CASE_INSENSITIVE|Pattern.DOTALL);
Matcher ma
=
pattern.matcher(webContent);
while
(ma.find()){
/
/
System.out.println(ma.group());
return
outTag(ma.group());
}
return
null;
}
/
*
*
函数说明:
*
getTitle(String webcontent):
*
输入参数:web页面信息html
*
返回结果:标题
*
*
/
public static String getTitle(String webContent){
Pattern pattern
=
Pattern.
compile
(
"<title>.*?</title>"
,Pattern.CASE_INSENSITIVE|Pattern.DOTALL);
Matcher ma
=
pattern.matcher(webContent);
while
(ma.find()){
/
/
System.out.println(ma.group());
return
outTag(ma.group());
}
return
null;
}
/
/
去除标题中的一些无关信息
public static String outTag(String s)
{
String title
=
s.replaceAll(
"<.*?>"
, "");
title
=
replaceBlank(title);
title
=
title.replace(
"首页"
, "");
title
=
title.replace(
"-"
, "");
title
=
title.replace(
"主页"
, "");
title
=
title.replace(
"官网"
, "");
title
=
title.replace(
"欢迎进入"
, "");
title
=
title.replace(
"欢迎访问"
, "");
title
=
title.replace(
"登录入口"
, "");
return
title;
}
/
/
去除标题中的一些无关信息
public static String outTag(String s)
{
String title
=
s.replaceAll(
"<.*?>"
, "");
title
=
replaceBlank(title);
title
=
title.replace(
"首页"
, "");
title
=
title.replace(
"-"
, "");
title
=
title.replace(
"主页"
, "");
title
=
title.replace(
"官网"
, "");
title
=
title.replace(
"欢迎进入"
, "");
title
=
title.replace(
"欢迎访问"
, "");
title
=
title.replace(
"登录入口"
, "");
return
title;
}
/
/
除去标题字符串中的\t制表符 \n回车 \r换行符
public static String replaceBlank(String
str
) {
String dest
=
"";
if
(
str
!
=
null) {
Pattern p
=
Pattern.
compile
(
"\\s*|\t|\r|\n"
);
Matcher m
=
p.matcher(
str
);
dest
=
m.replaceAll("");
}
return
dest;
}
/
/
除去标题字符串中的\t制表符 \n回车 \r换行符
public static String replaceBlank(String
str
) {
String dest
=
"";
if
(
str
!
=
null) {
Pattern p
=
Pattern.
compile
(
"\\s*|\t|\r|\n"
);
Matcher m
=
p.matcher(
str
);
dest
=
m.replaceAll("");
}
return
dest;
}
public static String getCharset(String link) {
String charset
=
"utf-8"
;
HttpURLConnection conn
=
null;
try
{
URL url
=
new URL(link);
conn
=
(HttpURLConnection)url.openConnection();
conn.setRequestProperty(
"User-Agent"
,
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36"
);
conn.connect();
System.setProperty(
"sun.net.client.defaultConnectTimeout"
,
"30000"
);
System.setProperty(
"sun.net.client.defaultReadTimeout"
,
"30000"
);
String contentType
=
conn.getContentType();
/
/
在header里面找charset
charset
=
findCharset(contentType);
/
/
System.out.println(
"header:"
+
charset);
/
/
如果没找到的话,则一行一行的读入页面的html代码,从html代码中寻找
if
(charset.isEmpty()){
BufferedReader reader
=
new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line
=
reader.readLine();
while
(line !
=
null) {
if
(line.contains(
"Content-Type"
)) {
/
/
result
=
findCharset(line);
Pattern p
=
Pattern.
compile
(
"content=\"text/html;\\s*charset=([^>]*)\""
);
Matcher m
=
p.matcher(line);
if
(m.find()) {
charset
=
m.group(
1
);
System.out.println(
"html:"
+
charset);
}
break
;
}
line
=
reader.readLine();
}
reader.close();
}
} catch (Exception e) {
/
/
TODO Auto
-
generated catch block
/
/
这里可以打印响应不了的域名错误信息
/
/
e.printStackTrace();
}
finally
{
conn.disconnect();
}
return
charset;
}
public static String getCharset(String link) {
String charset
=
"utf-8"
;
HttpURLConnection conn
=
null;
try
{
URL url
=
new URL(link);
conn
=
(HttpURLConnection)url.openConnection();
conn.setRequestProperty(
"User-Agent"
,
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36"
);
conn.connect();
System.setProperty(
"sun.net.client.defaultConnectTimeout"
,
"30000"
);
System.setProperty(
"sun.net.client.defaultReadTimeout"
,
"30000"
);
String contentType
=
conn.getContentType();
/
/
在header里面找charset
charset
=
findCharset(contentType);
/
/
System.out.println(
"header:"
+
charset);
/
/
如果没找到的话,则一行一行的读入页面的html代码,从html代码中寻找
if
(charset.isEmpty()){
BufferedReader reader
=
new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line
=
reader.readLine();
while
(line !
=
null) {
if
(line.contains(
"Content-Type"
)) {
/
/
result
=
findCharset(line);
Pattern p
=
Pattern.
compile
(
"content=\"text/html;\\s*charset=([^>]*)\""
);
Matcher m
=
p.matcher(line);
if
(m.find()) {
charset
=
m.group(
1
);
System.out.println(
"html:"
+
charset);
}
break
;
}
line
=
reader.readLine();
}
reader.close();
}