??xml version="1.0" encoding="utf-8" standalone="yes"?> I use Apache’s HttpClient library for all my URL related needs. It is a marvelous library that does most of the job behind the scenes. Compared the Java’s URL class, it is not as easy to use as Apache’s HttpClient. While using this library, a site that I commonly check for updates threw the exception message javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated. When I checked the site, it seemed that its SSL certificated had expired. The only workaround for this is to create your own TrustManager. This class actually checks if the SSL certificate is valid. The scheme used by SSL is called X.509 and Java has a specific TrustManager for this scheme, called X509TrustManager. This handy method created by theskeleton is just the perfect solution to have your HttpClient object bypass any SSL related errors and ensures that it accepts all SSL certificates of a site, whether it is expired or not. Here I have described how to create client/server keystores which can be used to secure Axsi2 webservices and invoke Axis2 secured webservices. i.e. It can be easily used with any WSO2 Product to experience security scenarios.More detailed explanation on creating client/server keystores using openssl including Certificate Authority(CA) Requests, can be found at http://wso2.org/library/174. Java keytool stores the keys and certificates in a keystore, protected by a keystore password. Further, it protects private key again with another password. A Java keystore contains private-public key pair and multiple trusted certificate entries. All entries in a keystore are referred by aliases. Both private key and self signed public key is referred by one alias while any other trusted certificates are referred by different individual aliases. As the first step, let's create a keystore for server. In order to do it, execute following command in a terminal. "server" in the following command corresponds to the private key/self signed public key certificate alias in the keystore while "server.jks" is the name of the creating keystore file. keytool -genkey -alias server -keyalg RSA -keystore server.jks when you execute the above command it will first prompt you to specify a password which is corresponded to the keystore password. Then it will prompt several questions. You can give answers that you wish. At the end it will ask for a password again, which will be used to secure the generated private key. Enter keystore password: Once you successfully completed this, java keytool will create a file named "server.jks". In the same way, you can create a client keystore named "client.jks" with the alias "client" using following command. keytool -genkey -alias client -keyalg RSA -keystore client.jks Now, you have two files named client.jks and server.jks. You can view the content of these keystore files using the following command. Replacess "ruchira" with the keystore password you entered while creating the keystore. keytool -list -v -keystore server.jks -storepass ruchira This will list something like this. Keystore type: JKS Your keystore contains 1 entry Alias name: server ******************************************* The next step is, getting server's self signed public key certificate and storing it in client's keystore. And getting and storing client's self signed public key certificate in server's keystore. In order to do that, first we need to export both server and client public key certificates into files. Using the following command, you can export server's public key certificate into server.cert file and client's public key certificate into client.cert file. keytool -export -file server.cert -keystore server.jks -storepass ruchira -alias server Now you have server.cert and client.cert. You can use following commands to view certificate contents. keytool -printcert -v -file server.cert As the last step, we need to import server.cert into client keystore and client.cert into server keystore. As I mentioned earlier, each entry of a Java Keystore is stored against an alias. So, we need to specify aliases here, which will be used to refer the certificates that we are going to store. keytool -import -file client.cert -keystore server.jks -storepass ruchira -alias client Above command will store client's self signed public key certificate(client.cert) in server.jks against the alias "client". So, using "client" alias on server.jks, we can refer client's certificate anytime. Likewise, following command will store server.cert within client.jks against the alias "server". keytool -import -file server.cert -keystore client.jks -storepass ruchira -alias server After all, please view the content of both keystore again using following commands. keytool -list -v -keystore server.jks -storepass ruchira It will give you something like bellow for server.jks Keystore type: JKS Your keystore contains 2 entries Alias name: server ******************************************* Alias name: client Owner: CN=Ruchira Wageesha, OU=Mashup Server, O=WSO2, L=Ahangama, ST=Southern, C=LK ******************************************* something like below for client.jks Keystore type: JKS Your keystore contains 2 entries Alias name: server Owner: CN=Ruchira Wageesha, OU=Mashup Server, O=WSO2, L=Ahangama, ST=Southern, C=LK ******************************************* Alias name: client ******************************************* If everything went well, you might have successfully created server.jks and client.jks which can be used to secure Axis2 Services and access those secured services.
try {
SSLContext ctx = SSLContext.getInstance("TLS");
X509TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException { }
public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException { }
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
ctx.init(null, new TrustManager[]{tm}, null);
SSLSocketFactory ssf = new SSLSocketFactory(ctx);
ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
ClientConnectionManager ccm = base.getConnectionManager();
SchemeRegistry sr = ccm.getSchemeRegistry();
sr.register(new Scheme("https", ssf, 443));
return new DefaultHttpClient(ccm, base.getParams());
} catch (Exception ex) {
return null;
}
}
Another way is to recreate the keystore, for the keystore you should have the site in the CN=XXX.
the command as below:
1. Create keystore
keytool -export -keystore pznKeyStore.jks -alias pznsigned -file pznsslcert.cer
3. Create trust store for client
keytool -genkey -dname "cn=da957203.fmr.com,o=,c=" -storepass MB7BROKERpzn -keystore pznTrustStore.jks -alias pzntrustsigned
4. import the server cert
keytool -import -alias pzntrust -file pznsslcert.cer -keystore pznTrustStore.jks -storepass MB7BROKERpzn
5. use http client to call the server
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
FileInputStream instream = new FileInputStream(new File(trustfname));
try {
trustStore.load(instream, passphrase.toCharArray());
} finally {
try { instream.close(); } catch (Exception ignore) {}
}
SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);
Scheme sch = new Scheme("https", 443, socketFactory);
httpclient.getConnectionManager().getSchemeRegistry().register(sch);
} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
]]>
Re-enter new password:
What is your first and last name?
[Unknown]: Ruchira Wageesha
What is the name of your organizational unit?
[Unknown]: Mashup Server
What is the name of your organization?
[Unknown]: WSO2
What is the name of your City or Locality?
[Unknown]: Ahangama
What is the name of your State or Province?
[Unknown]: Southern
What is the two-letter country code for this unit?
[Unknown]: LK
Is CN=Ruchira Wageesha, OU=Mashup Server, O=WSO2, L=Ahangama, ST=Southern, C=LK correct?
[no]: yes
Enter key password for
(RETURN if same as keystore password):
Keystore provider: SUN
Creation date: Jul 8, 2010
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Ruchira Wageesha, OU=Mashup Server, O=WSO2, L=Ahangama, ST=Southern, C=LK
Issuer: CN=Ruchira Wageesha, OU=Mashup Server, O=WSO2, L=Ahangama, ST=Southern, C=LK
Serial number: 4c356225
Valid from: Thu Jul 08 10:59:09 IST 2010 until: Wed Oct 06 10:59:09 IST 2010
Certificate fingerprints:
MD5: 60:0B:48:0D:DB:56:8C:68:8C:2D:94:4A:D6:DA:04:B8
SHA1: A7:CE:57:10:70:87:C1:2C:C0:9D:1D:90:8C:BB:69:B6:66:26:97:13
Signature algorithm name: SHA1withRSA
Version: 3
*******************************************
keytool -export -file client.cert -keystore client.jks -storepass ruchira -alias client
keytool -printcert -v -file client.cert
keytool -list -v -keystore client.jks -storepass ruchira
Keystore provider: SUN
Creation date: Jul 8, 2010
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Ruchira Wageesha, OU=Mashup Server, O=WSO2, L=Ahangama, ST=Southern, C=LK
Issuer: CN=Ruchira Wageesha, OU=Mashup Server, O=WSO2, L=Ahangama, ST=Southern, C=LK
Serial number: 4c3562a0
Valid from: Thu Jul 08 11:01:12 IST 2010 until: Wed Oct 06 11:01:12 IST 2010
Certificate fingerprints:
MD5: AB:77:72:F1:0D:09:55:E3:B6:D3:DC:A6:4D:D4:39:36
SHA1: D7:C1:60:5C:7E:34:40:A9:0B:E4:2C:65:6C:E0:79:7C:EE:37:A7:19
Signature algorithm name: SHA1withRSA
Version: 3
*******************************************
Creation date: Jul 8, 2010
Entry type: trustedCertEntry
Issuer: CN=Ruchira Wageesha, OU=Mashup Server, O=WSO2, L=Ahangama, ST=Southern, C=LK
Serial number: 4c356225
Valid from: Thu Jul 08 10:59:09 IST 2010 until: Wed Oct 06 10:59:09 IST 2010
Certificate fingerprints:
MD5: 60:0B:48:0D:DB:56:8C:68:8C:2D:94:4A:D6:DA:04:B8
SHA1: A7:CE:57:10:70:87:C1:2C:C0:9D:1D:90:8C:BB:69:B6:66:26:97:13
Signature algorithm name: SHA1withRSA
Version: 3
*******************************************
Keystore provider: SUN
Creation date: Jul 8, 2010
Entry type: trustedCertEntry
Issuer: CN=Ruchira Wageesha, OU=Mashup Server, O=WSO2, L=Ahangama, ST=Southern, C=LK
Serial number: 4c3562a0
Valid from: Thu Jul 08 11:01:12 IST 2010 until: Wed Oct 06 11:01:12 IST 2010
Certificate fingerprints:
MD5: AB:77:72:F1:0D:09:55:E3:B6:D3:DC:A6:4D:D4:39:36
SHA1: D7:C1:60:5C:7E:34:40:A9:0B:E4:2C:65:6C:E0:79:7C:EE:37:A7:19
Signature algorithm name: SHA1withRSA
Version: 3
*******************************************
Creation date: Jul 8, 2010
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=Ruchira Wageesha, OU=Mashup Server, O=WSO2, L=Ahangama, ST=Southern, C=LK
Issuer: CN=Ruchira Wageesha, OU=Mashup Server, O=WSO2, L=Ahangama, ST=Southern, C=LK
Serial number: 4c356225
Valid from: Thu Jul 08 10:59:09 IST 2010 until: Wed Oct 06 10:59:09 IST 2010
Certificate fingerprints:
MD5: 60:0B:48:0D:DB:56:8C:68:8C:2D:94:4A:D6:DA:04:B8
SHA1: A7:CE:57:10:70:87:C1:2C:C0:9D:1D:90:8C:BB:69:B6:66:26:97:13
Signature algorithm name: SHA1withRSA
Version: 3
*******************************************
]]>
在IE下用Ajaxh某一面Q通常会因为缓存的原因而返回上一ơ的l果Q造成混ؕQ而FF下不会出现这U情cؓ了不受缓存媄响,可以q样做:
IE讉K{略QInternet选项--览历史记录--讄-- Internet 临时文g的选项改ؓ每次讉K|页时也可以
1: 在AJAXh的页面后加个随机函数,我们可以使用随机旉函数
在javascript发送的URL后加上t=Math.random()
例如q样:URL+"&"+"t="+Math.random();或者new Date();
2: 在XMLHttpRequest发送请求之前加上XMLHttpRequest.setRequestHeader("If-Modified-Since","0")
一般情况下,q里的XMLHttpRequest不会直接使用
你应该可以找到这L代码
XXXXX.send(YYYYYY);
那么,把它变?
XXXXX.setRequestHeader("If-Modified-Since","0");
XXXXX.send(YYYYYY);
实践证明Q两U方法都非常有效?/p>
RPCQ?/span>Remote Procedure Call ProtocolQ?/span>—?span style="font-family: 宋体;">q程q程调用协议Q它是一U通过|络从远E计机E序上请求服务,而不需要了解底层网l技术的协议?/span>RPC协议假定某些传输协议?/span> 存在Q如TCP?/span>UDPQؓ通信E序之间携带信息数据。在OSI|络通信模型中,RPC跨越了传输层和应用层?/span>RPC使得开发包括网l分布式多程序在内的 应用E序更加Ҏ?br />
基本?/span>
RPC采用客户?服务器模式。请求程序就是一个客hQ而服务提供程序就是一个服务器。首先,调用q程发送一个有q程参数的调用信息到服务q程Q然后等待应{信息。在服务器端Q进E保持睡眠状态直到调用信息的到达为止。当一个调用信息到达,服务器获得进E参敎ͼ计算l果Q发送答复信息,然后{待下一个调 用信息,最后,客户?/span>?用过E接收答复信息,获得q程l果Q然后调用执行l进行?
目前Q有多种 RPC 模式和执行。最初由 Sun 公司提出。IETF ONC 宪章重新修订?Sun 版本Q?ONC PRC 协议成ؓ IETF 标准协议。现在用最普遍的模式和执行是开攑ּ软g基础的分布式计算环境QDCEQ?br />
q程q程调用QRPC[1]Q信 息协议由两个不同l构l成Q调用信息和{复信息。信息流E如下所C:
RPCQ远E过E调用流E?
RPC 调用信息Q每条远E过E调用信息包括以下无W号整数字段Q以独立识别q程q程Q?
E序PProgram numberQ?
E序版本PProgram version numberQ?
q程PProcedure numberQ?
RPC 调用信息M形式如下Q?
struct call_body {
unsigned int rpcvers;
unsigned int prog;
unsigned int vers;
unsigned int proc;
opaque_auth cred;
opaque_auth verf;
1 parameter
2 parameter . . . }Q?
RPC {复信息QRPC 协议的答复信息的改变取决于网l服务器对调用信息是接收q是拒绝。答复信息请求包括区别以下情形的各种信息Q?
RPC 成功执行调用信息?
RPC 的远E实C是协议第二版Q返?RPC 支持的最低和最高版本号?
在远E系l中Q远E程序不可用?
q程E序不支持被h的版本号。返回远E程序所支持的最低和最高版本号?
h的过E号不存在。通常是呼叫方协议或程序差错?
RPC{复信息形式如下Q?
enum reply_stat stat
{MSG_ACCEPTED = 0,
MSG_DENIED = 1 }Q?/span>
q行?一ơ客hҎ务器的RPC调用,其内部操作大致有如下十步Q?
1.调用客户端句柄;执行传送参?
2.调用本地pȝ内核发送网l消?
3.消息传送到q程L
4.服务器句柄得到消息ƈ取得参数
5.执行q程q程
6.执行的过E将l果q回服务器句?
7.服务器句柄返回结果,调用q程pȝ内核
8.消息传回本地L
9.客户句柄由内核接收消?
10.客户接收句柄q回的数?/span>
Microsoft RPC-over-HTTP 部v(RPC over HTTP)允许RPC 客户端安全和有效地通过Internet q接到RPC 服务器程序ƈ执行q程q程调用。这是在一个名UCؓRPC-over-HTTP 代理Q或UCؓRPC 代理?/span>中间?/span>的帮助下 完成的?
RPC 代理q行在IIS 计算Z。它接受来自Internet 的RPC hQ在q些h上执行认证,验和讉K查,如果h通过所有的试QRPC 代理请求{发给执行真正处理的RPC 服务器。通过RPC over HTTPQRPC 客户端不和服务器直接通信Q它们用RPC 代理作ؓ中间件?br />l过代理以后Q由于在客户端和服务之间增加了中间层Q因此服务器无法直接拿到客户端的IPQ服务器端应用也无法直接通过转发h的地址q回l客L。但? 在{发请求的HTTP头信息中Q增加了XQFORWARDEDQFOR信息。用以跟t原有的客户端IP地址和原来客Lh的服务器地址。当我们讉Khttp://m.tkk7.com/dashi99 Ӟ其实q不是我们浏览器真正讉KC服务器上的index.jsp文gQ而是先由代理服务器去讉Khttp://192.168.1.110Q?046/index.jsp Q代理服务器再将讉K到的l果q回l我们的览器,因ؓ是代理服务器去访问index.jsp的,所以index.jsp中通过 request.getRemoteAddrQ)的方法获取的IP实际上是代理服务器的地址Qƈ不是客户端的IP地址?/p>
于是可得得客L真实IP地址的方法一Q?/p>
public
String getRemortIP(HttpServletRequest request) { if (request.getHeader("x-forwarded-for") == null) { return request.getRemoteAddr(); } return request.getHeader("x-forwarded-for"); } |
可是当我讉Khttp://m.tkk7.com/dashi99 Ӟq回的IP地址始终是unknownQ也q不是如上所C的127.0.0.1 或 192.168.1.110了,而我讉Khttp://192.168.1.110Q?046/index.jsp Ӟ则能q回客户端的真实IP地址Q写了个Ҏ去验证。原因出在了Squid上。squid.conf 的配制文件 forwarded_for w认是为onQ如?forwarded_for 设成?off 则:X-Forwarded-ForQ?unknown
于是可得得客L真实IP地址的方法二Q?/p>
public
String getIpAddr(HttpServletRequest request) { String ip = request.getHeader("x-forwarded-for"); if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } return ip; } |
可是Q如果通过了多U反向代理的话,X-Forwarded-For的值ƈ不止一个,而是一Ԍp|I竟哪个才是真正的用L的真实IP呢?
{案是取X-Forwarded-For中第一个非unknown的有效IP字符丌Ӏ?/p>
如:X-Forwarded-ForQ?92.168.1.110Q?192.168.1.120Q?192.168.1.130Q? 192.168.1.100用户真实IP为: 192.168.1.110