Jersey框架三:Jersey对HTTPS的支持详解编程语言

Jersey系列文章:

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

Jersey框架二:Jersey对JSON的支持

Jersey框架三:Jersey对HTTPS的支持

证书的生成过程这里就不介绍了,请参照:Java网络编程二:Java Secure(SSL/TLS) Socket实现 中的证书部分

代码结构如下:

Jersey框架三:Jersey对HTTPS的支持详解编程语言

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>  

原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/19463.html

(0)
上一篇 2021年7月19日 22:14
下一篇 2021年7月19日 22:14

相关推荐

发表回复

登录后才能评论