实现Spring RESTful服务的SSL
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt386
本文介绍如何让基于Spring的REST服务变得SSL/TSL化。
首先,假设一个Spring REST 服务如下:
|
1
2
3
4
5
6
7
8
9
|
@Controller@RequestMapping("/")public class RestService { @RequestMapping(method = RequestMethod.GET) @ResponseBody public String get() { return "Called the get Rest Service"; }} |
Web.xml的配置如下:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
<?xml version="1.0" encoding="UTF-8"?><web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"> <servlet> <servlet-name>rest</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextClass</param-name> <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value> </init-param> <init-param> <param-name>contextConfigLocation</param-name> <param-value>com.radcortez.rest.ssl</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>rest</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <security-constraint> <web-resource-collection> <web-resource-name>Rest Application</web-resource-name> <url-pattern>/*</url-pattern> </web-resource-collection> <user-data-constraint> <!-- Needed for our application to respond to https requests --> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint> </security-constraint></web-app> |
注意其中security-constraint, user-data-constraint 和 <transport-guarantee>CONFIDENTIAL</transport-guarantee>配置,这些指定这个应用需要一个安全连接。
运行这个服务,部署应用到TomEE,键入网址:https://localhost:8443/,如果你正常配置了tomcat的SSL配置,浏览https和端口844应该一切正常,返回:Called the Rest Service
如果现在调用客户端不是一般浏览器,而是一个Java客户端,这时会抛出错误:
Message: I/O error on GET request for "https://localhost:8443/":sun.security.validator.ValidatorException:
Exception: Caused by: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
这是因为客户端JDK并没有你服务器的证书,你需要导入,这里我们展示使用编程方式提供信任蜜月的方式,这样做的好处:
你可以运行应用代码在多个环境(和JDK无关)
你不必每次手工将证书导入JDK
你也不必升级JDK时得记住你的证书
其他原因导致你不能直接向JDK导入证书
编写代码:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
RestClientConfig.java@Configuration@PropertySource("classpath:config.properties")public class RestClientConfig { @Bean public RestOperations restOperations(ClientHttpRequestFactory clientHttpRequestFactory) throws Exception { return new RestTemplate(clientHttpRequestFactory); } @Bean public ClientHttpRequestFactory clientHttpRequestFactory(HttpClient httpClient) { return new HttpComponentsClientHttpRequestFactory(httpClient); } @Bean public HttpClient httpClient(@Value("${keystore.file}") String file, @Value("${keystore.pass}") String password) throws Exception { KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); FileInputStream instream = new FileInputStream(new File(file)); try { trustStore.load(instream, password.toCharArray()); } finally { instream.close(); } SSLContext sslcontext = SSLContexts.custom() .loadTrustMaterial(trustStore, new TrustSelfSignedStrategy()).build(); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1.2"}, null, BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); return HttpClients.custom().setSSLSocketFactory(sslsf).build(); } @Bean public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() { return new PropertySourcesPlaceholderConfigurer(); }} |
这里我们使用Spring RestOperations接口规定一个RESTful操作的基本集合,下面我们使用Apache HTTP组件SSLConnectionSocketFactory 提供的功能来校验服务器的信任密钥,也是使用服务器的 KeyStore。
RestServiceClientIT.java
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(classes = RestClientConfig.class)public class RestServiceClientIT { @Autowired private RestOperations rest; @Test public void testRestRequest() throws Exception { ResponseEntity response = rest.getForEntity("https://localhost:8443/", String.class); System.out.println("response = " + response); System.out.println("response.getBody() = " + response.getBody()); }} |
上面是一个简单的测试类,我们需要一个属性文件提供keystore文件位置和密码:
config.properties
keystore.file=${user.home}/.keystore
keystore.pass=changeit
现在我们可以运行测试客户端,你应该得到如下:
Response: <200 OK,Called the get Rest Service,{Server=[Apache-Coyote/1.1], Cache-Control=[private], Expires=[Thu, 01 Jan 1970 01:00:00 WET], Content-Type=, Content-Length=[27], Date=[Tue, 23 Dec 2014 01:29:20 GMT]}>
Body: Called the get Rest Service
这说明一切正常,现在,你可以使用Java客户端以SSL/TLS方式调用你的REST服务了。
实现Spring RESTful服务的SSL的更多相关文章
- Spring RESTful服务接收和返回JSON最佳实践
http://blog.csdn.net/prince_hua/article/details/12103501
- 使用Spring Security Oauth2完成RESTful服务password认证的过程
摘要:Spring Security与Oauth2整合步骤中详细描述了使用过程,但它对于入门者有些重量级,比如将用户信息.ClientDetails.token存入数据库而非内存.配置 ...
- 应用Spring MVC发布restful服务是怎样的一种体验
摘要:“约定优于配置”这是一个相当棒的经验,SOAP服务性能差.基于配置.紧耦合,restful服务性能好.基于约定.松耦合,现在我就把使用Spring MVC发布restful服务的 ...
- Spring Boot初探之restful服务发布
一.背景 Spring boot是集服务发布.数据库管理.日志管理等于一身的服务开发框架:是微服务开发的全能小帮手.这章讲述一下如何使用spring boot发布restful服务接口. 二.搭建基础 ...
- 用Kotlin写一个基于Spring Boot的RESTful服务
Spring太复杂了,配置这个东西简直就是浪费生命.尤其在没有什么并发压力,随便搞一个RESTful服务 让整个业务跑起来先的情况下,更是么有必要纠结在一堆的XML配置上.显然这么想的人是很多的,于是 ...
- CXF+Spring+JAXB+Json构建Restful服务
话不多说,先看详细的样例: 文件文件夹结构: web.xml <?xml version="1.0" encoding="UTF-8"? > < ...
- 使用spring mvc或者resteasy构建restful服务
看到最近一个项目里用resteasy来构建restful接口,有点不明白,不少Spring mvc4.0以后也可以很方面的实现restful服务吗,为啥还要在Spring MVC的项目里还引入rest ...
- 实战SpringCloud响应式微服务系列教程(第九章)使用Spring WebFlux构建响应式RESTful服务
本文为实战SpringCloud响应式微服务系列教程第九章,讲解使用Spring WebFlux构建响应式RESTful服务.建议没有之前基础的童鞋,先看之前的章节,章节目录放在文末. 从本节开始我们 ...
- HTTP RESTful服务开发 spring boot+Maven +Swagger
这周配合第三方平台整合系统,需要提供HTTP REST服务和使用ActiveMQ推送消息,研究了下,做个笔记. 1.使用eclipse创建Spring Boot项目 创建Spring Boot项目( ...
随机推荐
- VM虚拟机中安装Linux操作系统
本文操作步骤,笔者已实验成功 (前提:正确安装VM并激活) 1,点击新建虚拟机,在页面上选择"自定义",点击下一步 2,进入选择虚拟机硬件兼容页面,这里一般不用操作,直接点击下一步 ...
- 自定义MySQL函数
1.MySQL创建函数语法: CREATE [DEFINER = { user | CURRENT_USER }] FUNCTION sp_name ([func_parameter[,...]]) ...
- Java读取properties文件(非泛滥)
根据spring配置文件的 PropertiesFactoryBean和 PropertyPlaceholderConfigurer可以选择不同的加载方式,我是使用System.setProperty ...
- 已有 JFFs2文件系统的修改
项目应用中,对于前人留下的JFFS2的文件,有时候我们需要修改,但是苦于没有源文件,实际操作很多时候无所适从.每次支持生产之后再进行人为的升级.这样费时费力,也给生产人员增加了负担. 为了解决这个问题 ...
- Lenovo T440p 外放没有声音
背景:Lenovo T440p,今天突然想听会歌 外放竟然没声音,fuck!!! 任务栏声音图标也没有静音标志. 驱动出问题了?检查下驱动,正常. 找了耳机试下,正常,看来驱动真的没问题. 喇叭坏了? ...
- POJ 3311 Hie with the Pie:TSP(旅行商)【节点可多次经过】
题目链接:http://poj.org/problem?id=3311 题意: 你在0号点(pizza店),要往1到n号节点送pizza. 每个节点可以重复经过. 给你一个(n+1)*(n+1)的邻接 ...
- 为什么重写 equals 方法 必须重写 hashCode
自己学到这,就记录了下来,代码都是自己敲得,有不对的地方希望大神指点出来 为什么重写 equals 方法 必须重写 hashCode 如果你重写了equals,比如说是基于对象的内容实现的,而不重写 ...
- softmax函数
该函数作用于输出层之上,用于改善输出层神经元饱和时与该神经元直接相关的w和bias学习率下降的问题. 定义: 这表明,在用柔性最大值函数定义输出神经元的输出时,神经元的输出是一种概率分布,所有输出层神 ...
- HTML5+js页面传值给Java后台的小技巧
页面传值小技巧 平常我们在做的web项目,一般一个HTML页面上会有好几个步骤,step_num①,step_num②,step_num③,一般先显示step_num①,根据跳转条件显示step_nu ...
- Webstorm 提示 Can't use Subversion command line client
Webstorm 提示 Can't use Subversion command line client Webstorm 提示 Can't use Subversion command line c ...