昨天尝试把cas的java client端部署到另外一台机器,结果就有问题了。(localhost部署cas server和java client端参见:http://www.cnblogs.com/sunshineatnoon/p/4119565.html)
主要是client访问的时候报错:javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names present。
后来在stackoverflow上找到了解决办法:http://stackoverflow.com/questions/9331087/how-to-setup-ssl-for-cas-and-client-different-machines?rq=1
根据jasig文档对这个错误的解释:
Sample Alt Name Stack Trace
javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: No subject alternative names present
In most cases this is a hostname/SSL certificate CN mismatch. This commonly happens when a self-signed certificate issued to localhost is placed on a machine that is accessed by IP address. It should be noted that generating a certificate with an IP address for a common name, e.g. CN=192.168.1.1,OU=Middleware,dc=vt,dc=edu, will not work in most cases where the client making the connection is Java. For example the Java CAS client will throw SSL errors on connecting to a CAS server secured with a certificate containing an IP address in the CN.
是由于生成的证书中域名(CN)和server的域名或者以后client端访问的域名不一致造成的,并且这里也说了,不能用ip地址当作生成证书时候的CN,只能用域名。
所以改变的方法就是用域名生成证书,并且配置client端电脑的hosts和lmhosts.sam文件解析服务器域名,具体步骤如下:
1. 编辑client端机器的C:WindowsSystem32Driversetchosts,添加一行:
your_ip(xxx.xxx.xxx.xxx) your_cn(sunshineatnoon.com)
2. 编辑client端机器的C:WindowsSystem32Driversetclmhosts.sam,添加一行:
your_ip(xxx.xxx.xxx.xxx) your_cn(sunshineatnoon.com)
3. 在server端所在的机器用keytool重新生成证书:
keytool -genkeypair -alias "tomcat" -keyalg "RSA" -keystore "g: omcat.keystore"
在回答"what's you name?"这个问题的时候回答上述你的域名:sunshineatnoon.com
4.配置server端机器的tomcat下%TOMCAT_PATH%/conf下的server.xml文件,参考http://www.cnblogs.com/sunshineatnoon/p/4064632.html的3(1)(2),如果生成证书和以前的位置密码都没变,就不用重新配置了。
5.重新用文件InstallCert.java生成证书放到client端机器的$JAVA_HOMEjrelibsecurity下,参考http://www.cnblogs.com/sunshineatnoon/p/4070750.html我所解决的第2个bug。
6.client端的java程序中请求ticket的url就由https://localhost:8443/cas/v1/tickets变成了https://sunshineatnoon.com:8443/cas/v1/tickets,改变后的client.java如下所示:
1 package cas; 2 3 4 import java.io.BufferedReader; 5 import java.io.BufferedWriter; 6 import java.io.IOException; 7 import java.io.InputStreamReader; 8 import java.io.OutputStreamWriter; 9 import java.net.MalformedURLException; 10 import java.net.URL; 11 import java.net.URLConnection; 12 import java.net.URLEncoder; 13 14 import javax.net.ssl.HttpsURLConnection; 15 16 public class Client { 17 18 19 public static void main(String... args) throws Exception 20 { 21 String username ="test01"; 22 String password ="psw01"; 23 validateFromCAS(username,password); 24 } 25 26 public static boolean validateFromCAS(String username, String password) throws Exception 27 { 28 29 //String url = "https://localhost:8443/cas/v1/tickets"; 30 String url = "https://sunshineatnoon.com:8443/cas/v1/tickets"; 31 try 32 { 33 HttpsURLConnection hsu = (HttpsURLConnection)openConn(url); 34 String s = URLEncoder.encode("username","UTF-8") + "=" + URLEncoder.encode("test01","UTF-8"); 35 s+="&" +URLEncoder.encode("password","UTF-8") + "=" + URLEncoder.encode("psw01","UTF-8"); 36 37 System.out.println(s); 38 OutputStreamWriter out = new OutputStreamWriter(hsu.getOutputStream()); 39 BufferedWriter bwr = new BufferedWriter(out); 40 bwr.write(s); 41 bwr.flush(); 42 bwr.close(); 43 out.close(); 44 45 String tgt = hsu.getHeaderField("location"); 46 System.out.println( hsu.getResponseCode()); 47 if(tgt != null && hsu.getResponseCode() == 201) 48 { 49 System.out.println(tgt); 50 51 System.out.println("Tgt is : " + tgt.substring( tgt.lastIndexOf("/") +1)); 52 tgt = tgt.substring( tgt.lastIndexOf("/") +1); 53 bwr.close(); 54 closeConn(hsu); 55 56 57 //String serviceURL = "http://localhost:8080/CasClient"; 58 String serviceURL = "http://www.baidu.com"; 59 String encodedServiceURL = URLEncoder.encode("service","utf-8") +"=" + URLEncoder.encode(serviceURL,"utf-8"); 60 System.out.println("Service url is : " + encodedServiceURL); 61 62 63 64 String myURL = url+ "/"+ tgt ; 65 System.out.println(myURL); 66 hsu = (HttpsURLConnection)openConn(myURL); 67 out = new OutputStreamWriter(hsu.getOutputStream()); 68 bwr = new BufferedWriter(out); 69 bwr.write(encodedServiceURL); 70 bwr.flush(); 71 bwr.close(); 72 out.close(); 73 74 System.out.println("Response code is: " + hsu.getResponseCode()); 75 76 BufferedReader isr = new BufferedReader( new InputStreamReader(hsu.getInputStream())); 77 String line; 78 System.out.println( hsu.getResponseCode()); 79 while ((line = isr.readLine()) != null) { 80 System.out.println( line); 81 } 82 isr.close(); 83 hsu.disconnect(); 84 return true; 85 86 } 87 else 88 { 89 return false; 90 } 91 92 93 } 94 catch(MalformedURLException mue) 95 { 96 mue.printStackTrace(); 97 throw mue; 98 99 } 100 catch(IOException ioe) 101 { 102 ioe.printStackTrace(); 103 throw ioe; 104 } 105 106 107 108 109 110 } 111 112 113 static URLConnection openConn(String urlk) throws MalformedURLException, IOException 114 { 115 116 URL url = new URL(urlk); 117 HttpsURLConnection hsu = (HttpsURLConnection) url.openConnection(); 118 hsu.setDoInput(true); 119 hsu.setDoOutput(true); 120 hsu.setRequestMethod("POST"); 121 return hsu; 122 123 124 } 125 126 127 static void closeConn(HttpsURLConnection c) 128 { 129 c.disconnect(); 130 } 131 132 133 }
注意红色那行改变的代码。
7.这时client端上的java client端应该就可以成功得到TGT和ST了。