HttpClient发起HTTP请求流程
Dart IO库中提供了用于发起Http请求的一些类,我们可以直接使用HttpClient来发起请求。使用HttpClient发起请求分为五步:
1. 创建一个HttpClient
HttpClient httpClient = new HttpClient();
2. 打开Http连接,设置请求头
HttpClientRequest request = await httpClient.getUrl(uri);
这一步可以使用任意Http Method,如
httpClient.get(host, port, path)
httpClient.patch(host, port, path)
httpClient.open(method, host, port, path)
httpClient.head(host, port, path)
httpClient.post(host, port, path)
httpClient.put(host, port, path)
httpClient.delete(host, port, path)
httpClient.getUrl(uri)
httpClient.patchUrl(uri)
httpClient.openUrl(method, url)
httpClient.headUrl(uri)
httpClient.postUrl(uri)
httpClient.putUrl(uri)
httpClient.deleteUrl(uri)
等
如果包含Query参数,可以在构建uri时添加,如:
Uri uri=Uri(scheme: "https", host: "flutterchina.club", queryParameters: {
"xx":"xx",
"yy":"dd"
});
// (new) Uri Uri({
// String scheme,
// String userInfo,
// String host,
// int port,
// String path,
// Iterable<String> pathSegments,
// String query,
// Map<String,
// dynamic> queryParameters,
// String fragment})
通过HttpClientRequest可以设置请求header,如:
request.headers.add("user-agent", "test");
如果是post或put等可以携带请求体方法,可以通过HttpClientRequest对象发送request body,如:
String payload="...";
request.add(utf8.encode(payload));
//request.addStream(_inputStream); //可以直接添加输入流
3. 等待连接服务器
HttpClientResponse response = await request.close();
这一步完成后,请求信息就已经发送给服务器了,返回一个HttpClientResponse对象,它包含响应头(header)和响应流(响应体的Stream),接下来就可以通过读取响应流来获取响应内容。
4. 读取响应内容
String responseBody = await response.transform(utf8.decoder).join();
我们通过读取响应流来获取服务器返回的数据,在读取时我们可以设置编码格式,这里是utf8。
5. 请求结束,关闭HttpClient
httpClient.close();
关闭client后,通过该client发起的所有请求都会中止
具体代码
void requestTest() async {
//1.创建一个HttpClient:
HttpClient httpClient = new HttpClient();
//2.打开Http连接,设置请求头:
HttpClientRequest request = await httpClient.getUrl(uri);
Uri uri = Uri(
scheme: "https",
host: "flutterchina.club",
queryParameters: {"xx": "xx", "yy": "dd"});
//3.等待连接服务器:
HttpClientResponse response = await request.close();
//4.读取响应内容
String responseBody = await response.transform(utf8.decoder).join();
//5.请求结束,关闭HttpClient
httpClient.close();
print(responseBody);
}
示例
我们实现一个获取百度首页html的例子,示例效果如图所示:
点击“获取百度首页”按钮后,会请求百度首页,请求成功后,我们将返回内容显示出来并在控制台打印响应header,代码如下:
import 'package:flutter/material.dart';
import 'dart:convert';
import 'dart:io';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: true,
title: '网络请求',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(title: Text("网络请求")),
body: HttpTestRoute(),
));
}
}
class HttpTestRoute extends StatefulWidget {
@override
_HttpTestRouteState createState() => new _HttpTestRouteState();
}
class _HttpTestRouteState extends State<HttpTestRoute> {
bool _loading = false;
String _text = "";
@override
Widget build(BuildContext context) {
return ConstrainedBox(
constraints: BoxConstraints.expand(),
child: SingleChildScrollView(
child: Column(
children: <Widget>[
RaisedButton(
child: Text("获取京东首页"),
onPressed: _loading ? null : () async {
setState(() {
_loading = true;
_text = "正在请求...";
});
try {
//创建一个HttpClient
HttpClient httpClient = new HttpClient();
//打开Http连接
HttpClientRequest request = await httpClient.getUrl(
Uri.parse("https://www.jd.com"));
//使用iPhone的UA
request.headers.add("user-agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1");
//等待连接服务器(会将请求信息发送给服务器)
HttpClientResponse response = await request.close();
//读取响应内容
_text = await response.transform(utf8.decoder).join();
//输出响应头
print(response.headers);
setState(() {
_loading = false;
_text = _text;
});
//关闭client后,通过该client发起的所有请求都会中止。
httpClient.close();
} catch (e) {
_text = "请求失败:$e";
} finally {
setState(() {
_loading = false;
});
}
}
),
Container(
width: MediaQuery.of(context).size.width-50.0,
child: Text(_text.replaceAll(new RegExp(r"\s"), ""))
)
],
),
),
);
}
}
控制台输出:
I/flutter (18545): connection: Keep-Alive
I/flutter (18545): cache-control: no-cache
I/flutter (18545): set-cookie: .... //有多个,省略...
I/flutter (18545): transfer-encoding: chunked
I/flutter (18545): date: Tue, 30 Oct 2018 10:00:52 GMT
I/flutter (18545): content-encoding: gzip
I/flutter (18545): vary: Accept-Encoding
I/flutter (18545): strict-transport-security: max-age=172800
I/flutter (18545): content-type: text/html;charset=utf-8
I/flutter (18545): tracecode: 00525262401065761290103018, 00522983
HttpClient请求头配置
HttpClient有很多属性可以配置,常用的属性列表如下:
属性 | 含义 |
---|---|
idleTimeout | 对应请求头中的keep-alive字段值,为了避免频繁建立连接,httpClient在请求结束后会保持连接一段时间,超过这个阈值后才会关闭连接。 |
connectionTimeout | 和服务器建立连接的超时,如果超过这个值则会抛出SocketException异常。 |
maxConnectionsPerHost | 同一个host,同时允许建立连接的最大数量。 |
autoUncompress | 对应请求头中的Content-Encoding,如果设置为true,则请求头中Content-Encoding的值为当前HttpClient支持的压缩算法列表,目前只有”gzip” |
userAgent | 对应请求头中的User-Agent字段。 |
可以发现,有些属性只是为了更方便的设置请求头,对于这些属性,完全可以通过HttpClientRequest直接设置header
- 不同的是通过HttpClient设置的对整个httpClient都生效
- 而通过HttpClientRequest设置的只对当前请求生效
HTTP请求认证
Http协议的认证(Authentication)机制可以用于保护非公开资源。如果Http服务器开启了认证,那么用户在发起请求时就需要携带用户凭据,如果你在浏览器中访问了启用Basic认证的资源时,浏览就会弹出一个登录框,如:
我们先看看Basic认证的基本过程:
客户端发送http请求给服务器,服务器验证该用户是否已经登录验证过了,如果没有的话, 服务器会返回一个401 Unauthozied给客户端,并且在响应header中添加一个 “WWW-Authenticate” 字段,例如:
WWW-Authenticate: Basic realm="admin"
其中”Basic”为认证方式,realm为用户角色的分组,可以在后台添加分组。
- 客户端得到响应码后,将用户名和密码进行base64编码(格式为用户名:密码),设置请求头Authorization,继续访问 :
服务器验证用户凭据,如果通过就返回资源内容。Authorization: Basic YXXFISDJFISJFGIJIJG
注意,Http的方式除了Basic认证之外还有:
- Digest认证
- Client认证
- Form Based认证等
目前Flutter的HttpClient只支持
- Basic认证
- Digest认证
这两种认证方式最大的区别是发送用户凭据时,对于用户凭据的内容
- Basic认证只是简单的通过Base64编码(可逆)
- Digest认证会进行哈希运算,相对来说安全一点点
但是为了安全起见,无论是采用Basic认证还是Digest认证,都应该在Https协议下,这样可以防止抓包和中间人攻击
HttpClient关于Http认证的方法和属性
- addCredentials(Uri url, String realm, HttpClientCredentials credentials)
该方法用于添加用户凭据,如:
如果是Digest认证,可以创建Digest认证凭据:httpClient.addCredentials(_uri, "admin", new HttpClientBasicCredentials("username","password"), //Basic认证凭据 );
HttpClientDigestCredentials("username","password")
- authenticate(Future
f(Uri url, String scheme, String realm))
这是一个setter,类型是一个回调,当服务器需要用户凭据且该用户凭据未被添加时,httpClient会调用此回调,在这个回调当中,一般会调用addCredentials()来动态添加用户凭证,例如:
一个建议是,如果所有请求都需要认证,那么应该在HttpClient初始化时就调用addCredentials()来添加全局凭证,而不是去动态添加。httpClient.authenticate=(Uri url, String scheme, String realm) async{ if(url.host=="xx.com" && realm=="admin"){ httpClient.addCredentials(url, "admin", new HttpClientBasicCredentials("username","pwd"), ); return true; } return false; };
代理
可以通过findProxy来设置代理策略,例如,我们要将所有请求通过代理服务器(192.168.1.2:8888)发送出去:
client.findProxy = (uri) {
// 如果需要过滤uri,可以手动判断
return "PROXY 192.168.1.2:8888";
};
findProxy 回调返回值是一个遵循浏览器PAC脚本格式的字符串,详情可以查看API文档,如果不需要代理,返回”DIRECT”即可。
在APP开发中,很多时候我们需要抓包来调试,而抓包软件(如charles)就是一个代理,这时我们就可以将请求发送到我们的抓包软件,我们就可以在抓包软件中看到请求的数据了。
有时代理服务器也启用了身份验证,这和http协议的认证是相似的,HttpClient提供了对应的Proxy认证方法和属性:
set authenticateProxy(
Future<bool> f(String host, int port, String scheme, String realm));
void addProxyCredentials(
String host, int port, String realm, HttpClientCredentials credentials);
他们的使用方法和上面“HTTP请求认证”一节中介绍的addCredentials和authenticate 相同,故不再赘述。
证书校验
Https中为了防止通过伪造证书而发起的中间人攻击,客户端应该对自签名或非CA颁发的证书进行校验。HttpClient对证书校验的逻辑如下:
- 如果请求的Https证书是可信CA颁发的,并且访问host包含在证书的domain列表中(或者符合通配规则)并且证书未过期,则验证通过。
- 如果第一步验证失败,但在创建HttpClient时,已经通过SecurityContext将证书添加到证书信任链中,那么当服务器返回的证书在信任链中的话,则验证通过。
- 如果1、2验证都失败了,如果用户提供了badCertificateCallback回调,则会调用它,如果回调返回true,则允许继续链接,如果返回false,则终止链接。
综上所述,我们的证书校验其实就是提供一个badCertificateCallback回调,下面通过一个示例来说明。
示例
假设我们的后台服务使用的是自签名证书,证书格式是PEM格式,我们将证书的内容保存在本地字符串中,那么我们的校验逻辑如下:
String PEM="XXXXX";//可以从文件读取
...
httpClient.badCertificateCallback=(X509Certificate cert, String host, int port){
if(cert.pem==PEM){
return true; //证书一致,则允许发送数据
}
return false;
};
X509Certificate是证书的标准格式,包含了证书除私钥外所有信息,读者可以自行查阅文档。另外,上面的示例没有校验host,是因为只要服务器返回的证书内容和本地的保存一致就已经能证明是我们的服务器了(而不是中间人),host验证通常是为了防止证书和域名不匹配。
对于自签名的证书,我们也可以将其添加到本地证书信任链中,这样证书验证时就会自动通过,而不会再走到badCertificateCallback回调中:
SecurityContext sc=new SecurityContext();
//file为证书路径
sc.setTrustedCertificates(file);
//创建一个HttpClient
HttpClient httpClient = new HttpClient(context: sc);
注意,通过setTrustedCertificates()设置的证书格式必须为PEM或PKCS12,如果证书格式为PKCS12,则需将证书密码传入,这样则会在代码中暴露证书密码,所以客户端证书校验不建议使用PKCS12格式的证书。
扩展:HTTP HTTPSCASSLTLS
协议 | 描述 | 区别 |
---|---|---|
HTTP HyperText Transfer Protocol 超文本传输协议 |
- HTTP就是平时浏览网页时候使用的一种协议; - 输的数据都是明文,未加密的,也就是传输隐私信息非常不安全 - 连接很简单,是无状态的 - 基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等) - 使用80端口通讯 |
- 🔐安全性:HTTPS > HTTP |
HTTP 明文传输,数据都是未加密的,安全性较差HTTPS(SSL+HTTP) 数据传输过程是加密的,安全性较好
- 响应速度:HTTP > HTTPS
HTTP 使用 TCP 三次握手建立连接,客户端和服务器需要交换 3 个包
而 HTTPS除了 TCP 的三个包,还要加上 ssl 握手需要的 9 个包,所以一共是 12 个包
- 连接方式 HTTP80 HTTPS443
- 传输大小 HTTPS > HTTP
HTTPS 其实就是建构在 SSL/TLS 之上的 HTTP 协议,所以,要比较 HTTPS 比 HTTP 要更耗费服务器资源 | | HTTPS超文本传输安全协议
Hypertext Transfer Protocol Secure
常称为
HTTP over TLS
HTTP over SSL
HTTP Secure |
- 经由超文本传输协议(HTTP)进行通信,但利用SSL/TLS来加密数据包。
- 占用443端口通讯
- 开发的主要目的,是提供对网络服务器的身份认证,保护交换数据的隐私与完整性(服务端和客户端之间的所有通讯,都是加密的)
- 这个协议由网景公司(Netscape)在1994年首次提出,随后扩展到互联网上
- 使用 HTTPS 协议需要到 CA(Certificate Authority,数字证书认证机构) 申请证书,一般免费证书较少,因而需要一定费用。证书颁发机构如:Symantec、Comodo、GoDaddy 和 GlobalSign 等
- telnet 23/tcp,smtp 25/tcp, ftp 21/tcp 控制端口 ftp-data 20/tcp数据端口
| | | | | | CA
certificate authority
电子商务认证授权机构
|
- 作为电子商务交易中收信人的第三方,复制颁发和管理数字证书,在公钥体系内检验公钥的合法性。
- CA证书,是签证机关,对于用户公钥的的认证。包括CA信息,公钥用户信息,公钥,权威机构的签字和有效期等信息。
- 数字证书,在公钥后附加了用户信息和CA的签名
| | | SSL
secure socket layer
安全套接层 |
- SSL位于传输层和应用层之间,浏览器和服务器都需要在发送前对数据进行加密
| 1)基本思路是公钥加密法。客户端先向服务器索要公钥,然后使用公钥加密数据,服务器收到密文后使用私钥解密。
2) 每一次会话,客户端和服务器都生成一个”session key”对话密钥(对称加密),服务器公钥只用来加密对话密钥本身 | | TLS
transport layer security
传输层安全 |
- TLS的目标是使SSL更安全,增强了加密方面的功能,用于两个应用程序之间提供保密性和数据完整性
| |
TCP 三次握手
SYN:同步序列编号(Synchronize Sequence Numbers),TCP/IP建立连接时使用的握手信号
seq:序号,通过 TCP 传送的字节流中的每个字节都按顺序编号,而报头中的序号字段值则指的是本报文段数据的第一个字节的序号占4字节序号范围[0,2^32-1],序号增加到 2^32-1 后,下个序号又回到 0
ack:确认号,期望收到对方下个报文段的第一个数据字节的序号占4字节
HTTPS 工作原理
HTTPS在传输数据之前需要客户端(浏览器)与服务端(网站)之间进行一次握手,在握手过程中将确立双方加密传输数据的密码信息。TLS/SSL协议不仅仅是一套加密传输的协议,更是一件经过艺术家精心设计的艺术品,TLS/SSL中使用了非对称加密,对称加密以及HASH算法。握手过程的具体描述如下
- 浏览器将自己支持的一套加密规则发送给网站。
- 网站从中选出一组加密算法与HASH算法,并将自己的身份信息以证书的形式发回给浏览器。证书里面包含了
- 网站地址
- 加密公钥
- 以及证书的颁发机构等信息。
- 浏览器获得网站证书之后浏览器要做以下工作:
- 验证证书的合法性(颁发证书的机构是否合法,证书中包含的网站地址是否与正在访问的地址一致等),如果证书受信任,则浏览器栏里面会显示一个小锁头,否则会给出证书不受信的提示。
- 如果证书受信任,或者是用户接受了不受信的证书,浏览器会生成一串随机数的密码,并用证书中提供的公钥加密。
- 使用约定好的HASH算法计算握手消息,并使用生成的随机数对消息进行加密,最后将之前生成的所有信息发送给网站。
-
网站接收浏览器发来的数据之后要做以下的操作:
- 使用自己的私钥将信息解密取出密码,使用密码解密浏览器发来的握手消息,并验证HASH是否与浏览器发来的一致。
- 使用密码加密一段握手消息,发送给浏览器。
- 浏览器解密并计算握手消息的HASH,如果与服务端发来的HASH一致,此时握手过程结束,之后所有的通信数据将由之前浏览器生成的随机密码并利用对称加密算法进行加密
这里浏览器与网站互相发送加密的握手消息并验证,目的是为了保证双方都获得了一致的密码,并且可以正常的加密解密数据,为后续真正数据的传输做一次测试。另外,HTTPS一般使用的加密与HASH算法如下
算法类型 | |
---|---|
对称加密算法 | AES,RC4,3DES |
非对称加密算法 | RSA,DSA/DSS |
HASH算法 | MD5,SHA1,SHA256 |
SSL 证书
从前面我们可以了解到HTTPS核心的一个部分是数据传输之前的握手,握手过程中确定了数据加密的密码。在握手过程中,网站会向浏览器发送SSL证书,SSL证书和我们日常用的身份证类似,是一个支持HTTPS网站的身份证明,SSL证书里面包含了
- 网站的域名
- 证书有效期
- 证书的颁发机构以
- 及用于加密传输密码的公钥等信息
由于公钥加密的密码只能被在申请证书时生成的私钥解密,因此浏览器在生成密码之前需要先核对当前访问的域名与证书上绑定的域名是否一致,同时还要对证书的颁发机构进行验证,如果验证失败浏览器会给出证书错误的提示。在这一部分我将对SSL证书的验证过程以及个人用户在访问HTTPS网站时,对SSL证书的使用需要注意哪些安全方面的问题进行描述
证书的类型
实际上,我们使用的证书分很多种类型,SSL证书只是其中的一种。证书的格式是由X.509标准定义。SSL证书负责传输公钥,是一种PKI(Public Key Infrastructure,公钥基础结构)证书。 我们常见的证书根据用途不同大致有以下几种:
- SSL证书,用于加密HTTP协议,也就是HTTPS。
- 代码签名证书,用于签名二进制文件,比如Windows内核驱动,Firefox插件,Java代码签名等等。
- 客户端证书,用于加密邮件。
- 双因素证书,网银专业版使用的USB Key里面用的就是这种类型的证书。
这些证书都是由受认证的证书颁发机构——我们称之为CA(Certificate Authority)机构来颁发,针对企业与个人的不同,可申请的证书的类型也不同,价格也不同。CA机构颁发的证书都是受信任的证书,对于SSL证书来说,如果访问的网站与证书绑定的网站一致就可以通过浏览器的验证而不会提示错误。
HTTPS对应的通信时序图如下
SSL证书申请与规则
SSL证书可以向CA机构通过付费的方式申请,也可以自己制作。
CA机构颁发的证书价格非常昂贵,而且有效期一般只有一年到三年不等(年数不同,价格也不同),过期之后还要再次交钱申请,因此一般只有企业才会申请证书。但是随着个人网站的增多,目前也有针对个人的SSL证书服务,价格相对便宜一些,国内的话400多块钱就能申请到一个,国外更是有免费的SSL证书可以申请。
在申请SSL证书时需要向CA机构提供网站域名,营业执照,以及申请人的身份信息等。网站的域名非常重要,申请人必须证明自己对域名有所有权,如果支持Hotmail.com,Gmail.com的SSL证书都可以随便申请,黑客们就不用做假证书欺骗了。
此外,一个证书一般只绑定一个域名,如果CA机构心情好的话,会免费再绑一个,比如你要申请域名时绑定的域名是 www.runoob.com,那么只有在浏览器地址是 https://www.runoob.com 的时候,这个证书才是受信任的,如果地址是https://tt.runoob.com或者https://login.runoob.com,那么这个证书由于访问的域名与证书绑定的域名不同,仍然会被浏览器显示为不受信任的。
CA机构也提供申请通配符域名(例如,*.runoob.com),通配符域名相当于绑定了主域名下的所有域名,因此使用起来非常方便,但是价格也超级昂贵,一个通配符域名一年大概得5000块钱,只有企业才可以申请。
下面就来看看一个证书的信息:
在访问hotmail的时候会跳转到login.live.com,这时IE浏览器上会有一个小锁头,点一下那个小锁头再点击里面的”查看证书”就会出现上图的证书窗口,这里面我们可以看到这个证书只有一个用途——向远程计算机证明身份信息,证书的用途会有很多,SSL只是其中之一。在”颁发给”这一项就是这个证书在申请时绑定的域名;下面的”颁发者”是证书的颁发机构。最下面的两个日期是证书申请时间以及过期的时间。这里我们可以注意一下”颁发者”的信息,里面有”Extended Validation SSL”的字样,表明了这个证书是一个EV SSL证书(扩展验证SSL证书),EV SSL证书有个特点就是可以让浏览器的地址栏变绿,同时显示出来证书所属公司的名称,如下图所示:
EV SSL证书与其他的证书相比,费用更高。
以上说的是向CA机构申请证书的情况,如果个人网站只为加密传输也可以自己制作SSL证书,自己制作的证书不会受到浏览器的信任,在访问的时候由于证书验证失败而给出警告。
证书的验证过程
证书以证书链的形式组织,在颁发证书的时候首先要有根CA机构颁发的根证书,再由根CA机构颁发一个中级CA机构的证书,最后由中级CA机构颁发具体的SSL证书。我们可以这样理解,根CA机构就是一个公司,根证书就是他的身份凭证,每个公司由不同的部门来颁发不同用途的证书,这些不同的部门就是中级CA机构,这些中级CA机构使用中级证书作为自己的身份凭证,其中有一个部门是专门颁发SSL证书,当把根证书,中级证书,以及最后申请的SSL证书连在一起就形成了证书链,也称为证书路径。在验证证书的时候,浏览器会调用系统的证书管理器接口对证书路径中的所有证书一级一级的进行验证,只有路径中所有的证书都是受信的,整个验证的结果才是受信。我们还是以login.live.com这个证书举例,在查看证书的时候,点击”证书路径”标签就会有下图的显示:
根证书是最关键的一个证书,如果根证书不受信任,它下面颁发的所有证书都不受信任。操作系统在安装过程中会默认安装一些受信任的CA机构的根证书,可以在”运行”里面运行”certmgr.msc”启动证书管理器,如下图所示:
根证书的有效期长,支持的用途多以方便颁发不同用途类型的中级证书;中级证书用途单一,有效期相对短一些,但是比具体的SSL证书要长很多。
如果SSL证书验证失败根据浏览器的不同会有以下的错误提示:
SSL证书验证失败有以下三点原因:
- 1、SSL证书不是由受信任的CA机构颁发的
- 2、证书过期
- 3、访问的网站域名与证书绑定的域名不一致
这三点原因也是IE浏览器给出的提示。
小提示:如果你对哪个根证书CA机构比较憎恨,可以将它的根证书删除,这样所有它颁发的证书都不会受信任。
SSL证书的安全问题
对HTTPS最常见的攻击手段就是SSL证书欺骗或者叫SSL劫持,是一种典型的中间人攻击。不过SSL劫持并非只是用于攻击目的,在一些特殊情况下利用SSL劫持我们可以更顺畅的访问网络,我会在后文提到。
以攻击为目的的SSL劫持如果不注意浏览器安全提示的话,很容易就中招。当网络中有中间人发起SSL劫持攻击时,攻击者需要伪造一个SSL证书发给浏览器,这个时候由于伪造的SSL证书不受信任,浏览器会给出提示。
这里有一个误区,当SSL证书不受信任的时候,并不一定就是有SSL劫持发生,有种例外情况是:一些个人网站买不起合法的SSL证书,因此会自己制作一个SSL证书来加密传输的数据。如果你经常访问某个个人网站,而且你知道这个网站是干什么的,那么这种情况可以不用担心。但是如果你访问的是网银,在线支付,或者是hotmail.com,gmail.com等,这类公司性质的网站一定会申请合法的SSL证书(12306.cn除外),一旦SSL证书不受信任,应该果断的终止访问,这个时候网络中一定会存在异常行为,对于一些小区宽带的用户一定要注意这点。
所以作为个人用户,你一定要知道你访问的是什么网站,如果你只是一个没有多少计算机只是的普通网民,我相信你不会经常上那些自己制作SSL证书的个人网站(12306.cn除外),因此如果你没有办法判断网络是不是有异常,只要是证书有问题的,干脆就别再访问了。
小提示:对于12306.cn,一定要按照网站说的那样,”为保障您顺畅购票,请下载安装根证书”。 最后我们总结一下使用SSL证书要注意的问题:
- 除非必要,不要随意安装根证书。安装根证书的时候一定要明确证书的来源。
- 对于网银,在线支付,重要邮箱等网站,一定要确保SSL证书是没有问题的,如果浏览器给出SSL证书错误的警告,一定要拒绝访问。一些小区宽带用户一定要注意这点。
- 由于现在个人申请SSL证书比较便宜,一定要注意挂着合法SSL证书的钓鱼网站(国外比较常见)。对于钓鱼网站,一定要看清域名,另外别相信什么中奖的消息,同时要安装带有钓鱼防护功能的安全软件。
总结
值得注意的是,HttpClient提供的这些属性和方法最终都会作用在请求header里,我们完全可以通过手动去设置header来实现,之所以提供这些方法,只是为了方便开发者而已。另外,Http协议是一个非常重要的、使用最多的网络协议,每一个开发者都应该对http协议非常熟悉。