012 提供Https支持(2017.06.22更新)

012 提供Https支持(2017.06.22更新)

更新了关于生成证书的部分,添加了参数,详见下面生成证书部分

视频发布在youtube上面了
https://youtu.be/fnxF0kXVEJQ
优酷上面的链接
http://v.youku.com/v_show/id_XMjgzOTg5MDgwNA==.html?f=49760672

HTTPS(全称:Hypertext Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。

HTTPS的作用
确认网站的真实性:通过权威机构的证书来证明
保证数据传输的安全:客户端产生一个对称的密钥,通过服务器的证书来交换密钥,之后的数据使用密钥加密之后传输。

双向认证 SSL 协议的具体过程
  ① 浏览器发送一个连接请求给安全服务器。
  ② 服务器将自己的证书,以及同证书相关的信息发送给客户浏览器。
  ③ 客户浏览器检查服务器送过来的证书是否是由自己信赖的 CA 中心所签发的。如果是,就继续执行协议;如果不是,客户浏览器就给客户一个警告消息:警告客户这个证书不是可以信赖的,询问客户是否需要继续。
  ④ 接着客户浏览器比较证书里的消息,例如域名和公钥,与服务器刚刚发送的相关消息是否一致,如果是一致的,客户浏览器认可这个服务器的合法身份。
  ⑤ 服务器要求客户发送客户自己的证书。收到后,服务器验证客户的证书,如果没有通过验证,拒绝连接;如果通过验证,服务器获得用户的公钥。
  ⑥ 客户浏览器告诉服务器自己所能够支持的通讯对称密码方案。
  ⑦ 服务器从客户发送过来的密码方案中,选择一种加密程度最高的密码方案,用客户的公钥加过密后通知浏览器。
  ⑧ 浏览器针对这个密码方案,选择一个通话密钥,接着用服务器的公钥加过密后发送给服务器。
  ⑨ 服务器接收到浏览器送过来的消息,用自己的私钥解密,获得通话密钥。
  ⑩ 服务器、浏览器接下来的通讯都是用对称密码方案,对称密钥是加过密的。

Java提供相对简单的被称为keytool的命令行工具,可以简单地产生“自己签名”的证书。自己签名的证书只是用户产生的证书,没有正式在大家所熟知的认证权威那里注册过,因此不能确保它的真实性。但却能保证数据传输的安全性。
下面是官方网址
http://docs.oracle.com/javase/7/docs/technotes/tools/solaris/keytool.html

生成证书
-dname属性说明
CN=cName, OU=orgUnit, O=org, L=city, S=state, C=countryCode

参数说明
CN个人名字,例如:”Susan Jones”
OU短的组织名字,例如:”Purchasing”
O长的组织名字,例如:”ABCSystems, Inc.”
L本地(城市)名字,例如:”Palo Alto”
S省名字,例如:”California”
C两位国家代码,例如:中国是“CN”

这里增加了-ext参数,不然会出现http://localhost:8190/template可以访问。但是http://127.0.0.1:8190/template 不能访问的问题。

1 、生成服务器证书库
keytool -validity 365 -genkeypair -v -alias server -keyalg RSA -keysize 2048 -keystore /Users/zhengjun/Documents/java_library/server.keystore -dname "CN=server,OU=Demo,O=Https Demo,L=Pudong,S=Shanghai,c=CN" -storepass 111111 -keypass 111111 -ext SAN=DNS:localhost,IP:127.0.0.1
2 、生成客户端证书库
keytool -validity 365 -genkeypair -v -alias client -keyalg RSA -keysize 2048 -storetype PKCS12 -keystore /Users/zhengjun/Documents/java_library/client.p12 -dname "CN=client,OU=Demo,O=Https Demo,L=Pudong,S=Shanghai,c=CN" -storepass 222222 -keypass 222222 -ext SAN=DNS:localhost,IP:127.0.0.1
3 、从客户端证书库中导出客户端证书
keytool -export -v -alias client -keystore /Users/zhengjun/Documents/java_library/client.p12 -storetype PKCS12 -storepass 222222 -rfc -file /Users/zhengjun/Documents/java_library/client.cer
4 、从服务器证书库中导出服务器证书
keytool -export -v -alias server -keystore /Users/zhengjun/Documents/java_library/server.keystore -storepass 111111 -rfc -file /Users/zhengjun/Documents/java_library/server.cer
5 、生成客户端信任证书库(由服务端证书生成的证书库)
keytool -import -v -alias server -file /Users/zhengjun/Documents/java_library/server.cer -keystore /Users/zhengjun/Documents/java_library/client.truststore -storepass 222222
6 、将客户端证书导入到服务器证书库(使得服务器信任客户端证书)
keytool -import -v -alias client -file /Users/zhengjun/Documents/java_library/client.cer -keystore /Users/zhengjun/Documents/java_library/server.keystore -storepass 111111
7 、查看证书库中的全部证书
keytool -list -keystore /Users/zhengjun/Documents/java_library/server.keystore -storepass 111111

mac下面如果keychain里面没有证书,可以手动导入进去.File-import items选择*.p12那个,需要输入生成证书时指定的密码。

配置tomcat中conf下的server.xml文件

<!-- Define a SSL/TLS HTTP/1.1 Connector on port 8443
    This connector uses the NIO implementation that requires the JSSE
    style configuration. When using the APR/native implementation, the
    OpenSSL style configuration is required as described in the APR/native
    documentation -->

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
          maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
          clientAuth="false" sslProtocol="SSL" 
          keystoreFile="/Users/zhengjun/Documents/java_library/server.keystore" keystorePass="111111"
    truststoreFile="/Users/zhengjun/Documents/java_library/server.keystore" truststorePass="111111"/>
字段说明
keystoreFile指定服务器密钥库,如“/opt/web/ssl/server.keystore”
keystorePass密钥库生成时的密码
truststoreFile受信任密钥库,和密钥库相同即可
truststorePass受信任密钥库密码

需要说明的是,修改TOMCAT的server.xml文件,如果是ECLIPSE中建的服务器,不会有效果,需要删除服务器重新建个服务器。配置好后重启tomcat就可以访问

配置web.xml去掉默认主页支持,交给spring mvc controller处理,配置SSL参数

<!-- 强制SSL配置,即普通的请求也会重定向为SSL请求 -->
<security-constraint>
   <web-resource-collection>
       <web-resource-name>SSL</web-resource-name>
       <url-pattern>/*</url-pattern> <!-- 全站使用SSL -->
   </web-resource-collection>
   <user-data-constraint>
       <description>SSL required</description>
       <!-- CONFIDENTIAL: 要保证服务器和客户端之间传输的数据不能够被修改,且不能被第三方查看到 -->
       <!-- INTEGRAL: 要保证服务器和client之间传输的数据不能够被修改 -->
       <!-- NONE: 指示容器必须能够在任一的连接上提供数据。(即用HTTP或HTTPS,由客户端来决定) -->
       <transport-guarantee>CONFIDENTIAL</transport-guarantee>
   </user-data-constraint>
</security-constraint>

<welcome-file-list>  
    <welcome-file></welcome-file>  
</welcome-file-list>  

在controller里面添加一个处理主页信息的
AdminController

@Controller
public class AdminController
{
    private static final Logger logger = LogManager.getLogger(AdminController.class.getName());

    @RequestMapping("/")
    public String index(ServletRequest req, ServletResponse res)
    {
        logger.info("controller index enter.");

        return "login";
    }

    @RequestMapping(value = "/v1/login", method = RequestMethod.POST)
    public String loginProc(ServletRequest req, ServletResponse res)
    {
        logger.info("controller loginProc enter.");

        return "main";
    }

}

现在通过wireshark抓包就看不出来具体的信息了。

这里因为是自签名所以chrome不信任这个证书,虽然是https,但是被划掉了。

那么如何使证书受信任呢?这就需要专门的权威部门来签发给你证书。这些机构称为CA,由于CA的信息已经被集成在操作系统中了,所以这些颁发证书的CA机构是操作系统可信的。操作系统检测到证书的颁发者是可信的时候,就会信任此证书。
也可以自己充当CA机构来签发证书,该CA所签发的证书只能本机可信。过程如下:
1.首先将CA信息安装到操作系统,使操作系统对该CA可信。
安装server.cer到操作系统,过程默认。
2.使用该CA来签发证书。
可以使用openssl来签发数字证书,这里用的是JAVA程序来签发证书的。

在网上找了一个登陆页面,加入工程
views/login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <title>HTML5/CSS3登录表单DEMO演示</title>
    <script type="text/javascript" charset="UTF-8" src="resources/js/prefixfree.min.js"></script>
<style type="text/css">
/**
 * 使用属性选择器 隐藏所有的checkboxes
 */
input[type=checkbox] {
    visibility: hidden;
}
body {
   background: url(resources/images/bg.png);
   background-size: 100% 100%;
   margin:0;
   padding:0;}
.content {
    width:600px;
    height:350px;
    margin:50px auto 10px auto;
}
.login-form {
    width:400px;
    height:177px;
    margin:70px auto 0;
    padding-top:73px;
    position:relative;
    background-image:-*-linear-gradient(top,rgb(255,255,255),rgb(242,242,242));
    box-shadow:0 3px 3px rgba(21,62,78,0.8);
}
.login-form:before {
    content:"";
    position:absolute;
    top:-50px;
    left:150px;
    width:102px;
    height:102px;
    padding:2px;
    border:1px solid rgb(216,216,219);
    background:#fff url("resources/images/profilepicture.jpg") no-repeat 2px 2px;
}
.not-registered {
    position:absolute;
    color:rgb(153,153,153);
    font-weight:bold;
    font-size:13px;
    top:calc(100% + 20px);
    background-color:rgb(255,255,255);
    width:400px;
    height:46px;
    margin:0 auto;
    line-height:46px;
    text-align: center;
    box-shadow:0 3px 3px rgba(21,62,78,0.8);
}
.not-registered a {
    margin-left:5px;
    text-decoration: none;
    color:rgb(52,119,182);
    cursor: pointer;
}
.login-form div {
    width:216px;
    height:28px;
    margin:20px auto;
    position:relative;
    line-height:28px;
    border:none;
}
.login-form .user-icon, 
.login-form .password-icon {
    display:inline-block;
    font-family: 'loginform-icon';
    font-size:15px;
    text-align:center;
    line-height:28px;
    color:rgb(153,153,153);
    position:absolute;
    left:1px;
    top:1px;
    background-color:rgb(255,255,255);
    border:none;
    border-right:1px solid rgb(229,229,232);
    width:30px;
    height:28px;
    transition: all 300ms linear;
}
.login-form .username input, .login-form .password input {
    height:100%;
    width:calc(100% - 40px);
    padding-left:40px;
    border-radius:2px;
    border:1px solid;
    border-color:rgb(229,229,232) rgb(220,220,221) rgb(213,213,213) rgb(220,220,221);
    display:block;
    transition: all 300ms linear;
}

.login-form .icon:before, .login-form .icon:after {
    content:"";
    position:absolute;
    top:10px;
    left:30px;
    width:0;
    height:0;
    border:4px solid transparent;
    border-left-color:rgb(255,255,255);
}
.login-form .icon:before {
    top:9px;
    border:5px solid transparent;
    border-left-color:rgb(229,229,232);
}
.login-form .username input:focus, .login-form .password input:focus {
    border-color:rgb(69,153,228);
    box-shadow:0 0 2px 1px rgb(200,223,244);
}
.login-form .username input:focus + span, .login-form .password input:focus + span {
    background:-*-linear-gradient(top,rgb(255,255,255),rgb(245,245,245));
    color:rgb(51,51,51);
}
.login-form .username input:focus + span:after, .login-form .password input:focus + span:after {
    border-left-color:rgb(250,250,250);
}

.login-form .account-control label {
    margin-left:24px;
    font-size:12px;
    font-family: Arial, Helvetica, sans-serif;
    cursor:pointer;
}
.login-form button[type="submit"] {
    color:#fff;
    font-weight:bold;
    float:right;
    width:68px;
    height:30px;
    position:relative;
    background:-*-linear-gradient(top,rgb(74,162,241),rgb(52,119,182)) 1px 0 no-repeat,
               -*-linear-gradient(top,rgb(52,118,181),rgb(36,90,141)) left top no-repeat;
    background-size:66px 28px,68px 29px;
    border:none;
    border-top:1px solid rgb(52,118,181);
    border-radius:2px;
    box-shadow:inset 0 1px 0 rgb(86,174,251);
    text-shadow:0 1px 1px rgb(51,113,173);
    transition: all 200ms linear;
}
.login-form button[type="submit"]:hover {
    text-shadow:0 0 2px rgb(255,255,255);
    box-shadow:inset 0 1px 0 rgb(86,174,251),0 0 10px 3px rgba(74,162,241,0.5);
}
.login-form button[type="submit"]:active {
    background:-*-linear-gradient(top,rgb(52,119,182),rgb(74,162,241)) 1px 0 no-repeat,
               -*-linear-gradient(top,rgb(52,118,181),rgb(36,90,141)) left top no-repeat;
}

.login-form .account-control input {
    width:0px;
    height:0px;
}
.login-form label.check {
    position:absolute;
    left:0;
    top:50%;
    margin:-8px 0;
    display:inline-block;
    width:16px;
    height:16px;
    line-height: 16px;
    text-align:center;
    border-radius:2px;
    background:-*-linear-gradient(top,rgb(255,255,255),rgb(246,246,246)) 1px 1px no-repeat,
               -*-linear-gradient(top,rgb(227,227,230),rgb(165,165,165)) left top no-repeat;
    background-size:14px 14px,16px 16px;
}
.login-form .account-control input:checked + label.check:before {
    content:attr(data-on);
    font-family:loginform-icon;
}
@font-face {
  font-family: 'loginform-icon';
  src: url("resources/font/loginform-icon.eot");
  src: url("resources/font/loginform-icon.eot?#iefix") format('embedded-opentype'),
       url("resources/font/loginform-icon.woff") format('woff'),
       url("resources/font/loginform-icon.ttf") format('truetype'),
       url("resources/font/loginform-icon.svg#loginform-icon") format('svg');
  font-weight: normal;
  font-style: normal;
}
</style>
<script type="text/javascript">  
function doLogin() {
    var password = hex_md5($("#password").val());
    document.getElementById("form1").submit();
}
</script> 
</head>
<body>

       <div class="content">
           <form action="v1/login" method="post" class="login-form">
               <div class="username">
                   <input type="text" name="username" placeholder="user@gmail.com" autocomplete="on" />
                   <span class="user-icon icon">u</span>
               </div>
               <div class="password">
                   <input type="password" name="password" placeholder="********" />
                   <span class="password-icon icon">p</span>
               </div>
               <div class="account-control">
                   <input type="checkbox" name="Remember me" id="Remember me" value="Remember me" checked="checked" />
                   <label for="Remember me" data-on="c" class="check"></label>
                   <label for="Remember me" class="info">Remember me</label>
                   <button type="submit" onclick="doLogin();">Login</button>
               </div>
               <p class="not-registered">Not a registered user yet?<a>Sign up now!</a></p>
           </form>
       </div>

</body>
</html>

这里css样式没有使用外部链接的方式,因为那样加载页面的时候能看出来样式的改变,比较慢。

images添加图片
font添加字体
js添加脚本

添加一个main.jsp作为登录成功之后的主页。
简单的打个信息<h3>Main Page</h3>

现在应该可以看到登录页面了,点击Login可以跳转到主页。具体的验证功能下次再弄吧。这次到这里了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值