本文已参与「新人创作礼」活动,一起开启掘金创作之路。
SSL安全证书
SSL证书是数字证书的一种,因为配置在服务器上,也称为SSL服务器证书。 SSL证书就是遵守 SSL协议,由受信任的数字证书颁发机构CA,在验证服务器身份后颁发,具有服务器身份验证和数据传输加密功能。 SSL证书通过在客户端浏览器和Web服务器之间建立一条SSL安全通道(Secure socket layer(SSL)安全协议是由Netscape Communication公司设计开发。该安全协议主要用来提供对用户和服务器的认证;对传送的数据进行加密和隐藏;确保数据在传送中不被改变,即数据的完整性,
SSL证书分为如下种类:
- 扩展验证型(EV)SSL证书
- 组织验证型(OV)SSL证书
- 域名验证型(DV)SSL证书
网站使用ssl证书的好处
- 传输加密(防止数据被窃取)
- 防止钓鱼网站
- 防止网站被劫持(被插入一些广告信息)
- 提高SEO排名
获取证书的几种方式
1.自己签发
使用openssl给自己签发证书(自签CA)
1. openssl genrsa -out server.key 2048 #创建私钥
2. openssl req -new -key server.key -out server.csr #构造证书请求文件
3. openssl x509 -req -in server.csr -out server.crt -signkey server.key -days 3650 #自签证书
4. openssl x509 -in server.crt -out server.pem -outform PEM #生成pem格式的证书
#自签名的证书可以作为自己的CA(根)证书再签名二级证书
#ca.crt就是自签的ca证书,ca.key同上
openssl ca -in server.csr -out server.crt -cert ca.crt -keyfile ca.key
#格式化创建CA的命令行
#CABase 作为CA的根目录
#CAType CA类型可以填RSA/RSA2SM2
#Orgnize 组织信息
#Name 授权名称
str := fmt.Sprintf("openssl req -new -x509 -days 3650 -extensions v3_ca -key %v/.%v.ca.key -subj=\"/C=CN/ST=shanghai/L=shanghai/O=%v/CN=%v\" -out %v/.%v.ca.crt ",CABase, CAType, Orgnize, Name, CABase, CAType)
#格式化证书请求文件命令行
#keypath 私钥路径
#Subject 证书请求主体:fmt.Sprintf("/C=CN/ST=shanghai/L=shanghai/O=%v/CN=%v",Orgnize, Name),
#csrpath 证书请求文件输出路径
str := fmt.Sprintf("openssl req -nodes -new -key %v -subj \"%v\" -out %v ", keypath,Subject, csrpath)
#格式化签发证书的命令行
#Days 证书有效期(天)
#csrpath 证书请求文件路径
#Serial 证书流水号
#crtpath 证书输出路径
signStr := fmt.Sprintf("openssl x509 -req -sha256 -extensions v3_req -days %v -in %v -CA %v/.%v.ca.crt -CAkey %v/.%v.ca.key -set_serial %v -out %v ", Days, csrpath,CABase,KeyType,CABase,Name,Serial, crtpath)
2.找云服务商买域名签发证书
阿里云和腾讯云等服务商有提供证书业务,可以购买证书或者使用免费的DV证书
3.LetsEncrypt免费的CA签发服务
git clone https://github.com/letsencrypt/letsencrypt
cd letsencrypt
./certbot-auto certonly -d *.你的域名 --manual --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory
#使用crontab自动续期
crontab -e #编辑定时任务
0 */12 * * * certbot renew --quiet --renew-hook "/etc/init.d/nginx reload"
证书双向认证
1. 服务端配置(Nginx)
server {
...
ssl on;
ssl_certificate /data/sslKey/server-cert.cer; #server证书公钥
ssl_certificate_key /data/sslKey/server-key.key; #server私钥
#双向认证的核心配置,配置客户端证书CA和开启客户端证书认证
ssl_client_certificate /data/sslKey/root-cert.cer; #根级证书公钥,用于验证各个二级client
ssl_verify_client on; #开启客户端证书验证
...
}
2.客户端配置(Java)
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import javax.net.ssl.SSLContext;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
public class HttpsDemo {
private final static String PFX_PATH = "client.p12"; //客户端证书路径
private final static String PFX_PWD = "****"; //客户端证书密码
public static String sslRequestGet(String url) throws Exception {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
InputStream instream = new FileInputStream(new File(PFX_PATH));
try {
keyStore.load(instream, PFX_PWD.toCharArray());
} finally {
instream.close();
}
SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, PFX_PWD.toCharArray()).build();
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext
, new String[] { "TLSv1" } // supportedProtocols ,这里可以按需要设置
, null // supportedCipherSuites
, SSLConnectionSocketFactory.getDefaultHostnameVerifier());
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
try {
HttpGet httpget = new HttpGet(url);
// httpost.addHeader("Connection", "keep-alive");// 设置一些heander等
CloseableHttpResponse response = httpclient.execute(httpget);
try {
HttpEntity entity = response.getEntity();
String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");//返回结果
EntityUtils.consume(entity);
return jsonStr;
} finally {
response.close();
}
} finally {
httpclient.close();
}
}
public static void main(String[] args) throws Exception {
System.out.println(sslRequestGet("https://www.test.com/"));
}
}
3.curl命令行带证书和私钥访问
curl -k --cert client.pem --key key.pem https://www.xxxx.com