Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

Currently, I've been successful implementing Mutual Authentication security so long as the client accesses the website using a web browser, because browsers take care of all the certificate exchange for you. Now I need to create a secure interface with which users can access web services over HTTPS, using the mutual authentication required by the server.

First off, are there any resources anyone knows of that can help me with this? I've looked for quite some time and found nothing. Any other tips anyone can give me on how to go about this?

Secondly, I think my biggest roadblock is my lack of understanding of how to handle certificates. How do I negotiate accepting the server's key and presenting my own key to the server? This is in Java.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
174 views
Welcome To Ask or Share your Answers For Others

1 Answer

I spent a long time on this but I finally found an example that actually works. It's Glassfish and Netbeans-based but I guess you could get it working in other environments (e.g. Eclipse and Tomcat) if you played around with it.

http://java.sun.com/webservices/reference/tutorials/wsit/doc/WSIT_Security9.html#wp162511

The problem I've found though is when you want to use your own certificates, not the ones that come pre-installed with glassfish.

Note: I am not a security expert. Don't deploy this to a production environment!

To do this I'm using NetBeans 6.9, JDK 1.6, GlassFish 3.0.1 and OpenSSL v1.0 (I'm using the unofficial Win32 binaries)

# Create the CA
mkdir ca server client
cd ca
openssl req -new -x509 -days 3650 -extensions v3_ca -keyout ca.key -out ca.pem
echo 02 > serial.txt
cd ..

# Creating the Server Keystore

openssl req -days 3650 -newkey rsa:1024 -keyout server/server.key -out server/server.req
openssl x509 -extensions usr_cert -extfile C:estbedOpenSSL-Win32inopenssl.cfg -CA ca/ca.pem -CAkey ca/ca.key -CAserial ca/serial.txt -req -in server/server.req -out server/server.crt
openssl pkcs12 -export -inkey server/server.key -in server/server.crt -out server/server.p12 -name server
keytool -importkeystore -destkeystore server/server.jks -deststoretype jks -srckeystore server/server.p12 -srcstoretype pkcs12
keytool -exportcert -alias server -keystore server/server.jks -file server/server.cer

# Create the Client Keystore

openssl req -days 3650 -newkey rsa:1024 -keyout client/client1.key -out client/client1.req
openssl x509 -extensions usr_cert -extfile C:estbedOpenSSL-Win32inopenssl.cfg -CA ca/ca.pem -CAkey ca/ca.key -CAserial ca/serial.txt -req -in client/client1.req -out client/client1.crt
openssl pkcs12 -export -inkey client/client1.key -in client/client1.crt -out client/client1.p12 -name client1
keytool -importkeystore -destkeystore client/client1.jks -deststoretype jks -srckeystore client/client1.p12 -srcstoretype pkcs12
keytool -exportcert -alias client1 -keystore client/client1.jks -file client/client1.cer

# Import public keys and certificates into each others keystores

keytool -import -noprompt -trustcacerts -alias client1 -file client/client1.cer -keystore server/server.jks
keytool -import -noprompt -trustcacerts -alias server -file server/server.cer -keystore client/client1.jks
keytool -import -noprompt -trustcacerts -alias my_ca -file ca/ca.pem -keystore server/server.jks
keytool -import -noprompt -trustcacerts -alias my_ca -file ca/ca.pem -keystore client/client1.jks
keytool -import -noprompt -trustcacerts -alias my_ca -file ca/ca.pem -keystore "C:Program Filesglassfish-3.0.1glassfishdomainsdomain1configcacerts.jks"
keytool -import -noprompt -trustcacerts -alias my_ca -file ca/ca.pem -keystore "C:Program FilesJavajdk1.6jrelibsecuritycacerts"
move "C:Program Filesglassfish-3.0.1glassfishdomainsdomain1configkeystore.jks" "C:Program Filesglassfish-3.0.1glassfishdomainsdomain1configkeystore.jks.backup"
copy serverserver.jks "C:Program Filesglassfish-3.0.1glassfishdomainsdomain1configkeystore.jks"

In the GlassFish admin console, enable Security on your http-listener, tick the SSL3, TLS and Client Authentication boxes, set the Certificate NickName to server, the Key Store to configkeystore.jks, the Trust Store to configkeystore.jks, the Trust Algorithm to PKIX and leave the Max Certificate Length at 5.

In NetBeans, create a new Web Application project. Within that, create a new Web Service.

My Web Service code looked like this:

@WebService()
public class ListProducts {

  @Resource WebServiceContext context;

  @WebMethod(operationName = "listProducts")
  public String listProducts() {
    return context.getUserPrincipal().toString();
  }

}

Right click on the Web Service and select Edit Web Service Attributes. Tick the Secure Service box and select Mutual Certificates Security as the Security Mechanism. Click on the Configure... button and tick the Encrypt Signature box. Now untick the Use Development Defaults box and then click the Keystore button. Set the location of your server.jks keystore and select the server alias. Do the same for the Truststore configuration (although you don't have to select an alias here).

Import the client1.p12 client certificate into your browser. Deploy your Web Service to Glassfish. Open up your web service in a browser and browse to the deployed WSDL via HTTPS. Download the WSDL and any other schemas. Rename any referenced schemas to local copies so that when you use WSDL2Java NetBeans won't use any remote resources. (This paragraph is because you've restricted your WSDL to clients with an approved certificate but NetBeans can't fetch it remotely because it doesn't have access to the certificate in question).

Create a new Java Project. Create a new Web Service Client. When prompted, point NetBeans to your saved WSDL file. Import the METRO2.0 library files (C:Program FilesNetbeans 6.9enterprisemodulesextmetrwebservices-*.jar). My code looked like this:

public static void main(String[] args) {
  System.getProperties().put("javax.net.ssl.keyStore", "C:\NetBeansProjects\security-04\ssl\client\client1.jks");
  System.getProperties().put("javax.net.ssl.keyStorePassword", "changeit");
  System.getProperties().put("javax.net.ssl.trustStore", "C:\NetBeansProjects\security-04\ssl\client\client1.jks");
  System.getProperties().put("javax.net.ssl.trustStorePassword", "changeit");
  System.out.println(new ListProductsService().getListProductsPort().listProducts());
}

Copy webservices-api.jar into your Javajdk1.6jrelibendorsed directory. Right-click on the Web Service reference and select Edit Web Service Attributes. Set the keystore location to client1.jks and set the alias to client1. Set the truststore location to client1.jks and set the alias to server.

Hopefully you can now run your client and you should see output like so: [email protected], CN=Bob Smith, OU=Something, O=SomethingElse, L=AnyTown, ST=AnyState, C=US


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...