首先cmd命令行输入如下:
keytool -genkey -alias tomcat -keyalg RSA -keystore ./server.keystore
接着按提示输入:输入完口令后,一顿回车,直到问你是否确认你输入y
输入密钥库口令:888888
再次输入新口令:888888
您的名字与姓氏是什么?
[Unknown]:
您的组织单位名称是什么?
[Unknown]:
您的组织名称是什么?
[Unknown]:
您所在的城市或区域名称是什么?
[Unknown]:
您所在的省/市/自治区名称是什么?
[Unknown]:
该单位的双字母国家/地区代码是什么?
[Unknown]:
CN=kaibowang, OU=yuxuelian, O=yuxuelian, L=chengdu, ST=chengdushi, C=china是否正确?
[否]: y
输入 的密钥口令
(如果和密钥库口令相同, 按回车):
再次输入新口令:
Warning:
JKS 密钥库使用专用格式。建议使用 "keytool -importkeystore -srckeystore C:\Users\Administrator\.keystore -destkeystore C:\Users\Administrator\.keystore -deststoretype pkcs12" 迁移到行业标准格式 PKCS12
此时,你就可以在电脑的用户组目录下发现server.keystore文件,说明证书生成了。接着将这个证书放到Springboot项目resource目录下。然后配置yaml文件:
server:
port: 5001
servlet:
context-path: /ais/ogw
ssl:
key-alias: tomcat
key-store: classpath:server.keystore # 证书路径,有可能你放到resouce目录下,需要重新构建以下项目,不然可能会抛出找不到server.keystore错误。
enabled: true
key-store-password: 888888 # 填写你当时创建证书的密钥
key-store-type: JKS
到次,你直接浏览器访问https://localhost:端口/你的资源路径。
就可以看到成功!
前端发起http请求自动转成访问https请求。
如浏览器访问http://localhost/资源路径。自动重定向访问到你JavaHttps服务器的https://localhost:服务器端口/资源路径.
import org.apache.catalina.Context;
import org.apache.catalina.connector.Connector;
import org.apache.tomcat.util.descriptor.web.SecurityCollection;
import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class HttpsConfig {
@Bean
public TomcatServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
@Override
protected void postProcessContext(Context context) {
SecurityConstraint securityConstraint = new SecurityConstraint();
securityConstraint.setUserConstraint("CONFIDENTIAL");
SecurityCollection collection = new SecurityCollection();
collection.addPattern("/*");
securityConstraint.addCollection(collection);
context.addConstraint(securityConstraint);
}
};
tomcat.addAdditionalTomcatConnectors(initHttpConnector());
return tomcat;
}
private Connector initHttpConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setScheme("http");
// 监听http协议的80端口
connector.setPort(80);
connector.setSecure(false);
// 将http 请求转发到https 的5001 (你后端服务器啥地址,这里就填写啥,我是5001)
connector.setRedirectPort(5001);
return connector;
}
}
重启服务,浏览器直接访问localhost/资源路径。会发现浏览器自动302冲顶向到你https服务器的资源。因为你设置了监听80端口。你可以打开浏览器的网络查看,会显示302重定向消息。
假设现在前端vue项目所在服务器8080.首先8080是跨域访问https后端。你需要解决跨域,跨域我目前知道的有三种方案:
1. jsonp处理(前端ajax采用jsonp方式,后端处理的时候拿到前端传递过来的回调函数名,构建一个调用函数的代码字符串)
2. 后端配置crossFilter,或者实现WebMvcconfigurer往里面注册跨域信息。(这种方式我试了,我目前无法实现http跨https。你后端如果是http的话,随便跨,不管前端采用https协议还是怎么滴,都能跨。但是后端如果是https协议。前端发http请求,就会提示跨域)。
3. 用nginx服务器(还没试过)
/cross2,我是向用来演示后端配置跨域是否能打通。
/cross,我是用来演示采用jsonp方式跨域能否打通。
/**
* 这是演示直接在后端配置跨域解决。
* @return
*/
@GetMapping("/cross2")
@ResponseBody
public Map cross2(){
System.out.println("cross2.......");
Map map = new HashMap<>();
map.put("data","hello...cross2...success");
return map;
}
/**
* 这是演示jsonp 来处理跨域的。
* @param request
* @param response
*/
@GetMapping("/cross")
public void testCross(HttpServletRequest request, HttpServletResponse response){
System.out.println("testCross.....start");
try {
// 1. 接收前端回调函数名
String callback = request.getParameter("callback");
// 2. 业务逻辑处理(我这里简单演示)。。。。
String data = "hello world";
// 3. 通过前端传递的回调函数名,我们将data数据放入这个回调函数的参数上,并且以字符串方式调用这个回调函数
String jsoncallback = callback + "({'result':'"+data+"'})";
// 4. 由于是jsonp 只能处理get请求,get请求又有乱码问题,只好设置一下响应字符编码
response.setContentType("text/html");
response.setCharacterEncoding("utf-8");
// 5. 通过输入流将jsoncallback这个调用过程,打回给浏览器
PrintWriter out = response.getWriter();
out.println(jsoncallback);
out.flush();
out.close();
System.out.println("testCross....end");
} catch (IOException e) {
e.printStackTrace();
}
}
这是我后端配置的允许跨域。而且我也测试了,后端如果是采用http协议启动,前端vue8080是能够跨域访问的,这就说明这个配置是起作用的。
@Configuration
public class MvcConfig implements WebMvcConfigurer {
/**
* 解决跨域请求
* @return
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowCredentials(true)
.allowedOrigins("*")
.allowedHeaders("*")
.allowedMethods("*")
.maxAge(3600);
WebMvcConfigurer.super.addCorsMappings(registry);
}
}
前端是vue项目,服务器启动在8080端口。就两个按钮,用来测试用。
当我点击测试jsonp跨域按钮时,前端采用ajax并且是jsonp方式,发现后端服务器正常请求。浏览器正常接收。
我们来查看网络分析一下流程:
首先两个请求一个302,一个200.
302请求首先是访问http://localhost/.....是访问本台地址80端口,正好就被我后端https配置监听80端口,随后就302重定向到https的5001端口去,从而有第二个响应正常200的请求。
我们再来点击crossfilter处理跨域的情况。发现出现了跨域,为什么这样?
一样,查看网络情况:
302应该说明被后端服务器检测到http的80端口,做出了响应告诉浏览器重定向到https的5001,可是我们来看后端控制台情况, 什么也没有输出。我们的/cross2接口如果有进来,是会输出的。
说明crossFilter跨域情况请求都没有打入到服务器。为什么请求都没有打入到服务器,浏览器就报出跨域?跨域应该是请求可以打入服务器,并且服务器也可以做出响应,只不过浏览器拿到数据后,发现你的原始路径和目标路径跨域,最终才会在控制台上提示跨域啊?可是这里后端服务器都没有接收到请求,浏览器就先提示了跨域?我实在不理解。
我直接将后端http自动监听80重定向https的配置关了。前端发请求直接填写https://ip地址:服务器端口/...发现正常请求,正常响应。不管Java后端采用jsonp还是crosfilter都能处理!