在使用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
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>
<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后面增加“/”,再次进行单点退出的实验,成功!