论坛首页 编程语言技术论坛

HttpURLConnection模拟URL请求的一个问题

浏览 5473 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2013-04-01  

 

   在使用CAS Server进行单点退出的实验时,一直不成功,最终跟终到的代码是cas server通过HttpURLConnection模拟了一个对客户端应用的POST请求,通过代码的调试发现,问题就出现在POST请求这里,客户端应用的SingleSignOutFilter过滤器接收到了这个请求,但是得到的请求却是GET请求,并且得不到所需的参数值。

   为了进一步进行调试,把cas server中的请求过程拿出来做了一个测试类,如下:

public class TestConn {
	public static void main(String[] args) {
		String message = "<samlp:LogoutRequest xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" ID=\"LR-8-3iFpmqdWBa5MAh2VW5u5FiPYvoOu2MOSe7q\" Version=\"2.0\" IssueInstant=\"2013-04-01T15:42:45Z\"><saml:NameID xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">@NOT_USED@</saml:NameID><samlp:SessionIndex>ST-8-2PZRjTcDPWeBc6X4TVb6-cas</samlp:SessionIndex></samlp:LogoutRequest>";
		String url = "http://localhost:8880/web";
		int readTimeout = 50000;
		int connectionTimeout = 50000;
		HttpURLConnection connection = null;
		BufferedReader in = null;
		try {
			final URL logoutUrl = new URL(url);
			final String output = "logoutRequest="
					+ URLEncoder.encode(message, "UTF-8");

			connection = (HttpURLConnection) logoutUrl.openConnection();
			connection.setRequestMethod("POST");
			connection.setDoInput(true);
			connection.setDoOutput(true);
			connection.setUseCaches(false);
			connection.setReadTimeout(readTimeout);
			connection.setConnectTimeout(connectionTimeout);
			connection.setRequestProperty("Content-Length",
					Integer.toString(output.getBytes().length));
			connection.setRequestProperty("Content-Type",
					"application/x-www-form-urlencoded");
			final DataOutputStream printout = new DataOutputStream(
					connection.getOutputStream());
			printout.writeBytes(output);
			printout.flush();
			printout.close();

			in = new BufferedReader(new InputStreamReader(
					connection.getInputStream()));

			while (in.readLine() != null) {
				// nothing to do
			}

		} catch (final SocketTimeoutException e) {
			e.printStackTrace();
		} catch (final Exception e) {
			e.printStackTrace();
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (final IOException e) {
					// can't do anything
				}
			}
			if (connection != null) {
				connection.disconnect();
			}
		}
	}
}

   这里的http://localhost:8880/web也配置了一个filter,内容如下:

@Override
	public void doFilter(ServletRequest req, ServletResponse res,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest request = (HttpServletRequest) req;
		System.out.println(request.getMethod());
		System.out.println(request.getParameter("logoutRequest"));
		chain.doFilter(req, res);
	}

   运行测试程序,在web端的控制台上面输出的内容为:

写道
GET
null

   得到这样的一个结果,实在是相当意外,这里测试程序里面可以看到,请求方法已经改为了POST,得到的却是GET请求。还以为是JDK的BUG,于是依次换成jdk1.5 1.6 1.7,多次进行测试,结果依旧。

   终于,功夫不负苦心人,楼主一个不经意的举动换来了意想不到的收获,我把这里请求的URL不小心改成了

http://localhost:8880/web/

 却在web控制台看到了这样的输出结果:

 

写道

 

POST
<samlp:LogoutRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="LR-8-3iFpmqdWBa5MAh2VW5u5FiPYvoOu2MOSe7q" Version="2.0" IssueInstant="2013-04-01T15:42:45Z"><saml:NameID xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">@NOT_USED@</saml:NameID><samlp:SessionIndex>ST-8-2PZRjTcDPWeBc6X4TVb6-cas</samlp:SessionIndex></samlp:LogoutRequest>

 居然正确了!!!

 

于是,果断把CAS client端的serverName后面增加“/”,再次进行单点退出的实验,成功!

 

   发表时间:2013-04-01  
HTTP协议里面有说  url 后面 默认是有/的  是浏览器帮我们加的
0 请登录后投票
   发表时间:2013-04-02  
HTTP协议规范中没有默认/结尾这条说明,不要误导人
0 请登录后投票
   发表时间:2013-04-02  
lzxz1234 写道
HTTP协议规范中没有默认/结尾这条说明,不要误导人

不过浏览器会自动增加最后面的/倒是确实存在的。我在实验的时候,就是直接把chrome浏览器上面的地址复制到测试类里面,就实验成功了。

大侠知道是什么原因导致程序把没有/结尾的请求认做是GET请求了吗
0 请登录后投票
   发表时间:2013-04-02  
dinguangx 写道
不过浏览器会自动增加最后面的/倒是确实存在的。我在实验的时候,就是直接把chrome浏览器上面的地址复制到测试类里面,就实验成功了。

大侠知道是什么原因导致程序把没有/结尾的请求认做是GET请求了吗


这个不容易观察,不过我猜测Chrome会加 / 可能是服务器返回了 301 的指令,程序不能接收/结尾的请求 可能 是你某个配置文件写的有问题,看看web.xml啥的,具体很难猜
0 请登录后投票
   发表时间:2013-04-02  
lzxz1234 写道
dinguangx 写道
不过浏览器会自动增加最后面的/倒是确实存在的。我在实验的时候,就是直接把chrome浏览器上面的地址复制到测试类里面,就实验成功了。

大侠知道是什么原因导致程序把没有/结尾的请求认做是GET请求了吗


这个不容易观察,不过我猜测Chrome会加 / 可能是服务器返回了 301 的指令,程序不能接收/结尾的请求 可能 是你某个配置文件写的有问题,看看web.xml啥的,具体很难猜

http表示要通过HTTP协议来定位网络资源;host表示合法的Internet主机域名或者IP地址;port指定一个端口号,为空则使用缺省端口80;abs_path指定请求资源的URI;如果URL中没有给出abs_path,那么当它作为请求URI时,必须以“/”的形式给出,通常这个工作浏览器自动帮我们完成。

所有浏览器都会加
0 请登录后投票
   发表时间:2013-04-02  
zhaojuan9 写道

http表示要通过HTTP协议来定位网络资源;host表示合法的Internet主机域名或者IP地址;port指定一个端口号,为空则使用缺省端口80;abs_path指定请求资源的URI;如果URL中没有给出abs_path,那么当它作为请求URI时,必须以“/”的形式给出,通常这个工作浏览器自动帮我们完成。

所有浏览器都会加


嗯,协议没问题,但有一点可能你误解了
如果URL中没有给出 abs_path, 对于 http://localhost:8880/web 这么一个链接来说 abs_path 是 /web,已经给出了,那么就不会加,对于 http://localhost:8880 这么一个链接来说 abs_path 才是空,浏览器才会加
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics