使用Nginx代理restful实现SSL链路加密
时间:2022-04-27
本文章向大家介绍使用Nginx代理restful实现SSL链路加密,主要内容包括1 目标说明、1.2 目标网络模型、1.3 SSL说明、2 调研过程、2.2 测试https 加密restful、3 总结、基本概念、基础应用、原理机制和需要注意的事项等,并结合实例形式分析了其使用技巧,希望通过本文能帮助到大家理解应用这部分内容。
1 目标说明
1.1 调研目的
本次调研主要为了解决两个问题:
- 不需要对restful的web容器做任何配置,实现对restful链路进行加密;
- 方便restful应用进行扩展,采用多个服务进行负载均衡,以提升吞吐量。
1.2 目标网络模型
希望达到的目标网络模型如下:
1.3 SSL说明
通过对SSL的学习,结合自身业务的考虑,对SSL的使用做如下说明:
我这里SSL使用TLSv1,并且服务端不需要校验客户端的身份合法性,则使用SSL单向认证方式,只需要服务端证书。另外我们只需要用到SSL的链路加密,所以可以设置客户端对服务端证书保持永久信任
2 调研过程
这里restful使用jersey来实现,使用jetty作为javaee容器。
2.1 测试非加密restful
通过jetty发布非加密restful服务,url为 http://localhost:8080/api/v1/....
2.1.1 服务端代码
web.xml
<servlet>
<servlet-name>RestApplication</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>com.spiro.test.jersey.MyApplication</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>RestApplication</servlet-name>
<url-pattern>/api/v1/*</url-pattern>
</servlet-mapping>
Resource:
import com.spiro.test.jersey.entity.Terminal;
import javax.inject.Singleton;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.List;
@Path("terminals")
@Singleton
public class TerminalsResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getAll() {
List<Terminal> terminals = new ArrayList<Terminal>();
Terminal ter1 = new Terminal();
ter1.setId("101");
ter1.setDesc("I'm 101");
terminals.add(ter1);
Terminal ter2 = new Terminal();
ter2.setId("102");
ter2.setDesc("I'm 102");
terminals.add(ter2);
// if(true) {
// return Response.status(Response.Status.UNAUTHORIZED).build();
// }
return Response.ok(terminals).build();
}
}
ResourceConfig:
import com.spiro.test.jersey.resources.TerminalsResource;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.server.ResourceConfig;
public class MyApplication extends ResourceConfig {
public MyApplication() {
register(TerminalsResource.class);
register(JacksonFeature.class);
}
}
2.1.2 客户端代码
public static void testHttp() {
ClientConfig clientConfig = new ClientConfig();
Client client = ClientBuilder.newClient(clientConfig);
String url = "http://localhost:8080/api/v1/";
String entity = client.target(url)
.path("terminals")
.request(MediaType.APPLICATION_JSON)
.get(String.class);
System.out.println(entity);
}
经测试成功打印:[{"id":"101","desc":"I'm 101"},{"id":"102","desc":"I'm 102"}]
2.2 测试https 加密restful
2.2.1 nginx安装配置
在windows7机器上安装nginx-1.10.1,配置如下:
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
server {
listen 443 ssl;
server_name localhost;
ssl_certificate D:/server.crt;
ssl_certificate_key D:/_server.key;
location / {
proxy_pass http://127.0.0.1:8080;
}
}
}
2.2.2 服务端代码
同2.1.1
2.2.3 客户端代码
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}
};
// Install the all-trusting trust manager
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
// Create all-trusting host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
Client client = ClientBuilder.newBuilder().sslContext(sslContext).build();
String entity = client.target("https://127.0.0.1:443/api/v1/")
.path("terminals")
.request(MediaType.APPLICATION_JSON)
.get(String.class);
System.out.println(entity);
设置客户端请求连接为ssl加密,并且客户端永久信任服务端,不对服务端证书进行验证。
经测试成功打印:[{"id":"101","desc":"I'm 101"},{"id":"102","desc":"I'm 102"}]
3 总结
经测试,可以通过nginx https代理restful 实现链路加密,后续可通过nginx upstream实现负载均衡。
- 《小美好》短评文本情感分析+生成词云
- 通过shell定制dbms_advisor.quick_tune(r4笔记第15天)
- 跨浏览器tab页的通信解决方案尝试
- 深度学习的GPU:深度学习中使用GPU的经验和建议
- socket.io搭配pm2(cluster)集群解决方案
- 用 Python 来刷微信「跳一跳」游戏的记录
- Spring+SpringMVC+MyBatis+easyUI整合优化篇(十二)数据层优化-explain关键字及慢sql优化
- 高吞吐koa日志中间件
- 关于SQLRecoverableException问题的排查和分析(r4笔记第13天)
- Spring+SpringMVC+MyBatis+easyUI整合优化篇(十三)数据层优化-表规范、索引优化
- node中的Stream-Readable和Writeable解读
- Spring+SpringMVC+MyBatis+easyUI整合进阶篇(六)一定要RESTful吗?
- 深入node之Transform
- 巧用shell脚本统计磁盘使用情况(r4笔记第12天)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 浙大版《C语言程序设计(第3版)》题目集 习题8-5 使用函数实现字符串部分复制
- 最小生成树-Magicpig密室出逃(Kruskal+并查集)
- 浙大版《C语言程序设计(第3版)》题目集 习题8-6 删除字符
- SQL-显示供应商供应零件的汇总列表(with rollup+coalesce)
- 浙大版《C语言程序设计(第3版)》题目集 习题8-8 判断回文字符串
- 双向广搜-HDU1401 Solitaire
- TCP三次握手和四次挥手以及11种状态
- 浙大版《C语言程序设计(第3版)》题目集 题8-9 分类统计各类字符个数
- 迭代加深搜索-POJ 3134 Power Calculus
- 浙大版《C语言程序设计(第3版)》题目集 习题9-2 计算两个复数之积
- 浙大版《C语言程序设计(第3版)》题目集 习题9-6 按等级统计学生成绩
- 实战|用pandas+PyQt5制作一款数据分组透视处理工具
- 带权/种类并查集-POJ 1182食物链
- 浙大版《C语言程序设计(第3版)》题目集 练习10-1 使用递归函数计算1到n之和
- 十分钟快速了解Pandas的常用操作!