zoukankan      html  css  js  c++  java
  • Jersey框架三:Jersey对HTTPS的支持

    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>  
  • 相关阅读:
    查看邵杨的源码
    java 读写excle
    绘图的引擎
    handler的使用
    小结
    周末,啦啦啦
    监控宝发布移动应用监控服务 引领移动APM
    监控宝优化升级 创新驱动用户体验
    云智慧:顺势而为 做世界级APM服务商
    性能为王:云智慧APM助小米IT服务能力提升
  • 原文地址:https://www.cnblogs.com/chen-lhx/p/6138484.html
Copyright © 2011-2022 走看看