HTTPS实际上是有两部分组成:HTTP + SSL / TLS,java
也就是在HTTP上又加了一层处理加密信息的模块,而且会进行身份的验证。web
如何进行身份验证?算法
首先咱们要明白什么是对称加密,什么是非堆成加密浏览器
对称加密就是只有一个密钥,客户端双方按照约定的密钥对本身的明文进行加密。tomcat
可是这种方式有个很很差的状况。A和B通信以前并不知道使用哪一种密钥加密。因此在第一次通信的时候会事先沟通好。安全
A->B:嗨!在吗?咱们开始聊天吧。 B->A:好的,咱们的密钥是:xxxxx。
若是此时黑客截取到了你的密钥,那加密也无济于事。服务器
非对称加密就是在对称加密上再套一层公钥。因此有公钥和私钥两种形式。ide
A->B:嗨!在吗?咱们开始聊天吧。 B->A:好的,咱们的公钥是:xx。 A->B(以公钥:xx加密): 你好我是A,咱们以后使用对称加密的zz来通信。 B:以xx的密钥解密,获得密钥zz,以后双方通信都经过对称加密的zz来通信。
公钥是公开的,用公钥加密的信息只能使用密钥解密。公钥是解不开的,即使公钥被非法路由或黑客拦截,也不能经过公钥解密。这就是数学的魅力,有兴趣的话能够了解一下:RSA算法工具
这样就安全了?答案是否认的,若是在B->A发送公钥 xx 的时候就已经被非法路由器或者黑客拦截,而后向A发送偷天换往后的公钥 yy。此时非法路由就有两个公钥 xx 和 yy 。而且拥有有 yy 的私钥,由于 yy 是其本身生成的。网站
所以,当A收到非法路由发送过来的偷天换往后的公钥 yy ,A信觉得真的认为这个就是B发送过来的公钥。当A向B发送发送一串由 YY 公钥加密的信息,非法路将其拦截而且用 yy 的密钥解密后再经过公钥 xx 加密后发送给B。这样你的消息通信依旧是不安全的。
上面这个环节按理来讲已经很安全了,为何仍是会被黑客或者非法路由攻击?思考上面的环节,问题出在发送公钥的时候,被黑客拦截,而后偷天换日的换了一个公钥。那是否是只要保证公钥的不可更改,就能维护了呢?是的,证书的出现就是解决这个问题(也是为何你要去找证书签发机构花钱购买证书的缘由)!!
简单来讲,一个HTTPS网站响应给咱们的并非一个公钥,而是证书。证书上包含了公钥,还包含了域名、签发机构、有效期、签名等等。
那证书的安全性怎么保证?为何中间人不能作一个假证书?
由于这套证书体系已经根植于每个操做系统里了。每个操做系统里,都内置了数十张根证书,每一个根证书都对应一个很是权威的证书签发机构。这些根证书上记录了各个机构的公钥。
那非法路由或者黑客能不能申请一个真的证书而后去作劫持呢?
一般来讲,证书签发机构的审核很是严格,若是没法证实B这个域名属于他,签发机构是不会给他签发一个知乎域名的证书的。而若是中间人用了其余域名的证书,浏览器会发现你请求的域名和返回的证书不一致,从而拒绝继续请求。除非你必定要点下面的「仍然继续」:
最后无奈地说,在破解了这么多数学上的难题后,HTTPS的安全性仍然保证在『证书签发机构必定都是颇有良心的』这种脆弱的基础上。(即使一些网站是经过证书签发机构的,可是嘛依旧会被植入小广告,咳咳....)。
咱们了解了https和证书的做用。其实咱们在系统之间内部通信的时候就可使用对称加密的方式进行访问便可。
由于是内部嘛,咱们提早约定好使用何种证书就能够了。除非是很正式的项目,不然使用本身签发的证书便可,由于官方生成证书是要花钱滴。
有两种方式
第一种:服务端生成一个证书,每一个客户端都生成本身的证书,而后让服务端与各个客户端相互信任。
第二种:生成一个证书,将这个证书派发给各个客户端,每一个客户端携带该证书就会被服务端认证(这种安全性稍微低一些,可是在大部分对安全性要求不是特别高的场景推荐使用。下面主要说明这一种方式,若是想实现第一种参考:https://blog.csdn.net/u011350541/article/details/71941536)
首先保证服务器有jdk,打开CMD工具,进入到jdk的bin目录下输入一下信息。若是配置了环境变量则直接在命令行中输入便可。
keytool -genkey -alias tomcat -keypass 123456 -keyalg RSA -keysize 1024 -validity 365 -keystore D:/keys/server.jks -storepass 123456
上述参数的具体说明以下:
keytool -genkey -alias service(别名) -keypass 123456(别名密码) -keyalg RSA(算法) -keysize 1024(密钥长度) -validity 365(有效期,天单位) -keystore D:/keys/server.jks(指定生成证书的位置和证书名称) -storepass 123456(获取jks信息的密码)
/** * @author Eric * @Title: SoapService * @date 2019/7/17 10:42 * @Description: 发布的soap接口,注意注释的使用 */ @WebService public interface SoapService { void sayHello(@WebParam(name = "clientName") String clientName); }
/** * @author Eric * @Title: SoapServiceImpl * @date 2019/7/17 10:42 * @Description: soap接口的具体实现,注意注释的使用 */ @javax.jws.WebService public class SoapServiceImpl implements SoapService { @Override public void sayHello(String clientName) { System.out.println(clientName + "调用接口打了招呼"); } }
/** * @author Eric * @Title: testTest * @date 2019/7/17 10:45 * @Description: 发布soap接口 */ public class Release { public static void main(String[] args) throws Exception { initSoap(); } //初始化soap接口 public static void initSoap() { try { String host = "0.0.0.0"; int port = 8888; String address = "https://" + host + ":" + port + "/logProcessor"; //发布于https JaxWsServerFactoryBean sf = new JaxWsServerFactoryBean(); sf.setServiceClass(SoapService.class); //发布实现soap的接口类(你本身实现的接口,里面的方法就是发布的soap接口) sf.setAddress(address); SoapServiceImpl soapServiceImpl = new SoapServiceImpl(); //SoapService的实现类 sf.getServiceFactory().setInvoker(new BeanInvoker(soapServiceImpl)); sf = configureSSLOnTheServer(sf, port); Server server = sf.create(); String endpoint = server.getEndpoint().getEndpointInfo().getAddress(); System.out.println("soap发布的地址为:" + endpoint); } catch (Exception e) { System.out.println("Soap初始化失败:"+e); } } //https而且开启客户端认证。若是发布的接口是http,则无需实现该方法。 private static JaxWsServerFactoryBean configureSSLOnTheServer(JaxWsServerFactoryBean sf, int port) throws Exception { TLSServerParameters tlsParams = new TLSServerParameters(); ClientAuthentication clientAuthentication = new ClientAuthentication(); clientAuthentication.setRequired(true); //开启客户端认证 tlsParams.setClientAuthentication(clientAuthentication); KeyStore keyStore = KeyStore.getInstance("JKS"); String password = "123456"; //生成证书时候定义的的密码 File truststore = new File(Paths.get("D:\\keys", "server.jks").toString()); keyStore.load(new FileInputStream(truststore), password.toCharArray()); KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); keyFactory.init(keyStore, password.toCharArray()); KeyManager[] km = keyFactory.getKeyManagers(); tlsParams.setKeyManagers(km); truststore = new File(Paths.get("D:\\keys", "server.jks").toString()); keyStore.load(new FileInputStream(truststore), password.toCharArray()); TrustManagerFactory trustFactory = TrustManagerFactory .getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustFactory.init(keyStore); TrustManager[] tm = trustFactory.getTrustManagers(); tlsParams.setTrustManagers(tm); JettyHTTPServerEngineFactory factory = new JettyHTTPServerEngineFactory(); factory.setTLSServerParametersForPort(port, tlsParams); } }
经过上述代码,咱们将接口发布在了你本身定义的https://0.0.0.0:8888/logProcessor。若是发布成功,咱们想远程调用soap接口,此时打开soapUI
https://zhuanlan.zhihu.com/p/37738632 https://blog.csdn.net/u011350541/article/details/71941536