2010-02-10 37 views
19

Hiện tại, tôi đã triển khai thành công bảo mật Xác thực lẫn nhau miễn là khách hàng truy cập trang web bằng trình duyệt web, vì trình duyệt xử lý mọi trao đổi chứng chỉ cho bạn. Bây giờ tôi cần tạo một giao diện bảo mật mà người dùng có thể truy cập các dịch vụ web qua HTTPS, sử dụng xác thực lẫn nhau theo yêu cầu của máy chủ.Xác thực lẫn nhau với các dịch vụ web

Trước hết, có bất kỳ tài nguyên nào mà ai biết về điều đó có thể giúp tôi với điều này không? Tôi đã tìm kiếm một thời gian và không tìm thấy gì cả. Bất kỳ lời khuyên nào khác mà bất cứ ai cũng có thể cho tôi về cách để làm điều này?

Thứ hai, tôi nghĩ rào cản lớn nhất của tôi là sự thiếu hiểu biết về cách xử lý chứng chỉ. Làm cách nào để thương lượng chấp nhận khóa của máy chủ và trình bày khóa của riêng tôi cho máy chủ? Đây là trong Java.

Trả lời

1

Công thức đơn giản được đưa ra trong this blog entry.

Nhưng tôi nghĩ câu trả lời thực sự có thể phụ thuộc vào các API Java bạn đang sử dụng để triển khai các tương tác HTTP phía máy khách của bạn. Ví dụ, có vẻ như bạn sẽ làm mọi thứ a bit differently sử dụng JAX-RPC.

6

Nếu thư viện dịch vụ web sử dụng lớp tiêu chuẩn java.net.URL làm ứng dụng khách HTTP, bạn có thể đặt một số system properties và xác thực hai chiều sẽ được xử lý bằng hỗ trợ HTTPS tích hợp.

Các necessary properties là:

  • javax.net.ssl.trustStore: Chứa chứng chỉ CA gốc
  • javax.net.ssl.keyStore: Chứa giấy chứng nhận của khách hàng và tư nhân chính
  • javax.net.ssl.keyStorePassword: Mật khẩu bảo vệ của khóa riêng

Những khách hàng cài đặt trở thành mặc định cho tất cả các kết nối SSL theo quy trình. Nếu bạn muốn kiểm soát tốt hơn, bạn phải thiết lập của riêng bạn SSLContext. Cho dù đó là có thể với thời gian chạy webservice của bạn phụ thuộc vào thời gian chạy bạn đã chọn.

11

Đối xác thực lẫn nhau bằng SSL (aka hai chiều SSL) bên ngoài trình duyệt, bạn sẽ cần ... Vâng, thực sự, chúng ta hãy xem những gì bạn cần cho một chiều SSL đầu tiên:

  1. Một máy chủ keystore
  2. Một khách hàng truststore

các keystore máy chủ chứa giấy chứng nhận (có thể tự ký) của máy chủ và khóa bí mật. Cửa hàng này được máy chủ sử dụng để ký tin nhắn và trả lại thông tin đăng nhập cho khách hàng.

Truststore khách hàng chứa chứng chỉ (tự ký) của máy chủ (được trích xuất từ ​​kho khóa máy chủ thành chứng chỉ độc lập, không có khóa riêng của máy chủ). Điều này là bắt buộc nếu chứng chỉ không được ký bởi một CA đáng tin cậy mà bạn đã có chứng chỉ trong truststore đi kèm với JRE. Bước này cho phép tạo ra một chuỗi tin cậy.

Với điều này, bạn có thể triển khai SSL một chiều (trường hợp sử dụng truyền thống).

Để thực hiện hai chiều SSL, bạn cần phải thực hiện thiết lập này "đối xứng" vì vậy chúng tôi sẽ cần phải thêm:

  1. Một keystore client
  2. Một máy chủ truststore

Các khoá khách hàng chứa chứng chỉ của khách hàng (có thể tự ký) và khóa cá nhân. Cửa hàng này được khách hàng sử dụng cho cùng một mục đích so với kho khóa máy chủ, tức là gửi thông tin đăng nhập ứng dụng khách đến máy chủ trong quá trình bắt tay xác thực lẫn nhau TLS.

Máy chủ ủy thác máy chủ chứa các chứng chỉ độc lập của khách hàng (tự ký) (được trích xuất từ ​​kho khóa khách hàng thành chứng chỉ độc lập, không có khóa riêng của khách hàng). Điều này là cần thiết cho các lý do chính xác tương tự như đã đề cập trước đó.

Một số nguồn lực để giúp bạn tạo ra tất cả những thứ này và để thực hiện các giải pháp cuối cùng:

+3

Mặc dù bạn đã giải thích các khái niệm xác thực lẫn nhau khá tốt, các liên kết không phải là rất hữu ích ở tất cả. Bảo mật dịch vụ web Java đã thay đổi một chút công bằng kể từ năm 2006! :) – Catchwa

14

Tôi đã dành rất dài thời gian này nhưng cuối cùng tôi đã tìm thấy một ví dụ mà actu đồng minh hoạt động. Đó là Glassfish và Netbeans dựa trên nhưng tôi đoán bạn có thể làm cho nó hoạt động trong các môi trường khác (ví dụ: Eclipse và Tomcat) nếu bạn chơi với nó.

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

Vấn đề tôi đã tìm thấy mặc dù là khi bạn muốn sử dụng giấy chứng nhận của riêng bạn, không phải là những người mà đến cài đặt sẵn với glassfish.

Lưu ý: Tôi không phải là chuyên gia bảo mật. Không triển khai điều này vào một môi trường sản xuất!

Để làm điều này tôi đang sử dụng NetBeans 6.9, JDK 1.6, GlassFish 3.0.1 và OpenSSL v1.0 (Tôi đang sử dụng những chương trình Win32 không chính thức)

# 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:\testbed\OpenSSL-Win32\bin\openssl.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:\testbed\OpenSSL-Win32\bin\openssl.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 Files\glassfish-3.0.1\glassfish\domains\domain1\config\cacerts.jks" 
keytool -import -noprompt -trustcacerts -alias my_ca -file ca/ca.pem -keystore "C:\Program Files\Java\jdk1.6\jre\lib\security\cacerts" 
move "C:\Program Files\glassfish-3.0.1\glassfish\domains\domain1\config\keystore.jks" "C:\Program Files\glassfish-3.0.1\glassfish\domains\domain1\config\keystore.jks.backup" 
copy server\server.jks "C:\Program Files\glassfish-3.0.1\glassfish\domains\domain1\config\keystore.jks" 

Trong GlassFish admin console, kích hoạt Security trên trình nghe http của bạn, đánh dấu vào các hộp SSL3, TLS và Client Authentication, thiết lập Certificate NickName thành máy chủ, Key Store thành config \ keystore.jks, Trust Store để cấu hình \ keystore.jks, Trust Algorithm to PKIX và để Độ dài Chứng chỉ Tối đa ở 5.

Trong NetBeans, hãy tạo một dự án Ứng dụng Web mới. Trong đó, tạo một dịch vụ Web mới.

mã dịch vụ web của tôi trông như thế này:

@WebService() 
public class ListProducts { 

    @Resource WebServiceContext context; 

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

} 

Nhấp chuột phải vào Web Service và chọn Edit Web Service Attributes. Chọn hộp Secure Service và chọn Mutual Certificates Security làm cơ chế bảo mật. Nhấp vào nút Configure ... và đánh dấu vào ô Encrypt Signature. Bây giờ hãy bỏ chọn hộp Use Defaults Development và sau đó nhấn nút Keystore. Đặt vị trí của kho khóa server.jks của bạn và chọn bí danh server.Làm tương tự cho cấu hình Truststore (mặc dù bạn không phải chọn một bí danh ở đây).

Nhập chứng chỉ ứng dụng khách client1.p12 vào trình duyệt của bạn. Triển khai dịch vụ web của bạn với Glassfish. Mở dịch vụ web của bạn trong trình duyệt và duyệt đến WSDL được triển khai thông qua HTTPS. Tải xuống WSDL và bất kỳ lược đồ nào khác. Đổi tên bất kỳ lược đồ được tham chiếu nào thành các bản sao cục bộ để khi bạn sử dụng WSDL2Java NetBeans sẽ không sử dụng bất kỳ tài nguyên từ xa nào. (Đoạn này là vì bạn đã hạn chế WSDL của bạn cho các khách hàng có chứng chỉ được phê duyệt nhưng NetBeans không thể lấy nó từ xa vì nó không có quyền truy cập vào chứng chỉ được đề cập).

Tạo một dự án Java mới. Tạo một máy khách dịch vụ Web mới. Khi được nhắc, hãy trỏ NetBeans vào tệp WSDL đã lưu của bạn. Nhập tệp thư viện METRO2.0 (C:\Program Files\Netbeans 6.9\enterprise\modules\ext\metr\webservices-*.jar). Mã của tôi trông giống như sau:

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()); 
} 

Sao chép webservices-api.jar vào thư mục Java \ jdk1.6 \ jre \ lib \ endorsed của bạn. Nhấp chuột phải vào tham chiếu Dịch vụ web và chọn Chỉnh sửa thuộc tính dịch vụ web. Đặt vị trí kho khóa thành client1.jks và đặt bí danh thành client1. Đặt vị trí của truststore thành client1.jks và đặt bí danh là server.

Hy vọng rằng bây giờ bạn có thể chạy khách hàng của bạn và bạn sẽ thấy kết quả như sau: [email protected], CN=Bob Smith, OU=Something, O=SomethingElse, L=AnyTown, ST=AnyState, C=US

Các vấn đề liên quan