创建示例HTTPS服务器以获取乐趣和收益

通常,在开发人员或/和针对实际场景进行测试期间,我们(开发人员)面临着运行成熟的HTTPS服务器的需求,可能同时进行一些模拟。 在JVM平台上,除非您知道适合此工作的正确工具,否则它过去并不是一件容易的事。 在这篇文章中,我们将使用出色的Spray框架和Scala语言创建一个完全可操作的HTTPS服务器的框架。

首先,我们需要分别生成x509证书和私钥。 幸运的是,使用openssl命令行工具非常容易。

openssl req -x509 -sha256 -newkey rsa:2048 -keyout certificate.key -out certificate.crt -days 1024 -nodes

在JVM平台上,我们的基本目标是拥有Java密钥库 ( JKS ),这是安全证书的存储库。 但是,要将我们新生成的证书导入JKS ,我们必须以PKCS#12格式导出它,然后从中创建密钥库。 同样,在resque上使用openssl

openssl pkcs12 -export -in certificate.crt -inkey certificate.key -out server.p12 -name sample-https-server -password pass:change-me-please

请注意,存档服务器.p12受密码保护。 现在,最后一步涉及JDK发行版中的命令行工具keytool 。

keytool -importkeystore -srcstorepass change-me-please -destkeystore sample-https-server.jks -deststorepass change-me-please -srckeystore server.p12 -srcstoretype PKCS12 -alias sample-https-server

结果是受密码保护的sample-https-server.jks密钥库,我们可以在HTTPS服务器应用程序中使用它来配置SSL上下文。 Spray有非常好的文档和大量示例,其中一个示例SslConfiguration ,我们可以用来配置KeyManagerTrustManagerSSLContext

trait SslConfiguration {// If there is no SSLContext in scope implicitly, the default SSLContext is // going to be used. But we want non-default settings so we are making // custom SSLContext available here.implicit def sslContext: SSLContext = {val keyStoreResource = "/sample-https-server.jks"val password = "change-me-please"val keyStore = KeyStore.getInstance("jks")keyStore.load(getClass.getResourceAsStream(keyStoreResource), password.toCharArray)val keyManagerFactory = KeyManagerFactory.getInstance("SunX509")keyManagerFactory.init(keyStore, password.toCharArray)val trustManagerFactory = TrustManagerFactory.getInstance("SunX509")trustManagerFactory.init(keyStore)val context = SSLContext.getInstance("TLS")context.init(keyManagerFactory.getKeyManagers, trustManagerFactory.getTrustManagers, new SecureRandom)context}// If there is no ServerSSLEngineProvider in scope implicitly, // the default one is going to be used. But we would like to configure// cipher suites and protocols  so we are making a custom ServerSSLEngineProvider// available here.implicit def sslEngineProvider: ServerSSLEngineProvider = {ServerSSLEngineProvider { engine =>engine.setEnabledCipherSuites(Array("TLS_RSA_WITH_AES_128_CBC_SHA"))engine.setEnabledProtocols(Array( "TLSv1", "TLSv1.1", "TLSv1.2" ))engine}}
}

这里有几点要强调。 首先,使用先前创建的我们自己的密钥库(为方便起见,我们将其存储为类路径资源):

val keyStoreResource = "/sample-https-server.jks"
val password = "change-me-please"

此外,我们仅配置TLSTLS v1.0TLS v1.1TLS v1.2 ),不支持SSLv3 。 除此之外,我们仅启用一种密码: TLS_RSA_WITH_AES_128_CBC_SHA 。 这样做主要是为了说明,因为在大多数情况下都可以启用所有受支持的密码。

engine.setEnabledCipherSuites(Array("TLS_RSA_WITH_AES_128_CBC_SHA"))
engine.setEnabledProtocols(Array( "TLSv1", "TLSv1.1", "TLSv1.2" ))

这样,我们就可以创建一个真正的HTTPS服务器了,这要归功于Spray框架只有几行:

class HttpsServer(val route: Route = RestService.defaultRoute) extends SslConfiguration {implicit val system = ActorSystem()implicit val timeout: Timeout = 3 seconds val settings = ServerSettings(system).copy(sslEncryption = true)val handler = system.actorOf(Props(new RestService(route)), name = "handler")def start(port: Int) = Await.ready(IO(Http) ? Http.Bind(handler, interface = "localhost", port = port, settings = Some(settings)), timeout.duration)def stop() = {IO(Http) ? Http.CloseAllsystem.stop(handler)}
}

任何根本不执行任何操作的HTTPS服务器不是很有用。 这就是路由属性发挥作用的地方:使用Spray路由扩展,我们将映射(或路由)传递给HTTP服务参与者RestService )直接处理请求。

class RestService(val route: Route) extends HttpServiceActor with ActorLogging {def receive = runRoute {route}
}

使用默认路由就是:

object RestService {val defaultRoute = path("") {get {complete {"OK!\n"}}}
}

基本上,这就是我们所需要的,我们的HTTPS服务器已准备好进行测试! 运行它的最简单方法是使用Scala应用程序。

object HttpsServer extends App {val server = new HttpsServerserver.start(10999)
}

尽管是用Scala编写的,但我们可以轻松地将其嵌入到任何Java应用程序中(对于Java开发人员来说,使用一些非标准的命名约定),例如:

public class HttpsServerRunner {public static void main(String[] args) {final HttpsServer server = new HttpsServer(RestService$.MODULE$.defaultRoute());server.start(10999);}
}

一旦启动并运行(最简单的方法是sbt run ),就可以从浏览器或使用curl命令行客户端访问我们简单的HTTPS服务器的公开默认路由( -k命令行参数关闭SSL证书验证) :

$ curl -ki https://localhost:10999HTTP/1.1 200 OK
Server: spray-can/1.3.3
Date: Sun, 04 Oct 2015 01:25:47 GMT
Content-Type: text/plain; charset=UTF-8
Content-Length: 4OK!

或者,可以将证书与curl命令一起传递,以便进行完整的SSL证书验证,例如:

$  curl -i --cacert src/main/resources/certificate.crt  https://localhost:10999HTTP/1.1 200 OK
Server: spray-can/1.3.3
Date: Sun, 04 Oct 2015 01:28:05 GMT
Content-Type: text/plain; charset=UTF-8
Content-Length: 4OK!

一切看起来不错,但是我们可以使用HTTPS服务器作为集成测试套件的一部分来验证/存根/模拟,例如,与第三方服务的交互吗? 答案是肯定的,这要归功于JUnit规则。 让我们看一下HttpsServerRule的最简单实现:

class HttpsServerRule(@BeanProperty val port: Int, val route: Route) extends ExternalResource {val server = new HttpsServer(route)override def before() = server.start(port)override def after() = server.stop()
}object HttpsServerRule {def apply(port: Int) = new HttpsServerRule(port, RestService.defaultRoute);def apply(port: Int, route: Route) = new HttpsServerRule(port, route);
}

我们默认实现的JUnit测试用例使用了出色的RestAssured库,该库提供了Java DSL,可轻松测试REST服务。

public class DefaultRestServiceTest {@Rule public HttpsServerRule server = HttpsServerRule$.MODULE$.apply(65200);@Testpublic void testServerIsUpAndRunning() {given().baseUri("https://localhost:" + server.getPort()).auth().certificate("/sample-https-server.jks", "change-me-please").when().get("/").then().body(containsString("OK!"));}
}

可以肯定的是,您对默认实现无法做很多事情,因此提供自定义选项是必不可少的选择。 幸运的是,我们很早就通过接受路线来解决了这一问题。

object CustomRestService {val route = path("api" / "user" / IntNumber) { id =>get {complete {"a@b.com"}}}
}

这是一个测试用例:

public class CustomRestServiceTest {@Rule public HttpsServerRule server = HttpsServerRule$.MODULE$.apply(65201, CustomRestService$.MODULE$.route());@Testpublic void testServerIsUpAndRunning() {given().baseUri("https://localhost:" + server.getPort()).auth().certificate("/sample-https-server.jks", "change-me-please").when().get("/api/user/1").then().body(containsString("a@b.com"));}
}

事实证明,创建完善的HTTPS服务器一点也不难,而且一旦您知道执行此操作的正确工具,它可能真的很有趣。 Spray框架是那些魔术工具之一。 你们中许多人都知道, Spray将被Akka HTTP取代,后者最近已经发布了1.0版本,但目前缺少许多功能(包括HTTPS支持),因此Spray是可行的选择。

  • 完整的项目可以在Github上找到 。

翻译自: https://www.javacodegeeks.com/2015/10/creating-sample-https-server-for-fun-and-profit.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/356499.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WebDriver API元素的定位

一、以下截图为用FireBug定位的用火狐(Firefox)浏览器打开的百度首页,下面所讲述的八种定位方法,就是以该截图中的百度输入框为例子。 ①、FireBug是Firefox浏览器下的开发类插件,通过该插件可以查看HTML、CSS、Javascript控制台、网络状况监…

mysql字符乱码百度_如何解决MySQL字符集乱码问题

变量 a 的字符编码是由参数 CHARACTER_SET_CLIENT 决定的,假设此时编码为 A,也就是变量 a 的编码。2. 写入语句在发送到 MySQL 服务端之前的编码由 CHARACTER_SET_CONNECTION 决定,假设此时编码为 B。3. 经过 MySQL 一系列词法,语…

[水煮 ASP.NET Web API2 方法论](1-6)Model Validation

问题 想要 ASP.NET Web API 执行模型验证,同时可以和 ASP.NET MVC 共享一些验证逻辑。 解决方案 ASP.NET Web API 与 ASP.NET MVC 支持一样的验证机制,都是通过System.ComponentModel.DataAnnoataions 的属性验证。使用框架提供的相关验证属性&#xff0…

findbugs-dea_FindBugs和JSR-305

findbugs-dea假设该组开发人员在大型项目的各个部分上并行工作-一些开发人员在进行服务实现,而其他开发人员在使用该服务的代码。 考虑到API的假设,两个小组都同意服务API,并开始单独工作。 您认为这个故事会有幸福的结局吗? 好吧…

课程2 谈论音乐行业的趋势

1. 音乐词汇 CDdownloadLPsrecordsvinyl 黑胶sounddlbum covers 专辑封面2. 使用类似单词谈论各种录制你和聆听音乐的不同媒体 I still prefer the sound of my old LP records.My father used to by a lot of CDs.Most of my music these days is MP3s.3. 你可以使用这些词来谈…

带有ActiveMQ和Maven的JMS Sender应用程序

我们已经看到了如何使用ActiveMQ和Maven创建JMS Receiver应用程序 。 让我们看看我们如何类似地创建JMS Sender应用程序 。 web.xml与创建接收器应用程序时使用的相同&#xff1a; <web-app xmlns"http://java.sun.com/xml/ns/javaee"xmlns:xsi"http://www…

mysql自连接查询的sql语句_mysql 自连接

SELECT语句中的自连接。到目前为止&#xff0c;我们连接的都是两张不同的表&#xff0c;那么能不能对一张表进行自我连接呢&#xff1f;答案是肯定的。有没有必要对一张表进行自我连接呢&#xff1f;答案也是肯定的。表的别名&#xff1a;一张表可以自我连接。进行自连接时我们…

Spring的Lifecycle

Lifecycle接口定义了每个对象的重要方法&#xff0c;每个对象都有自己的生命周期需求&#xff0c;如下&#xff1a; public interface Lifecycle { void start(); void stop(); boolean isRunning(); } 任何spring管理的对象都可以实现这个接口。那么&#xff0c;当Appl…

mysql aes密钥大于16位_aes秘钥限制问题解决办法

在oarcle jdk1.8上执行256位的aes秘钥加密报错如下:java.lang.RuntimeException: java.security.InvalidKeyException: Illegal key sizeat com.xx.opal.core.utils.aes.AESTool.encryptWithoutEncode(AESTool.java:33)at com.xx.opal.aes.AESTest.test(AESTest.java:19)at sun…

background-clip与background-origin

规定背景的绘制区域 浏览器支持 IE9、Firefox、Opera、Chrome 以及 Safari 支持 background-clip 属性。 注释&#xff1a;Internet Explorer 8 以及更早的版本不支持 background-clip 属性。IE9、Firefox、Opera、Chrome 以及 Safari 支持 background-clip 属性。 有三个值&am…

策略模式应用场景和uml_策略模式

策略模式应用场景和uml在最近的博客中&#xff0c;我收到了Wojciech Soczy&#xff1f;ski的评论&#xff0c;内容涉及在使用“不要问”&#xff08;TDA&#xff09;时如何使用“战略”模式实施单一责任原则&#xff08;SRP&#xff09;。 在某些时候&#xff0c;我打算进一步讨…

mysql建表时主键_mysql建表时怎么设置主键?

设置方法&#xff1a;在“CREATE TABLE”语句中&#xff0c;通过“PRIMARY KEY”关键字来指定主键&#xff0c;语法格式“字段名 数据类型 PRIMARY KEY [默认值]”或“[CONSTRAINT 约束名] PRIMARY KEY 字段名”。主键(PRIMARY KEY)的完整称呼是“主键约束”&#xff0c;是 MyS…

mysql的考试范围_数据库考试范围整理

填空&#xff1a;1.目前常用的数据库管理系统软件有Access 、SQL Sever和Oracle.2.数据实际上就是存储在某一种媒体上的能够被识别的物理符号。3.一个关系的逻辑结构就是一个二维表。4.对关系进行选择、投影或连接运算之后&#xff0c;运算的结果仍然是一个关系。5.在关系数据库…

Java EE 8 MVC:控制器的详细介绍

Java EE MVC是为Java EE 8规划并在JSR-371中指定的基于动作的新MVC框架。 这是我的Java EE 8 MVC教程的第二篇文章。 第一篇文章介绍了基础知识&#xff0c;并展示了如何开始使用 Java EE 8 MVC参考实现Ozark 。 在本文中&#xff0c;我们将更详细地介绍MVC控制器。 MVC控制器…

mysql htmlspecialchars_htmlSpecialchars和MySQL_REARY_EXECH_String是否保证PHP代码

当涉及到数据库查询时&#xff0c;始终尝试并使用准备好的参数化查询。这个mysqli和PDO图书馆支持这一点。这比使用转义函数(如mysql_real_escape_string.是,mysql_real_escape_string实际上只是一个字符串转义函数。这不是一颗神奇的子弹。它所要做的就是转义危险字符&#xf…

前端跨域问题的几种解决方案

前端跨域问题 一&#xff1a;同源策略   1.whats this     所谓同源是指&#xff0c;域名&#xff0c;协议&#xff0c;端口相同。当浏览器运行一个JS脚本时会进行同源检测&#xff0c;如果不同源是不能执行的。   2.源继承     来自about:blank&#xff0c;javasc…

在OpenShift上部署Java EE微服务

我昨天用WildFly Swarm在博客上发布了有关简单JAX-RS微服务的博客。 您学习了如何使用Maven构建一个所谓的“胖子”&#xff0c;还使用Maven Docker插件对我们的微服务进行了Docker化并在Docker Machine上本地运行。 这是在本地测试事物的好方法。 到目前为止&#xff0c;缺少的…

rocketmq 订阅组_必须先理解的RocketMQ入门手册,才能再次深入解读

推荐阅读一下下2020年后想跳槽&#xff1f;MQ、ZK、Nginx、Kafk等分布式技术你都掌握了&#xff1f;阿里架构师推荐学习的《RabbitMQ实战指南》&#xff0c;渣渣的你都看过吗&#xff1f;RocketMQ入门手册RocketMQ是一个分布式、队列模型的开源消息中间件&#xff0c;前身是Met…

关于返回按钮的事情

在微信的项目涉及到多个不同的项目间跳转那么头部的返回按钮怎么办呢&#xff1f; 在项目之间跳转还有在微信菜单进入页面时我们用了一个中转页进行参数处理和页面跳转判断 目前要用到code&#xff0c;userId等从后端写好的带参数的url到前端获取然后去调用后端的一个校验code和…

.net数据源控件绑定mysql_理解asp.net中DropDownList编辑数据源,绑定数据库数据。...

一、理解asp.net绑定数据库终于学习到了连接数据库部分的内容&#xff0c;杨中科老师视频看起来挺轻松的&#xff0c;如果是高清版就更ok了。我发现我学习新的编程语言会有一个特点&#xff0c;都想要赶紧学习数据库&#xff0c;数据就是一切&#xff0c;有了数据才能操作一切的…