加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Jersey框架三:Jersey对HTTPS的支持

发布时间:2020-12-16 23:02:01 所属栏目:安全 来源:网络整理
导读:Jersey系列文章: Jersey框架一:Jersey RESTful WebService框架简介 Jersey框架二:Jersey对JSON的支持 Jersey框架三:Jersey对HTTPS的支持 ? 证书的生成过程这里就不介绍了,请参照:Java网络编程二:Java Secure(SSL/TLS) Socket实现 中的证书部分 代码结

Jersey系列文章:

Jersey框架一:Jersey RESTful WebService框架简介

Jersey框架二:Jersey对JSON的支持

Jersey框架三:Jersey对HTTPS的支持

?

证书的生成过程这里就不介绍了,请参照: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>

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读