JSSE(Java Secure Socket Extension)简单使用(二)

客户端和服务器端证书的生成,请看:

http://my.oschina.net/xinxingegeya/blog/266826

http://www.ibm.com/developerworks/cn/java/j-lo-socketkeytool/

参考文章:http://www.ibm.com/developerworks/cn/java/j-lo-socketkeytool/

参考文章:http://willtea.iteye.com/blog/1841281


单向认证

这里只需客户端认证服务器端,实现ssl通信。

服务器端程序

这段指定务端程序要使用的证书库和密码

 /**
         * 指定服务端程序要使用的证书库和密码:
         * 这是单向认证,只需客户端热证服务器端
         */
        System.setProperty("javax.net.ssl.keyStore", SERVER_KEY_STORE);
        System.setProperty("javax.net.ssl.keyStorePassword", SERVER_KEY_STORE_PASSWORD);

注意到程序中 setNeedClientAuth(false),表示不需要验证客户端身份。如果这里设置为 true,则我们这里还需要指定服务器端的信任库和密码

package ssl5;

import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
import java.io.*;

/**
 * Created with IntelliJ IDEA.
 * User: ASUS
 * Date: 14-5-20
 * Time: 下午12:07
 * To change this template use File | Settings | File Templates.
 */
public class SSLServer {

    // 服务器端授权的用户名和密码
    private static final String USER_NAME = "principal";
    private static final String PASSWORD = "credential";
    // 服务器端保密内容
    private static final String SECRET_CONTENT = "This is confidential content from server X, for your eye!";

    private static String SERVER_KEY_STORE = "E:\\javassl2\\sslserverkeys";
    private static String SERVER_KEY_STORE_PASSWORD = "123456";
    private SSLServerSocket serverSocket = null;

    public SSLServer() throws Exception {
        /**
         * 指定服务端程序要使用的证书库和密码:
         * 这是单向认证,只需客户端热证服务器端
         */
        System.setProperty("javax.net.ssl.keyStore", SERVER_KEY_STORE);
        System.setProperty("javax.net.ssl.keyStorePassword", SERVER_KEY_STORE_PASSWORD);

        // 使用默认方式获取套接字工厂实例
        SSLServerSocketFactory socketFactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
        serverSocket = (SSLServerSocket) socketFactory.createServerSocket(7070);
        /**
         * 设置不需要验证客户端身份
         */
        serverSocket.setNeedClientAuth(false);
    }

    private void runServer() {
        while (true) {
            try {
                System.out.println("Waiting for connection...");
                // 服务器端套接字进入阻塞状态,等待来自客户端的连接请求
                SSLSocket socket = (SSLSocket) serverSocket.accept();

                // 获取服务器端套接字输入流
                BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                // 从输入流中读取客户端用户名和密码
                String userName = input.readLine();
                String password = input.readLine();

                // 获取服务器端套接字输出流
                PrintWriter output = new PrintWriter(
                        new OutputStreamWriter(socket.getOutputStream()));

                // 对请求进行认证,如果通过则将保密内容发送给客户端
                if (userName.equals(USER_NAME) && password.equals(PASSWORD)) {
                    output.println("Welcome, " + userName);
                    output.println(SECRET_CONTENT);
                } else {
                    output.println("Authentication failed, you have no access to server X...");
                }

                // 关闭流资源和套接字资源
                output.close();
                input.close();
                socket.close();

            } catch (IOException ioException) {
                ioException.printStackTrace();
            }
        }
    }

    public static void main(String args[]) throws Exception {
        SSLServer server = new SSLServer();
        server.runServer();
    }
}


客户端程序

这段代码指定客户端需要信任的证书库和密码

 /**
         * 这是单向认证
         * 客户端指定信任库和密码
         * 如果服务端程序 setNeedClientAuth(true) 要求验证客户端身份,则我们还需要指定证书库和密码:
         */
        System.setProperty("javax.net.ssl.trustStore", CLIENT_TRUST_KEY_STORE);
        System.setProperty("javax.net.ssl.trustStorePassword", CLIENT_TRUST_KEY_STORE_PASSWORD);

如果服务端程序 setNeedClientAuth(true) 要求验证客户端身份,则我们还需要指定客户端的证书库和密码

package ssl5;

import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import java.io.*;

/**
 * Created with IntelliJ IDEA.
 * User: ASUS
 * Date: 14-5-20
 * Time: 下午12:06
 * To change this template use File | Settings | File Templates.
 */
public class SSLClient {

    private static String CLIENT_TRUST_KEY_STORE = "E:\\javassl2\\sslclienttrust";
    private static String CLIENT_TRUST_KEY_STORE_PASSWORD = "123456";


    private SSLSocket socket = null;

    public SSLClient() throws IOException {
        /**
         * 这是单向认证
         * 客户端指定信任库和密码
         * 如果服务端程序 setNeedClientAuth(true) 要求验证客户端身份,则我们还需要指定证书库和密码:
         */
        System.setProperty("javax.net.ssl.trustStore", CLIENT_TRUST_KEY_STORE);
        System.setProperty("javax.net.ssl.trustStorePassword", CLIENT_TRUST_KEY_STORE_PASSWORD);

        // 通过套接字工厂,获取一个客户端套接字
        SSLSocketFactory socketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
        socket = (SSLSocket) socketFactory.createSocket("localhost", 7070);
    }

    public void connect() {
        try {
            // 获取客户端套接字输出流
            PrintWriter output = new PrintWriter(
                    new OutputStreamWriter(socket.getOutputStream()));
            // 将用户名和密码通过输出流发送到服务器端
            String userName = "principal";
            output.println(userName);
            String password = "credential";
            output.println(password);
            output.flush();

            // 获取客户端套接字输入流
            BufferedReader input = new BufferedReader(
                    new InputStreamReader(socket.getInputStream()));
            // 从输入流中读取服务器端传送的数据内容,并打印出来
            String response = input.readLine();
            response += "\n " + input.readLine();
            System.out.println(response);

            // 关闭流资源和套接字资源
            output.close();
            input.close();
            socket.close();
        } catch (IOException ioException) {
            ioException.printStackTrace();
        } finally {
            System.exit(0);
        }
    }

    public static void main(String args[]) throws IOException {
        new SSLClient().connect();
    }
}

下一篇双向认证。


你可能感兴趣的:(安全套接字编程)