Jersey框架三:Jersey对HTTPS的支持

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

代码结构如下:

Maven配置文件:

[html]  view plain  copy
  1. <project xmlns="http://maven.apache.org/POM/4.0.0"   
  2.         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"   
  3.         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0   
  4.                 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
  5.     <modelVersion>4.0.0</modelVersion>  
  6.     <groupId>JERSEY</groupId>  
  7.     <artifactId>JERSEY</artifactId>  
  8.     <version>1.0</version>  
  9.     <dependencies>          
  10.         <dependency>  
  11.             <groupId>com.sun.jersey</groupId>  
  12.             <artifactId>jersey-client</artifactId>  
  13.             <version>1.18</version>  
  14.         </dependency>  
  15.         <dependency>  
  16.             <groupId>com.sun.jersey</groupId>  
  17.             <artifactId>jersey-grizzly2</artifactId>  
  18.             <version>1.18</version>  
  19.         </dependency>  
  20.         <dependency>  
  21.             <groupId>com.sun.jersey</groupId>  
  22.             <artifactId>jersey-json</artifactId>  
  23.             <version>1.18</version>  
  24.         </dependency>  
  25.         <dependency>  
  26.             <groupId>org.glassfish.jersey.media</groupId>  
  27.             <artifactId>jersey-media-json-jackson</artifactId>  
  28.             <version>2.15</version>  
  29.         </dependency>  
  30.     </dependencies>  
  31. </project>  

Person类是基本的JAXB:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package com.sean;  
  2.   
  3. import java.util.List;  
  4.   
  5. import javax.xml.bind.annotation.XmlRootElement;  
  6.   
  7. @XmlRootElement  
  8. public class Person {  
  9.     private String name;  
  10.     private List<String> addresses;  
  11.       
  12.     public Person(){}  
  13.       
  14.     public String getName() {  
  15.         return name;  
  16.     }  
  17.       
  18.     public void setName(String name) {  
  19.         this.name = name;  
  20.     }  
  21.       
  22.     public List<String> getAddresses() {  
  23.         return addresses;  
  24.     }  
  25.       
  26.     public void setAddresses(List<String> addresses) {  
  27.         this.addresses = addresses;  
  28.     }  
  29. }  

客户端代码:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package com.sean;  
  2.   
  3. import java.net.URI;  
  4.   
  5. import javax.net.ssl.SSLContext;  
  6. import javax.ws.rs.core.MediaType;  
  7. import javax.ws.rs.core.UriBuilder;  
  8.   
  9. import org.glassfish.jersey.SslConfigurator;  
  10.   
  11. import com.sun.jersey.api.client.Client;  
  12. import com.sun.jersey.api.client.ClientResponse;  
  13. import com.sun.jersey.api.client.WebResource;  
  14. import com.sun.jersey.api.client.config.ClientConfig;  
  15. import com.sun.jersey.api.client.config.DefaultClientConfig;  
  16. import com.sun.jersey.client.urlconnection.HTTPSProperties;  
  17.   
  18. public class SSLClient {  
  19.     public static void main(String[] args) {  
  20.         int authType =  
  21.                 Integer.valueOf(Config.getConfig().getProperty("authority")).intValue();  
  22.           
  23.         SslConfigurator sslConfig = SslConfigurator.newInstance();  
  24.         if(authType == 1){  
  25.             sslConfig.trustStoreFile(Config.getConfig().getProperty("clientTrustCer"))  
  26.                     .trustStorePassword(Config.getConfig().getProperty("clientTrustCerPwd"));  
  27.         }else if(authType == 2){  
  28.             sslConfig.keyStoreFile(Config.getConfig().getProperty("clientCer"))  
  29.                     .keyStorePassword(Config.getConfig().getProperty("clientCerPwd"))  
  30.                     .keyPassword(Config.getConfig().getProperty("clientKeyPwd"))  
  31.                     .trustStoreFile(Config.getConfig().getProperty("clientTrustCer"))  
  32.                     .trustStorePassword(Config.getConfig().getProperty("clientTrustCerPwd"));  
  33.         }  
  34.         sslConfig.securityProtocol(Config.getConfig().getProperty("protocol"));  
  35.         SSLContext sslContext = sslConfig.createSSLContext();  
  36.           
  37.         ClientConfig cc = new DefaultClientConfig();  
  38.         cc.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES,   
  39.                 new HTTPSProperties(new MyHostnameVerifier(), sslContext));  
  40.         Client client = Client.create(cc);  
  41.           
  42.         URI uri = UriBuilder.fromUri("https://127.0.0.1/queryAddress").port(10000).build();  
  43.         WebResource resource = client.resource(uri);  
  44.           
  45.         Person person = new Person();  
  46.         person.setName("sean");  
  47.           
  48.         ClientResponse response = resource  
  49.                 .accept(MediaType.APPLICATION_XML)  
  50.                 .type(MediaType.APPLICATION_XML)  
  51.                 .post(ClientResponse.class, person);  
  52.           
  53.         String addresses = response.getEntity(String.class);  
  54.         System.out.println(addresses);  
  55.     }  
  56. }  

SSL握手过程中,会对请求IP或请求域名进行校验,如果在证书信息中无法找到相关请求IP或请求域名则会报错(javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names present)

这里实现自己的校验逻辑(如果请求的IP为127.0.0.1或请求的域名为localhost,则直接通过校验)以覆盖默认逻辑

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package com.sean;  
  2.   
  3. import javax.net.ssl.HostnameVerifier;  
  4. import javax.net.ssl.SSLSession;  
  5.   
  6. public class MyHostnameVerifier implements HostnameVerifier {  
  7.   
  8.     @Override  
  9.     public boolean verify(String hostname, SSLSession session) {  
  10.         if("127.0.0.1".equals(hostname) || "localhost".equals(hostname) )  
  11.             return true;  
  12.         else  
  13.             return false;  
  14.     }  
  15. }  

服务端代码:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package com.sean;  
  2.    
  3. import java.io.IOException;  
  4. import java.net.URI;  
  5. import java.util.ArrayList;  
  6. import java.util.List;  
  7.   
  8. import javax.net.ssl.SSLContext;  
  9. import javax.ws.rs.Consumes;  
  10. import javax.ws.rs.POST;  
  11. import javax.ws.rs.Path;  
  12. import javax.ws.rs.Produces;  
  13. import javax.ws.rs.core.MediaType;  
  14. import javax.ws.rs.core.UriBuilder;  
  15.   
  16. import org.glassfish.grizzly.http.server.HttpHandler;  
  17. import org.glassfish.grizzly.http.server.HttpServer;  
  18. import org.glassfish.grizzly.ssl.SSLEngineConfigurator;  
  19. import org.glassfish.jersey.SslConfigurator;  
  20.   
  21. import com.sun.jersey.api.container.ContainerFactory;  
  22. import com.sun.jersey.api.container.grizzly2.GrizzlyServerFactory;  
  23. import com.sun.jersey.api.core.PackagesResourceConfig;  
  24. import com.sun.jersey.api.core.ResourceConfig;  
  25.    
  26. @Path("queryAddress")   
  27. public class SSLServer {  
  28.       
  29.     @POST  
  30.     @Consumes(MediaType.APPLICATION_XML)  
  31.     @Produces(MediaType.APPLICATION_XML)  
  32.     public Person queryAddress(String name) {  
  33.         System.out.println(name);  
  34.           
  35.         Person person = new Person();  
  36.         List<String> addresses = new ArrayList<String>();  
  37.         addresses.add("address1");  
  38.         addresses.add("address2");  
  39.         person.setAddresses(addresses);  
  40.         return person;  
  41.     }  
  42.       
  43.     public static void main(String[] args) {  
  44.         Integer authType =   
  45.                 Integer.valueOf(Config.getConfig().getProperty("authority")).intValue();  
  46.           
  47.         SslConfigurator sslConfig = SslConfigurator.newInstance();  
  48.         if(authType == 1){  
  49.             sslConfig.keyStoreFile(Config.getConfig().getProperty("serverCer"))  
  50.                     .keyStorePassword(Config.getConfig().getProperty("serverCerPwd"))  
  51.                     .keyPassword(Config.getConfig().getProperty("serverKeyPwd"));  
  52.         }else if(authType == 2){  
  53.             sslConfig.keyStoreFile(Config.getConfig().getProperty("serverCer"))  
  54.                     .keyStorePassword(Config.getConfig().getProperty("serverCerPwd"))  
  55.                     .keyPassword(Config.getConfig().getProperty("serverKeyPwd"))  
  56.                     .trustStoreFile(Config.getConfig().getProperty("serverTrustCer"))  
  57.                     .trustStorePassword(Config.getConfig().getProperty("serverTrustCerPwd"));  
  58.         }  
  59.         sslConfig.securityProtocol(Config.getConfig().getProperty("protocol"));  
  60.         SSLContext sslContext = sslConfig.createSSLContext();  
  61.           
  62.         SSLEngineConfigurator sslEngineConfig = new SSLEngineConfigurator(sslContext);  
  63.         //默认情况下是客户端模式,如果忘记修改模式  
  64.         //会抛出异常  
  65.         //javax.net.ssl.SSLProtocolException: Handshake message sequence violation, 1]  
  66.         sslEngineConfig.setClientMode(false);  
  67.         if(authType == 1)  
  68.             sslEngineConfig.setWantClientAuth(true);  
  69.         else if(authType == 2)  
  70.             sslEngineConfig.setNeedClientAuth(true);  
  71.               
  72.         ResourceConfig rc = new PackagesResourceConfig("com.sean");  
  73.         HttpHandler handler = ContainerFactory.createContainer(  
  74.                 HttpHandler.class, rc);  
  75.           
  76.         URI uri = UriBuilder.fromUri("https://127.0.0.1/").port(10000).build();  
  77.         try {  
  78.             HttpServer server = GrizzlyServerFactory.createHttpServer(uri, handler, true,   
  79.                     sslEngineConfig);  
  80.             server.start();  
  81.         } catch (IllegalArgumentException e) {  
  82.             e.printStackTrace();  
  83.         } catch (NullPointerException e) {  
  84.             e.printStackTrace();  
  85.         } catch (IOException e) {  
  86.             e.printStackTrace();  
  87.         }  
  88.         try {  
  89.             Thread.sleep(1000*1000);  
  90.         } catch (InterruptedException e) {  
  91.             e.printStackTrace();  
  92.         }  
  93.     }  
  94. }  

配置文件类:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package com.sean;  
  2.   
  3. import java.io.File;  
  4. import java.io.FileInputStream;  
  5. import java.io.InputStream;  
  6. import java.util.Properties;  
  7.   
  8. public class Config{  
  9.     private static Properties config;  
  10.       
  11.     public static Properties getConfig(){  
  12.         try{  
  13.             if(null == config){  
  14.                 File configFile =   
  15.                         new File("src/main/resources/config/config.properties");  
  16.                 if(configFile.exists() && configFile.isFile()  
  17.                         && configFile.canRead()){  
  18.                     InputStream input = new FileInputStream(configFile);  
  19.                     config = new Properties();  
  20.                     config.load(input);  
  21.                 }  
  22.             }  
  23.         }catch(Exception e){  
  24.             //default set  
  25.             config = new Properties();  
  26.             config.setProperty("authority", String.valueOf(1));  
  27.             config.setProperty("protocol""SSL");  
  28.             config.setProperty("serverCer""src/main/resources/certificate/server.jks");  
  29.             config.setProperty("serverCerPwd""1234sp");  
  30.             config.setProperty("serverKeyPwd""1234kp");  
  31.             config.setProperty("serverTrustCer""src/main/resources/certificate/serverTrust.jks");  
  32.             config.setProperty("serverTrustCerPwd""1234sp");  
  33.             config.setProperty("clientCer""src/main/resources/certificate/client.jks");  
  34.             config.setProperty("clientCerPwd""1234sp");  
  35.             config.setProperty("clientKeyPwd""1234kp");  
  36.             config.setProperty("clientTrustCer""src/main/resources/certificate/clientTrust.jks");  
  37.             config.setProperty("clientTrustCerPwd""1234sp");  
  38.         }  
  39.         return config;  
  40.     }  
  41. }  

配置文件config.properties:

[plain]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #1:单向认证,只有服务器端需证明其身份      
  2. #2:双向认证,服务器端和客户端都需证明其身份  
  3. authority=2  
  4. #通信协议    
  5. protocol=SSL  
  6. #服务端证书信息    
  7. serverCer=src/main/resources/certificate/server.jks  
  8. #keystore的storepass    
  9. serverCerPwd=1234sp  
  10. #keystore的keypass    
  11. serverKeyPwd=1234kp  
  12. #服务端证书信息    
  13. serverTrustCer=src/main/resources/certificate/serverTrust.jks  
  14. serverTrustCerPwd=1234sp  
  15. #客户端证书信息    
  16. clientCer=src/main/resources/certificate/client.jks  
  17. clientCerPwd=1234sp  
  18. clientKeyPwd=1234kp  
  19. clientTrustCer=src/main/resources/certificate/clientTrust.jks  
  20. clientTrustCerPwd=1234sp  

服务端运行结果:

[plain]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. 三月 03, 2015 3:30:54 下午 com.sun.jersey.api.core.PackagesResourceConfig init  
  2. INFO: Scanning for root resource and provider classes in the packages:  
  3.   com.sean  
  4. 三月 03, 2015 3:30:54 下午 com.sun.jersey.api.core.ScanningResourceConfig logClasses  
  5. INFO: Root resource classes found:  
  6.   class com.sean.SSLServer  
  7. 三月 03, 2015 3:30:54 下午 com.sun.jersey.api.core.ScanningResourceConfig init  
  8. INFO: No provider classes found.  
  9. 三月 03, 2015 3:30:54 下午 com.sun.jersey.server.impl.application.WebApplicationImpl _initiate  
  10. INFO: Initiating Jersey application, version 'Jersey: 1.18 11/22/2013 01:21 AM'  
  11. 三月 03, 2015 3:30:55 下午 org.glassfish.grizzly.http.server.NetworkListener start  
  12. INFO: Started listener bound to [127.0.0.1:10000]  
  13. 三月 03, 2015 3:30:55 下午 org.glassfish.grizzly.http.server.HttpServer start  
  14. INFO: [HttpServer] Started.  
  15. <?xml version="1.0" encoding="UTF-8" standalone="yes"?><person><name>sean</name></person>  

客户端运行结果

[plain]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8" standalone="yes"?><person><addresses>address1</addresses><addresses>address2</addresses></person>  
1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值