Jersey框架三:Jersey对HTTPS的支持
Jersey系列文章:
Jersey框架一:Jersey RESTful WebService框架简介
证书的生成过程这里就不介绍了,请参照:Java网络编程二:Java Secure(SSL/TLS) Socket实现中的证书部分
代码结构如下:
Maven配置文件:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>JERSEY</groupId>
<artifactId>JERSEY</artifactId>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-client</artifactId>
<version>1.18</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-grizzly2</artifactId>
<version>1.18</version>
</dependency>
<dependency>
<groupId>com.sun.jersey</groupId>
<artifactId>jersey-json</artifactId>
<version>1.18</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.15</version>
</dependency>
</dependencies>
</project>
Person类是基本的JAXB:
package com.sean; import java.util.List; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement
public class Person {
private String name;
private List<String> addresses; public Person(){} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public List<String> getAddresses() {
return addresses;
} public void setAddresses(List<String> addresses) {
this.addresses = addresses;
}
}
客户端代码:
package com.sean; import java.net.URI; import javax.net.ssl.SSLContext;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder; import org.glassfish.jersey.SslConfigurator; import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.client.urlconnection.HTTPSProperties; public class SSLClient {
public static void main(String[] args) {
int authType =
Integer.valueOf(Config.getConfig().getProperty("authority")).intValue(); SslConfigurator sslConfig = SslConfigurator.newInstance();
if(authType == 1){
sslConfig.trustStoreFile(Config.getConfig().getProperty("clientTrustCer"))
.trustStorePassword(Config.getConfig().getProperty("clientTrustCerPwd"));
}else if(authType == 2){
sslConfig.keyStoreFile(Config.getConfig().getProperty("clientCer"))
.keyStorePassword(Config.getConfig().getProperty("clientCerPwd"))
.keyPassword(Config.getConfig().getProperty("clientKeyPwd"))
.trustStoreFile(Config.getConfig().getProperty("clientTrustCer"))
.trustStorePassword(Config.getConfig().getProperty("clientTrustCerPwd"));
}
sslConfig.securityProtocol(Config.getConfig().getProperty("protocol"));
SSLContext sslContext = sslConfig.createSSLContext(); ClientConfig cc = new DefaultClientConfig();
cc.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES,
new HTTPSProperties(new MyHostnameVerifier(), sslContext));
Client client = Client.create(cc); URI uri = UriBuilder.fromUri("https://127.0.0.1/queryAddress").port(10000).build();
WebResource resource = client.resource(uri); Person person = new Person();
person.setName("sean"); ClientResponse response = resource
.accept(MediaType.APPLICATION_XML)
.type(MediaType.APPLICATION_XML)
.post(ClientResponse.class, person); String addresses = response.getEntity(String.class);
System.out.println(addresses);
}
}
SSL握手过程中,会对请求IP或请求域名进行校验,如果在证书信息中无法找到相关请求IP或请求域名则会报错(javax.NET.ssl.SSLHandshakeException: Java.security.cert.CertificateException: No subject alternative names present)
这里实现自己的校验逻辑(如果请求的IP为127.0.0.1或请求的域名为localhost,则直接通过校验)以覆盖默认逻辑
package com.sean; import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSession; public class MyHostnameVerifier implements HostnameVerifier { @Override
public boolean verify(String hostname, SSLSession session) {
if("127.0.0.1".equals(hostname) || "localhost".equals(hostname) )
return true;
else
return false;
}
}
服务端代码:
package com.sean; import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List; import javax.net.ssl.SSLContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder; import org.glassfish.grizzly.http.server.HttpHandler;
import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.grizzly.ssl.SSLEngineConfigurator;
import org.glassfish.jersey.SslConfigurator; import com.sun.jersey.api.container.ContainerFactory;
import com.sun.jersey.api.container.grizzly2.GrizzlyServerFactory;
import com.sun.jersey.api.core.PackagesResourceConfig;
import com.sun.jersey.api.core.ResourceConfig; @Path("queryAddress")
public class SSLServer { @POST
@Consumes(MediaType.APPLICATION_XML)
@Produces(MediaType.APPLICATION_XML)
public Person queryAddress(String name) {
System.out.println(name); Person person = new Person();
List<String> addresses = new ArrayList<String>();
addresses.add("address1");
addresses.add("address2");
person.setAddresses(addresses);
return person;
} public static void main(String[] args) {
Integer authType =
Integer.valueOf(Config.getConfig().getProperty("authority")).intValue(); SslConfigurator sslConfig = SslConfigurator.newInstance();
if(authType == 1){
sslConfig.keyStoreFile(Config.getConfig().getProperty("serverCer"))
.keyStorePassword(Config.getConfig().getProperty("serverCerPwd"))
.keyPassword(Config.getConfig().getProperty("serverKeyPwd"));
}else if(authType == 2){
sslConfig.keyStoreFile(Config.getConfig().getProperty("serverCer"))
.keyStorePassword(Config.getConfig().getProperty("serverCerPwd"))
.keyPassword(Config.getConfig().getProperty("serverKeyPwd"))
.trustStoreFile(Config.getConfig().getProperty("serverTrustCer"))
.trustStorePassword(Config.getConfig().getProperty("serverTrustCerPwd"));
}
sslConfig.securityProtocol(Config.getConfig().getProperty("protocol"));
SSLContext sslContext = sslConfig.createSSLContext(); SSLEngineConfigurator sslEngineConfig = new SSLEngineConfigurator(sslContext);
//默认情况下是客户端模式,如果忘记修改模式
//会抛出异常
//javax.net.ssl.SSLProtocolException: Handshake message sequence violation, 1]
sslEngineConfig.setClientMode(false);
if(authType == 1)
sslEngineConfig.setWantClientAuth(true);
else if(authType == 2)
sslEngineConfig.setNeedClientAuth(true); ResourceConfig rc = new PackagesResourceConfig("com.sean");
HttpHandler handler = ContainerFactory.createContainer(
HttpHandler.class, rc); URI uri = UriBuilder.fromUri("https://127.0.0.1/").port(10000).build();
try {
HttpServer server = GrizzlyServerFactory.createHttpServer(uri, handler, true,
sslEngineConfig);
server.start();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (NullPointerException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
Thread.sleep(1000*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
配置文件类:
package com.sean; import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Properties; public class Config{
private static Properties config; public static Properties getConfig(){
try{
if(null == config){
File configFile =
new File("src/main/resources/config/config.properties");
if(configFile.exists() && configFile.isFile()
&& configFile.canRead()){
InputStream input = new FileInputStream(configFile);
config = new Properties();
config.load(input);
}
}
}catch(Exception e){
//default set
config = new Properties();
config.setProperty("authority", String.valueOf(1));
config.setProperty("protocol", "SSL");
config.setProperty("serverCer", "src/main/resources/certificate/server.jks");
config.setProperty("serverCerPwd", "1234sp");
config.setProperty("serverKeyPwd", "1234kp");
config.setProperty("serverTrustCer", "src/main/resources/certificate/serverTrust.jks");
config.setProperty("serverTrustCerPwd", "1234sp");
config.setProperty("clientCer", "src/main/resources/certificate/client.jks");
config.setProperty("clientCerPwd", "1234sp");
config.setProperty("clientKeyPwd", "1234kp");
config.setProperty("clientTrustCer", "src/main/resources/certificate/clientTrust.jks");
config.setProperty("clientTrustCerPwd", "1234sp");
}
return config;
}
}
配置文件config.properties:
#1:单向认证,只有服务器端需证明其身份
#2:双向认证,服务器端和客户端都需证明其身份
authority=2
#通信协议
protocol=SSL
#服务端证书信息
serverCer=src/main/resources/certificate/server.jks
#keystore的storepass
serverCerPwd=1234sp
#keystore的keypass
serverKeyPwd=1234kp
#服务端证书信息
serverTrustCer=src/main/resources/certificate/serverTrust.jks
serverTrustCerPwd=1234sp
#客户端证书信息
clientCer=src/main/resources/certificate/client.jks
clientCerPwd=1234sp
clientKeyPwd=1234kp
clientTrustCer=src/main/resources/certificate/clientTrust.jks
clientTrustCerPwd=1234sp
服务端运行结果:
三月 03, 2015 3:30:54 下午 com.sun.jersey.api.core.PackagesResourceConfig init
INFO: Scanning for root resource and provider classes in the packages:
com.sean
三月 03, 2015 3:30:54 下午 com.sun.jersey.api.core.ScanningResourceConfig logClasses
INFO: Root resource classes found:
class com.sean.SSLServer
三月 03, 2015 3:30:54 下午 com.sun.jersey.api.core.ScanningResourceConfig init
INFO: No provider classes found.
三月 03, 2015 3:30:54 下午 com.sun.jersey.server.impl.application.WebApplicationImpl _initiate
INFO: Initiating Jersey application, version 'Jersey: 1.18 11/22/2013 01:21 AM'
三月 03, 2015 3:30:55 下午 org.glassfish.grizzly.http.server.NetworkListener start
INFO: Started listener bound to [127.0.0.1:10000]
三月 03, 2015 3:30:55 下午 org.glassfish.grizzly.http.server.HttpServer start
INFO: [HttpServer] Started.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><person><name>sean</name></person>
客户端运行结果
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><person><addresses>address1</addresses><addresses>address2</addresses></person>
Jersey框架三:Jersey对HTTPS的支持的更多相关文章
- Jersey框架二:Jersey对JSON的支持
Jersey系列文章: Jersey框架一:Jersey RESTful WebService框架简介 Jersey框架二:Jersey对JSON的支持 Jersey框架三:Jersey对HTTPS的 ...
- Jersey框架一:Jersey RESTful WebService框架简介
Jersey系列文章: Jersey框架一:Jersey RESTful WebService框架简介 Jersey框架二:Jersey对JSON的支持 Jersey框架三:Jersey对HTTPS的 ...
- Java Restful框架:Jersey入门示例(官方例子)
本文主要介绍了Java Restful框架Jersey入门例子(来源于官方网站https://jersey.java.net/),废话不多说进入正题. 在Jersey官方示例中(https://jer ...
- jersey框架实现文件上传
jersey框架是一个开源的RESTful的框架,实现了实现了JAX-RS规范,进一步地简化 RESTful service 和 client 开发.当然而且是必须的,jersey对文件的上传和下载也 ...
- Equinox OSGi应用嵌入Jersey框架搭建REST服务
原文地址:https://www.cnblogs.com/kira2will/p/5040264.html 一.环境 eclipse版本:eclipse-luna 4.4 jre版本:1.8 二.Eq ...
- Oltu在Jersey框架上实现oauth2.0授权模块
oltu是一个开源的oauth2.0协议的实现,本人在此开源项目的基础上进行修改,实现一个自定义的oauth2.0模块. 关于oltu的使用大家可以看这里:http://oltu.apache.org ...
- 关于Jersey框架下的Aop日志 和Spring 框架下的Aop日志
摘要 最近新接手的项目经常要查问题,但是,前面一拨人,日志打的非常乱,好多就根本没有打日志,所以弄一个AOP统一打印一下 请求数据和响应数据 框架 spring+springmvc+jersey 正文 ...
- 原创:Equinox OSGi应用嵌入Jersey框架搭建REST服务
一.环境 eclipse版本:eclipse-luna 4.4 jre版本:1.8 二.Equinox OSGi应用嵌入Jersey框架搭建REST服务 1.新建插件工程HelloWebOSGI a. ...
- 如何解决jersey框架中以json格式返回数组,当数组中元素一个时json格式不对
原文地址:http://www.cnblogs.com/swpk/p/3566536.html?utm_source=tuicool jersey 是oracle 出的一个较好的REST框架.使用此框 ...
随机推荐
- 认识axure部件库中各个部件的属性
在axure中每一个部件都有自己的属性,下面这个表格,我们就首先来了解认识一下!以下内容来自网站蓝图,版权归原作者所有! 属性名称 属性说明 属性举例 标签 用来标示部件的名称,在axure中,部件名 ...
- hdu4709求三角形面积
Herding Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Su ...
- Android之一个简单计算器源代码
通过Android4.0 网格布局GridLayout来实现一个简单的计算器界面布局 源码如下(欢迎大家指导 批评 ) package com.android.xiong.gridlayoutTe ...
- 基于visual Studio2013解决C语言竞赛题之1067间隔排序
题目 解决代码及点评 /* 功能:间隔元素排序.用随机函数产生25个[25,75]之间的整数, 把它送到一维数组M中. 要求对M[I],M[I+J],M[I+2*J],-这些元 ...
- VxWorks6.6 pcPentium BSP 使用说明(二):创建启动盘
本篇介绍从Solaris.Linux.Windows或VxWorks创建VxWorks启动盘的方法. 从Solaris或Linux创建启动盘 使用Solaris或Linux自带的工具/usr/bin/ ...
- 国际化之MessageFormat与占位符
如果一个字符串文本中包含了多个与国际化相关的数据,可以使用MessageFormat类对这些数据进行批量处理. 例如: 在2016年1月9日的时候,一场台风导致了500间房屋的摧毁和¥1000000元 ...
- python 网络爬虫(二) BFS不断抓URL并放到文件中
上一篇的python 网络爬虫(一) 简单demo 还不能叫爬虫,只能说基础吧,因为它没有自动化抓链接的功能. 本篇追加如下功能: [1]广度优先搜索不断抓URL,直到队列为空 [2]把所有的URL写 ...
- Android 高手进阶,自己定义圆形进度条
背景介绍 在Android 开发中,我们常常遇到各种各样绚丽的控件,所以,依靠我们Android本身所带的控件是远远不够的,许多时候须要我们自定义控件,在开发的过程中.我们公司遇到了一种须要自己写的一 ...
- MongoDB学习笔记(四) 用MongoDB的文档结构描述数据关系
MongoDB的集合(collection)可以看做关系型数据库的表,文档对象(document)可以看做关系型数据库的一条记录.但两者并不完全对等.表的结构是固定的,MongoDB集合并没有这个约束 ...
- net析构函数对垃圾回收的影响
net析构函数对垃圾回收的影响 之前忘了说了 代码都是在Release模式下运行的,现在补充上. 这里说析构函数,其实并不准确,应该叫Finalize函数,Finalize函数形式上和c++的析构函数 ...