nginx配置https私有证书访问
剧情需要,测试一下Java代码访问https,遂需要创建一个https的环境
平台:Windows 10
步骤:分为两个大步骤,即:证书生成
、nginx配置
、json-server关联
、java实现通过证书访问接口
证书生成
- 创建
myAwesomeCA.cnf
文件,并赋予如下内容
[ req ]
distinguished_name = req_distinguished_name
x509_extensions = root_ca
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
localityName = Locality Name (eg, city)
0.organizationName = Organization Name (eg, company)
organizationalUnitName = Organizational Unit Name (eg, section)
commonName = Common Name (eg, fully qualified host name)
commonName_max = 64
emailAddress = Email Address
emailAddress_max = 64
[ root_ca ]
basicConstraints = critical, CA:true
- 创建
myAwesomeServer.ext
文件,并赋予如下内容
subjectAltName = @alt_names
extendedKeyUsage = serverAuth
[alt_names]
IP.1 = 192.168.101.150
IP.2 = 192.168.100.150
生成的文件结构如下
- 生成
myAwesomeCA.cer
和myAwesomeCA.pvk
,在终端执行如下命令
openssl req -x509 -newkey rsa:2048 -out myAwesomeCA.cer -outform PEM -keyout myAwesomeCA.pvk -days 10000 -verbose -config myAwesomeCA.cnf -nodes -sha256 -subj "/CN=MyCompany CA"
# 注:openssl是MSYS2中的可执行文件
生成的文件结构如下
- 生成
myAwesomeServer.req
,在终端执行如下命令
openssl req -newkey rsa:2048 -keyout myAwesomeServer.pvk -out myAwesomeServer.req -subj /CN=localhost -sha256 -nodes
生成的文件结构如下
- 生成
myAwesomeServer.cer
,在终端执行如下命令
openssl x509 -req -CA myAwesomeCA.cer -CAkey myAwesomeCA.pvk -in myAwesomeServer.req -out myAwesomeServer.cer -days 10000 -extfile myAwesomeServer.ext -sha256 -set_serial 0x1111
nginx配置
下载nginx-1.20.1.zip并解压
在命令行执行
nginx.exe
浏览器访问http://localhost(或者http://你的ip)
如果你现在输入https://localhost,你断然不能访问哟
现在我们要做的事情就是要支持https://localhost访问
- 进入conf文件夹,并将
myAwesomeServer.cer
以及myAwesomeServer.pvk
拷贝到该目录下
- 编辑一下conf目录下的nginx.conf文件
- 将nginx.conf做如下内容更改
- 关掉之前执行nginx.exe的窗口,再新开窗口,执行nginx.exe
此刻你能正确访问该地址,点击高级
点击继续访问
此刻便正确得到了访问内容
json-server关联
- 自行安装并启动json-server,然后接口访问
- 修改nginx的nginx.conf文件
- 执行
nginx -s reload
命令后访问http://localhost/posts
- 现在对https做相同的操作,修改nginx的nginx.conf文件
- 执行
nginx -s reload
命令后访问http://localhost/posts
正确访问,总体来讲,就是我们访问http://localhost以及https://localhost时,都指向了http://localhost:3000端口的json-server内容
java实现通过证书访问接口
- 新建一个Kotlin工程,再build.gradle添加okhttp依赖
implementation 'com.squareup.okhttp3:okhttp:3.8.0'
- 编写代码
fun main(args: Array<String>) {
val okClient = OkHttpClient.Builder()
.build()
val request = Request.Builder()
.url("http://localhost/posts")
.build()
return try {
val execute = okClient.newCall(request).execute()
val bodyString = execute.body()?.string()
println("body:\n$bodyString")
} catch (e: IOException) {
println("body:\n" + e.message)
}
}
并执行,得到如下结果
body:
[
{
"id": 1,
"title": "json-server",
"author": "typicode"
},
{
"token": "861bc663-eaea-4bf3-9e93-6c3a818b6929",
"userId": "107",
"id": 2
}
]
我们将http改为https的话
再次执行得到如下结果
body:
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
是的,这就是没有证书的表现,现在我们添加私有证书,还记得前面我们生成的myAwesomeCA.cer
吗,我们将会用到它
修改之前的kotlin代码
具体代码如下
fun main(args: Array<String>) {
val sslContext: SSLContext
val trustManagers: Array<TrustManager>
try {
val keyStore = KeyStore.getInstance(KeyStore.getDefaultType())
keyStore.load(null, null)
val certInputStream: InputStream = FileInputStream(File("C:\\Users\\Watson\\Downloads\\https\\myAwesomeCA.cer"))
val bis = BufferedInputStream(certInputStream)
val certificateFactory = CertificateFactory.getInstance("X.509")
while (bis.available() > 0) {
val cert = certificateFactory.generateCertificate(bis)
keyStore.setCertificateEntry("anchor", cert)
}
val trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm())
trustManagerFactory.init(keyStore)
trustManagers = trustManagerFactory.trustManagers
sslContext = SSLContext.getInstance("TLS")
sslContext.init(null, trustManagers, null)
} catch (e: Exception) {
e.printStackTrace()
return
}
val okClient = OkHttpClient.Builder()
.sslSocketFactory(sslContext.socketFactory, trustManagers[0] as X509TrustManager)
.build()
val request = Request.Builder()
.url("https://localhost/posts")
.build()
return try {
val execute = okClient.newCall(request).execute()
val bodyString = execute.body()?.string()
println("body:\n$bodyString")
} catch (e: IOException) {
println("body:\n" + e.message)
}
}
再次执行得到如下结果
body:
[
{
"id": 1,
"title": "json-server",
"author": "typicode"
},
{
"token": "861bc663-eaea-4bf3-9e93-6c3a818b6929",
"userId": "107",
"id": 2
}
]
OK,完美收官!