内置Jetty HTTPS启动使用request.getScheme()总是返回http问题解决方案

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xiaozaq/article/details/85341914

现象:

        不论是http还是https访问时,通过request.getScheme()获取的值都是http。

环境:

        内置Jetty启动项目

        同时启动http与https访问。内置Jetty HTTPS启动

        jetty版本:9.4.9.v20180320

由于最近升级了https服务。导致系统原来的重定向功能出现了问题。

之前如果用户未登录,会重新定向到登录页面,登录成功后返回原页面。用户登录后重定向到原来访问页面

inv.getController().redirect("/xpl/admin/login"+"?toUrl=" + toUrl);  

但是使用https后,发现了一个新问题,上面默认重定向时总是使用http协议,导致重定向失败,提示:

Mixed Content: The page at 'https://localhost:9443/xpl/admin/main' was loaded over HTTPS, but requested an insecure resource 'http://localhost:9443/xpl/admin/login?toUrl=%2Fxpl%2Fadmin%2Fuser'. This request has been blocked; the content must be served over HTTPS.

而使用request.getScheme()又无法获取到正确的协议名称。

这个问题纠结了很久,昨天网上搜了很久的资料也没找到相关资料。

今天研究了一整天的jetty源码。终于找到获取到正确协议方法了。

具体过程就不详细描述了。直接给出解决方案吧:

第一步,定义下面函数获取Scheme。

/***
	 * 获取请求协议
	 * @return http 或者 https 或者 null
	 */
	public static String getScheme(){
		if(HttpConnection.getCurrentConnection() == null){
			return null;
		}
		return HttpConnection.getCurrentConnection().getHttpConfiguration().getSecureScheme();
	}

用户请求时,jetty会把创建的HttpConnection绑定到本地线程。

通过HttpConnection获取对应的HttpConfiguration,然后获取到SecureScheme。

第二步,启动jetty时,配置正确的HttpConfiguration。

由于HttpConfiguration的构造函数默认创建的SecureScheme值是https。

server = new Server( port );

替换为:

server = new Server();
HttpConfiguration.setSecureScheme(HttpScheme.HTTP.asString());
ServerConnector connector=new ServerConnector(server,null,null,null,-1,-1,new HttpConnectionFactory(HttpConfiguration));
connector.setPort( port );
server.setConnectors(new Connector[]{connector});

第三步,重定向时路径加上协议名称。

/***
	 * 获取协议,域名,端口号
	 * @param request
	 * @return 例如:http://f0rb.iteye.com:8080/ 
	 */
	public static String getDomain(HttpServletRequest request){
		StringBuffer url = request.getRequestURL();  
		String domain = url.delete(url.length() - request.getRequestURI().length(), url.length()).append("/").toString();
		if("https".equals(getScheme())){
			domain = domain.replace("http", "https");
		}
		return domain;
	}
inv.getController().redirect(domain + "xpl/admin/login?toUrl=" + toUrl);

打完收工。

PS:改完后发现http和https是共用session的。https登录后,使用http就可以不用登录,继续访问了。

这个我一直认为http和https是属于跨域的,应该不是同一个session啊。

这个原理还没搞懂,以后有时间再研究。谁知道的告诉我下,万分感谢!

猜你喜欢

转载自blog.csdn.net/xiaozaq/article/details/85341914