In the web application interaction process, there are many scenarios that need to ensure the security of communication data; in the previous articles, we have introduced how to use WS-Security to ensure the security of the interface interaction process during web service calling. It is worth noting that, the transmission protocol based on this method is still HTTP. The scalability and Data Interaction efficiency are relatively high. The other method is to use https, it is a re-encapsulation of HTTP at the protocol layer, with SSL/TLS added. All data that uses this protocol for communication will be encrypted, at present, web development programming has a certain degree of encapsulation, so the use of HTTPS to provide external services, in addition to the certificate, the programming capability requirements are not high, compared to the former threshold is low, however, it is inefficient to encrypt all the data communicated between the two parties and there are several handshakes during the interaction process; the following describes some problems that may occur when accessing HTTPS links in Java;
A key class is used to access HTTPS links in Java.HttpsurlconnectionSee the following implementation code:
- // Create a URL object
- URL myurl = new URL ("https://www.sun.com ");
- // Create an httpsurlconnection object and set its sslsocketfactory object
- Httpsurlconnection httpsconn = (httpsurlconnection) myurl
- . Openconnection ();
- // Obtain the input stream of the connection to read the response content
- Inputstreamreader insr = new inputstreamreader (httpsconn
- . Getinputstream ());
- // Read and display the server response content
- Int respint = insr. Read ();
- While (respint! =-1 ){
- System. Out. Print (char) respint );
- Respint = insr. Read ();
- }
When the connection is obtained and accessed by a normal browserVerify that the server certificate is trusted(Issued by an authority or signed by an authority). If the server certificate is not trusted, the default implementation will be problematic.SunjsseThe following exception is thrown:
Javax.net. SSL. sslhandshakeexception: Sun. Security. validator. validatorexception: pkix path building failed: Sun. Security. provider. certpath. Failed: unable to find valid certification path to requested target
As mentioned above, sunjsse (Java Secure Socket Extension) is a collection of packages for secure Internet communication. It is a pure Java implementation of SSL and TLS. It can transparently provide data encryption, server authentication, information integrity, and other functions, this allows us to use a secure socket established by JSSE just like a common socket. JSSE is an open standard. Not only can Sun implement a sunjsse, but in fact other companies have their own JSSE, which can then be used in JVM through JCA.
For details about JSSE, refer to reference: http://java.sun.com/j2se/1.5.0/docs/guide/security/jsse/jsserefguide.html;
And Java security guide: http://java.sun.com/j2se/1.5.0/docs/guide/security /;
Before learning about JSSE, you need to understand a Java security concept: the truststore file of the client. The client's truststore file stores the certificate information of the server trusted by the client. When the client performs an SSL connection, JSSE determines whether to trust the server certificate based on the Certificate in this file. In sunjsse, a trust manager class determines whether to trust a remote certificate. This class has the following processing rules:
1. If the system propertyJavax.net. SLL. truststoreIf the truststore file is specified, the trust manager searches for and uses the file in the LIB/security/directory under the JRE installation path to check the certificate.
2. If the system property does not specify the truststore file, it will go to the JRE installation path to find the default truststore file. The relative path of this file is lib/security/Jssecacerts.
3. If jssecacerts does not exist but cacerts exists (it is released along with j2sdk and contains a limited number of trusted Basic certificates), the default truststore file is lib/security/Cacerts.
How can we deal with this situation? There are two solutions:
1. According to the above rules of the trust manager,Import the public key of the server to jssecacertsOr set the path of the truststore file to be loaded in the system properties. For certificate import, run the following command: keytool-import-file src_cer_file-keystore dest_cer_store. For certificates, you can export them in the browser;
2. Implement your own certificate trust manager class, suchMyx509trustmanagerThis class must implement three methods in the x509trustmanager interface. Then, load the custom class in httpsurlconnection. For details, see the following two code snippets. One is the custom certificate trust manager, the second is the code for CONNECT:
- Package test;
- Import java. Io. fileinputstream;
- Import java. Security. keystore;
- Import java. Security. cert. certificateexception;
- Import java. Security. cert. x509certificate;
- Import javax.net. SSL. trustmanager;
- Import javax.net. SSL. trustmanagerfactory;
- Import javax.net. SSL. x509trustmanager;
- Public class myx509trustmanager implements x509trustmanager {
- /*
- * The default x509trustmanager returned by sunx509. we'll delegate
- * Decisions to it, and fall back to the logic in this class if
- * Default x509trustmanager doesn' t trust it.
- */
- X509trustmanager sunjssex509trustmanager;
- Myx509trustmanager () throws exception {
- // Create a "default" JSSE x509trustmanager.
- Keystore Ks = keystore. getinstance ("jks ");
- KS. Load (New fileinputstream ("trustedcerts "),
- "Passphrase". tochararray ());
- Trustmanagerfactory TMF =
- Trustmanagerfactory. getinstance ("sunx509", "sunjsse ");
- TMF. INIT (KS );
- Trustmanager TMS [] = TMF. gettrustmanagers ();
- /*
- * Iterate over the returned trustmanagers, look
- * For an instance of x509trustmanager. If found,
- * Use that as our "default" trust manager.
- */
- For (INT I = 0; I <TMS. length; I ++ ){
- If (TMS [I] instanceof x509trustmanager ){
- Sunjssex509trustmanager = (x509trustmanager) TMS [I];
- Return;
- }
- }
- /*
- * Find some other way to initialize, or else we have to fail
- * Constructor.
- */
- Throw new exception ("couldn't initialize ");
- }
- /*
- * Delegate to the default trust manager.
- */
- Public void checkclienttrusted (x509certificate [] Chain, string authtype)
- Throws certificateexception {
- Try {
- Sunjssex509trustmanager. checkclienttrusted (chain, authtype );
- } Catch (certificateexception excep ){
- // Do any special handling here, or rethrow exception.
- }
- }
- /*
- * Delegate to the default trust manager.
- */
- Public void checkservertrusted (x509certificate [] Chain, string authtype)
- Throws certificateexception {
- Try {
- Sunjssex509trustmanager. checkservertrusted (chain, authtype );
- } Catch (certificateexception excep ){
- /*
- * Possibly pop up a dialog box asking whether to trust
- * Cert chain.
- */
- }
- }
- /*
- * Merely pass this through.
- */
- Public x509certificate [] getacceptedissuers (){
- Return sunjssex509trustmanager. getacceptedissuers ();
- }
- }
- // Create an sslcontext object and use the specified trust manager to initialize the object
- Trustmanager [] TM = {New myx509trustmanager ()};
- Sslcontext = sslcontext. getinstance ("SSL", "sunjsse ");
- Sslcontext. INIT (null, TM, new java. Security. securerandom ());
- // Obtain the sslsocketfactory object from the sslcontext object
- Sslsocketfactory SSF = sslcontext. getsocketfactory ();
- // Create a URL object
- URL myurl = new URL ("https://ebanks.gdb.com.cn/sperbank/perbankLogin.jsp ");
- // Create an httpsurlconnection object and set its sslsocketfactory object
- Httpsurlconnection httpsconn = (httpsurlconnection) myurl. openconnection ();
- Httpsconn. setsslsocketfactory (SSF );
- // Obtain the input stream of the connection to read the response content
- Inputstreamreader insr = new inputstreamreader (httpsconn. getinputstream ());
- // Read and display the server response content
- Int respint = insr. Read ();
- While (respint! =-1 ){
- System. Out. Print (char) respint );
- Respint = insr. Read ();
- }
The two methods have their own advantages. The first methodJSSE security will not be damagedBut manually import the certificate. If there are many servers, the JRE of each server must perform the same operation. method 2Higher flexibilityBut be careful with the implementation, otherwise it may leave security risks;