1.1 生成keystore文件及导出证书
步奏1:打开控制台,运行:
%JAVA_HOME%inkeytool -genkey -alias tomcat -keyalg RSA
(如果你已经配置过javahome,直接输入)
keytool -genkey -alias tomcat -keyalg RSA
首先会要求输入密码,这里使用123123
步奏2:输入基本信息 (除了名称与姓氏其他都可以直接回车)
输入密钥库口令: 再次输入新口令: 您的名字与姓氏是什么? [Unknown]: tuhao(这里可以输入你的项目的域名:如localhost) 您的组织单位名称是什么? [Unknown]: tuhaojia 您的组织名称是什么? [Unknown]: fnic 您所在的城市或区域名称是什么? [Unknown]: didu 您所在的省/市/自治区名称是什么? [Unknown]: didu 该单位的双字母国家/地区代码是什么? [Unknown]: cn CN=tuhao, OU=tuhaojia, O=fnic, L=didu, ST=didu, C=cn是否正确? [否]: y
之后输入 <tomcat> 的密钥口令 (如果和密钥库口令相同, 按回车):
步奏3:拷贝keystore文件
完毕后会在当前目录下,会产生一个:.keystore文件,window系统默认在“C:Users你机器的名称” 下,将它拷贝到tomcat的bin目录下。
步奏4:导出证书
从控制台进入tomcat的bin目录,本机环境是:D:Tomcat7in> ,然后输入:
D:Tomcat7in>keytool -selfcert -alias tomcat -keystore .keystore
D:Tomcat7in>keytool -export -alias tomcat -keystore .keystore -storepass 你的密码(这里是123123) -rfc -file tomcat.cer
此时会在D:Tomcat7in>下生成tomcat.cer证书文件。
1.2 配置tomcat
步奏1:
打开tomcat目录下的/conf/server.xml 找到“SSL HTTP/1.1 Connector” 那一块,取消注释并将它改成:
<Connector port="443" protocol="org.apache.coyote.http11.Http11Protocol"
maxThreads="150" SSLEnabled="true" scheme="https" secure="true"
keystoreFile="bin/.keystore" keystorePass="123123"
clientAuth="false" sslProtocol="TLS"/>
请注意,这里我已经将tomcat的端口改成了80,相应的,https的端口我也改成了443(即默认的https端口)。
接下来重启tomcat,用https:// localhost/访问网站验证一下就行了。
可选步奏:
在tomcat的conf目录下的web.xml文件下配置以下内容则可以强制让整个项目使用https访问,请根据需求配置。
<security-constraint> <web-resource-collection > <web-resource-name >SSL</web-resource-name> <url-pattern>/*</url-pattern> </web-resource-collection> <user-data-constraint> <transport-guarantee>CONFIDENTIAL</transport-guarantee> </user-data-constraint> </security-constraint>
3 创建项目访问
注意:从https下的链接跳转到http的连接会造成session丢失,原因在于tomcat会给不同协议的请求创建不同的cookie
,并生成不同的sessionid,所以造成与服务端的session索引失败而无法获取session数据。
解决方法:可以编写一个过滤器,对所有的请求做处理,如果session是新的https session,则创建一个JSESSIONID cookie,
并设置到Servlet Response中,这样就突破了tomcat的限制,把https下的session传递到http协议下
3.1 建立Wrapper类,用于处理所有的Serverlet Request:
import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; //处理所有的Serverlet Request public class MyRequestWrapper extends HttpServletRequestWrapper { private HttpServletResponse response = null; public MyRequestWrapper(HttpServletRequest request) { super(request); } public void setResponse(HttpServletResponse response) { this.response = response; } public HttpSession getSession() { HttpSession session = super.getSession(); processSessionCookie(session); return session; } public HttpSession getSession(boolean create) { HttpSession session = super.getSession(create); processSessionCookie(session); return session; } /** * 当从https重定向到http时,tomcat会创建一个新的sessionid,所以造成session跟踪不到, * 这里获取先从cookie中获取sessionid,保存到新的cookie * @param session */ private void processSessionCookie(HttpSession session) { if (null == response || null == session) { // No response or session object attached, skip the pre processing return; } // cookieOverWritten - 用于过滤多个Set-Cookie头的标志 Object cookieOverWritten = getAttribute("COOKIE_OVERWRITTEN_FLAG"); if (null == cookieOverWritten && isSecure() && isRequestedSessionIdFromCookie() && session.isNew()) { // 当是https协议,且新session时,创建JSESSIONID cookie以欺骗浏览器 Cookie cookie = new Cookie("JSESSIONID", session.getId()); cookie.setMaxAge(-1); // 有效时间为浏览器打开或超时 String contextPath = getContextPath(); if ((contextPath != null) && (contextPath.length() > 0)) { cookie.setPath(contextPath); } else { cookie.setPath("/"); } response.addCookie(cookie); // 增加一个Set-Cookie头到response setAttribute("COOKIE_OVERWRITTEN_FLAG", "true");// 过滤多个Set-Cookie头的标志 } } }
3.2 再把上述Wrapper类与Filter建立关联:
import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class HttpsFilter implements Filter { @Override public void destroy() { // TODO Auto-generated method stub } @Override public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest)req; HttpServletResponse response = (HttpServletResponse)resp; MyRequestWrapper myrequest = new MyRequestWrapper(request); myrequest.setResponse(response); chain.doFilter(myrequest, response); } @Override public void init(FilterConfig arg0) throws ServletException { // TODO Auto-generated method stub } }
3.3 控制层执行代码
import java.io.IOException; import java.util.UUID; import javax.servlet.ServletException; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import entity.User; public class AdminServlet extends HttpServlet { /** * */ private static final long serialVersionUID = 7179221326322012461L; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String action = request.getParameter("action"); if("login".equals(action)){ login(request,response); } else if("index".equals(action)){ index(request, response); } else if("httplink".equals(action)){ httplink(request,response); } else if("tohttps".equals(action)){ tohttps(request,response); } else if("httpslink".equals(action)){ httpslink(request,response); } else if("tohttp".equals(action)){ tohttp(request,response); } } public void login(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException{ /*Cookie cookie = new Cookie("JSESSIONID", request.getSession().getId()); response.addCookie(cookie); // */ response.setContentType("text/html;charset=utf-8"); String username = request.getParameter("username"); String password = request.getParameter("password"); User user = new User(); user.setId(UUID.randomUUID().toString().replaceAll("-", "")); user.setUserName(username); user.setPassword(password); request.getSession().setAttribute("user", user); System.out.println(request.getRequestURI()); System.out.println(request.getRequestURL()); System.out.println(request.getContextPath()); System.out.println(request.getLocalName()); System.out.println(request.getLocalPort()); //重定向到http response.sendRedirect("http://"+request.getServerName()+":"+"80"+request.getContextPath()+"/admin?action=index"); } public void index(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException{ request.getRequestDispatcher("/WEB-INF/page/index.jsp").forward(request, response); System.out.println("主页的sessionid:"+request.getSession(false).getId()); Cookie[] cookies = request.getCookies(); for (Cookie c : cookies) { if (c.getName().equalsIgnoreCase("JSESSIONID")) { System.out.println("cookie中的sessionid:"+c.getValue()); } } } public void httpslink(HttpServletRequest request,HttpServletResponse response) throws IOException{ response.sendRedirect("https://"+request.getServerName()+request.getContextPath()+"/admin?action=tohttps"); } public void tohttps(HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException{ request.getRequestDispatcher("/WEB-INF/page/https.jsp").forward(request, response); System.out.println("https页面的sessionid:"+request.getSession(false).getId()); Cookie[] cookies = request.getCookies(); for (Cookie c : cookies) { if (c.getName().equalsIgnoreCase("JSESSIONID")) { System.out.println("cookie中的sessionid:"+c.getValue()); } } } public void httplink(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException{ response.sendRedirect("http://"+request.getServerName()+":"+"80"+request.getContextPath()+"/admin?action=tohttp"); } public void tohttp(HttpServletRequest request,HttpServletResponse response) throws IOException, ServletException{ request.getRequestDispatcher("/WEB-INF/page/index.jsp").forward(request, response); System.out.println("http页面的sessionid:"+request.getSession(false).getId()); Cookie[] cookies = request.getCookies(); for (Cookie c : cookies) { if (c.getName().equalsIgnoreCase("JSESSIONID")) { System.out.println("cookie中的sessionid:"+c.getValue()); } } } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
3.4 页面代码
login.jsp
<body> <form action="${pageContext.request.contextPath}/admin?action=login" method="post"> 账号:<input id="username" name="username" type="text" ><br/> 密码:<input id="password" name="password" type="text" ><br/> <input id="btn" type="submit" value="登录"> </form> <script type="text/javascript"> //强制让页面发送https请求 var targetProtocol = "https:"; if (window.location.protocol != targetProtocol) window.location.href = targetProtocol + window.location.href.substring(window.location.protocol.length); </script> </body>
index.jsp
<body> <table> <tr> <th>id:</th> <th>账号:</th> <th>密码:</th> </tr> <tr> <td>${sessionScope.user.id}</td> <td>${sessionScope.user.userName}</td> <td>${sessionScope.user.password}</td> </tr> </table> <a href="${pageContext.request.contextPath}/admin?action=httpslink" >跳转到https</a> </body>
https.jsp
<body> <table> <tr> <th>id:</th> <th>账号:</th> <th>密码:</th> </tr> <tr> <td>${sessionScope.user.id}</td> <td>${sessionScope.user.userName}</td> <td>${sessionScope.user.password}</td> </tr> </table> <a href="${pageContext.request.contextPath}/admin?action=httplink" >跳转到http</a> </body>