专栏首页IT杂记使用Nginx代理restful实现SSL链路加密

使用Nginx代理restful实现SSL链路加密

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实现负载均衡。

完整代码请查看

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 关于MySQL DNS解析探究之一:DNS解析确实在起作用

    机器A --> 192.168.103.94  -- 服务器 机器B --> 192.168.4.2        -- 客户端 机器A => 装上mysql-...

    囚兔
  • JVM垃圾收集调优案例-xwiki吞吐量调优

    简介 通过压力测试查看xwiki的gc情况,统计分析gc日志,在不改变总内存使用的情况下做出合理调整,通过压力测试聚合报告对比调优效果。 步骤 运行程序,增加打...

    囚兔
  • Websocket HandShake Sec-WebSocket-Accept 生成策略

    先阅读http://tools.ietf.org/html/rfc6455 规范,然后实践。 思路如下:     服务端先获得请求头部的Sec-WebSock...

    囚兔
  • SpringMVC类图关系

    package org.springframework.web.servlet {

    zhangheng
  • Glide4.8版本中,Glide是如何加载网络美女图片

    目前市场上主流的图片加载框架就是glide和fresco,个人觉得深入学习一款就可以,glide就是我的选择,在maven上可以看到Glide项目已经到4.11...

    包子388321
  • [第22期] React Conf 2019 样式新方案

    会上讲了很多激动人心的技术点,这里先介绍一些我比较感兴趣的点, 希望对大家有所启发。

    用户6900878
  • JDK动态代理详解

    本文主要介绍JDK动态代理的基本原理,让大家更深刻的理解JDK Proxy,知其然知其所以然。明白JDK动态代理真正的原理及其生成的过程,我们以后写JDK Pr...

    java架构师
  • Python MRO

    对于Python中的多继承情况,运行时在搜索对象的属性或方法时,需要遵循一定的顺序规则,这个规则称为:Method Resolution Order (MRO)...

    雪飞鸿
  • CSS Modules使用详解

    通过 JS 来管理 CSS 就很好解决上述列举的问题。CSS 模块化的解决方案有很多,但主要有两类。

    IMWeb前端团队
  • CSS Modules使用详解

    CSS Modules CSS 模块化 不管是用jquery还是react开发,都会遇到的一系列 CSS 的问题: 全局污染 命名混乱 依赖引入复杂 无法共享变...

    IMWeb前端团队

扫码关注云+社区

领取腾讯云代金券