An ninh là một yêu cầu chính của nhiều kiểu dịch vụ doanh nghiệp. Nó cũng là một khu vực nguy hiểm mà tự thân bạn cần phải cố gắng thực hiện, vì thậm chí chỉ một sự lơ đễnh nhỏ và mơ hồ có thể dẫn đến lỗ hổng nghiêm trọng. Những đặc điểm này làm cho việc tiêu chuẩn hóa xử lý an ninh luôn hấp dẫn, cho phép nhiều chuyên gia đóng góp vào một tiêu chuẩn và tránh bất kỳ sự lơ đễnh cá nhân nào. Các dịch vụ Web dựa trên SOAP có thể sử dụng sự hỗ trợ WS-Security rộng rãi và các tiêu chuẩn có liên quan cho các nhu cầu an ninh của chúng, cho phép cấu hình an ninh cho mỗi dịch vụ khi thích hợp.
Axis2 của Apache hỗ trợ các tiêu chuẩn an ninh này thông qua mô đun Rampart (xem Tài nguyên). Trong bài này, bạn sẽ thấy cách cài đặt, cấu hình và sử dụng Rampart với Axis2 dành cho chức năng an ninh cơ bản về việc gửi một tên người dùng và mật khẩu của một yêu cầu dịch vụ. Trong các bài viết tiếp theo của loạt bài này, bạn sẽ học cách sử dụng Rampart với nhiều hình thức an ninh tinh vi hơn.
WS-Security (an ninh dịch vụ Web) là một tiêu chuẩn để bổ sung thêm bảo đảm an ninh cho các trao đổi thông điệp của dịch vụ Web SOAP (xem Tài nguyên). Nó sử dụng một phần tử của phần đầu (header) thông điệp SOAP để đính kèm thông tin an ninh theo các thông báo, dưới dạng các thẻ bài (tokens) chuyển tải các kiểu lời tự khai khác nhau (các lời tự khai này có thể bao gồm tên, mã nhận diện, khóa, các nhóm, các đặc quyền, các khả năng, và v.v) cùng với thông tin mật mã hóa và chữ ký số. WS-Security hỗ trợ nhiều định dạng cho các thẻ bài, nhiều miền tin cậy, nhiều định dạng chữ ký và nhiều công nghệ mã hóa, do đó, trong hầu hết trường hợp, thông tin trong phần đầu thông điệp cần phải chứa định dạng cụ thể và định danh thuật toán cho mỗi thành phần. Các thông tin bổ sung này có thể dẫn đến một cấu trúc phức tạp cho các thông tin phần đầu của thông điệp, như được hiển thị trong (đã được biên tập lại nhiều) Liệt kê 1 — một ví dụ thông điệp với chữ ký và mật mã hóa:
Liệt kê 1. Thông báo ví dụ với chữ ký và mã hóa
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" ...>
<soap:Header>
<wsse:Security soap:mustUnderstand="1">
<wsu:Timestamp wsu:Id="Timestamp-d2e3c4aa-da82-4138-973d-66b596d66b2f">
<wsu:Created>2006-07-11T21:59:32Z</wsu:Created>
<wsu:Expires>2006-07-12T06:19:32Z</wsu:Expires>
</wsu:Timestamp>
<wsse:BinarySecurityToken ValueType="...-x509-token-profile-1.0#X509v3"
EncodingType="...-wss-soap-message-security-1.0#Base64Binary"
xmlns:wsu="...oasis-200401-wss-wssecurity-utility-1.0.xsd"
wsu:Id="SecurityToken-faa295...">MIIEC56MQswCQY...</wsse:BinarySecurityToken>
<xenc:EncryptedKey xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<wsse:SecurityTokenReference>
<wsse:KeyIdentifier ValueType=
"...#X509SubjectKeyIdentifier">LlYsHyhNnOVA9Aj7...</wsse:KeyIdentifier>
</wsse:SecurityTokenReference>
</KeyInfo>
<xenc:CipherData>
<xenc:CipherValue>g+A2WJhsoGBKUydZ9Za...</xenc:CipherValue>
</xenc:CipherData>
<xenc:ReferenceList>
<xenc:DataReference URI="#EncryptedContent-ba0556c3-d443-4f34-bcd1-14cbc32cd689" />
</xenc:ReferenceList>
</xenc:EncryptedKey>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<ds:CanonicalizationMethod
Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#" />
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
<Reference URI="#Id-c80f735c-62e9-4001-8094-702a4605e429">
<Transforms>
<Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
<DigestValue>lKjc5nyLQDZAIu/hZb4B6mLquow=</DigestValue>
</Reference>
...
</SignedInfo>
<SignatureValue>TiLmWvlz3mswinLVQn58BgYS0368...</SignatureValue>
<KeyInfo>
<wsse:SecurityTokenReference>
<wsse:Reference URI="#SecurityToken-faa295..."
ValueType="...-x509-token-profile-1.0#X509v3" />
</wsse:SecurityTokenReference>
</KeyInfo>
</Signature>
</wsse:Security>
</soap:Header>
<soap:Body wsu:Id="Id-8db9ff44-7bef-4737-8091-cdac51a34db8">
<xenc:EncryptedData Id="EncryptedContent-ba05..."
Type="http://www.w3.org/2001/04/xmlenc#Content"
xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"/>
<xenc:CipherData>
<xenc:CipherValue>mirmi0KuFEEI56eu2U3cICz...</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedData>
</soap:Body>
</soap:Envelope> |
Trong bài này, bạn sẽ thấy một số ví dụ đơn giản của các phần đầu trong WS-Security, với chỉ một thẻ bài duy nhất. Phần tiếp theo trong loạt bài này sẽ đi xa hơn trong việc thảo luận về kiểu cấu trúc phức tạp được hiển thị trong Liệt kê 1.
WS-Security áp dụng cho các trao đổi thông báo SOAP thực tế hiện nay. Việc triển khai thực hiện dịch vụ có thể xác minh rằng WS-Security đã được áp dụng đúng đắn với các thông báo đến, nhưng máy khách cần phải biết trước chúng phải thực hiện những gì để sử dụng dịch vụ này. Với sự phức tạp của WS-Security và số các tùy chọn được hỗ trợ, thật khó có thể sử dụng một mô tả văn bản cho mục đích này và cấu hình thủ công việc xử lý WS-Security có thể gây ra lỗi. WS-Policy (Chính sách dịch vụ Web) là một cấu trúc mục đích chung để xác định các yêu cầu mở rộng đối với các dịch vụ Web và WS-SecurityPolicy (Chính sách an ninh dịch vụ Web) là một phần mở rộng của WS-Policy đặc biệt dành cho sự hỗ trợ WS-Security. Hai tiêu chuẩn này đồng thời cùng với nhau hỗ trợ việc mô tả các yêu cầu WS-Security dưới dạng máy có thể đọc được. Thông tin WS-Policy và WS-SecurityPolicy có thể được sử dụng độc lập hoặc được nhúng trực tiếp bên trong các tài liệu Web Services Description Language (WSDL- Ngôn ngữ mô tả dịch vụ Web), sao cho các khung công tác dịch vụ Web có thể tự động đặt cấu hình chính mình theo các yêu cầu dịch vụ.
Rampart là mô-đun an ninh của Axis2, hỗ trợ WS-Security, WS-SecurityPolicy, WS-SecureConversation (đối thoại an ninh dịch vụ Web) và WS-Trust (Tin cậy dịch vụ Web). Trong bài này, bạn sẽ chỉ thấy các chức năng WS-Security và WS-SecurityPolicy của Rampart; các bài viết sau sẽ cho bạn xem xét các đặc tính khác.
Vì Rampart được thực hiện như là một mô đun (trên thực tế là một cặp mô đun — rampart.mar và rahas.mar), nó được cắm vào khung công tác xử lý Axis2 và thực hiện công việc của mình bằng cách chặn các thông báo tại các điểm cụ thể trong việc xử lý đi vào và đi ra, kiểm tra hoặc thực hiện các thay đổi với các thông báo khi thích hợp.
Rampart được phân phối dưới dạng một số tệp .jar (trong thư mục lib của bản phân phối), cùng với một cặp các tệp mô đun .mar (trong thư mục dist). Bạn phải thêm các tệp .jar vào đường dẫn lớp (classpath) của bạn để sử dụng Rampart với Axis2 và bạn phải thêm các tệp .mar vào đường dẫn lớp của bạn hoặc vào cấu trúc kho lưu trữ Axis2.
Cách dễ nhất để xử lý các tệp .jar và .mar của Rampart là
thêm chúng vào bản cài đặt Axis2 của bạn. Bạn có thể chỉ cần sao chép trực
tiếp các tệp .jar từ thư mục lib của Rampart vào thư mục lib của Axis2 của
bạn và các tệp .mar từ thư mục dist của Rampart vào thư mục
repository/modules của Axis2. (Bạn cũng có thể sử dụng tệp build.xml của
Ant trong thư mục samples của Rampart để sao chép các tệp này tới bản cài
đặt Axis2 của bạn. Chỉ cần đặt biến môi trường AXIS2_HOME tới thư mục cài đặt Axis2 của bạn và chạy ant từ cửa sổ dòng lệnh mở trong thư mục sample
của Rampart).
Đối với nhiều đặc tính WS-Security (An ninh dịch vụ
web), bạn cũng cần phải thêm trình cung cấp an ninh Bouncy Castle vào cấu
hình an ninh của JVM và tệp .jar của Bouncy Castle vào bản cài đặt Axis2
của bạn. Bước này — không cần thiết đối với UsernameToken mà bạn sẽ tìm hiểu về nó trong bài
viết này — là bắt buộc cho các tính năng an ninh khác được
trình bày sau trong loạt bài này. Vì lý do bằng sáng chế của một số thuật
toán an ninh, tệp .jar của Bouncy là một phần tải riêng từ Rampart (xem Tài nguyên). Hãy tải về phiên bản .jar thích hợp
cho thời gian chạy Java của bạn và thêm tệp .jar vào thư mục lib của
Axis2. Sau đó bạn cần phải thay đổi các chính sách an ninh của bản cài đặt
Java của bạn để sử dụng mã Bouncy Castle bằng cách thêm một dòng vào tệp
java.security có trong thư mục lib/security của thời gian chạy Java của
bạn. Hãy tìm phần của tệp có một số dòng security.provider khác nhau và thêm vào dòng sau
đây:
security.provider.99=org.bouncycastle.jce.provider.BouncyCastleProvider |
Trình
tự các dòng security.provider trong tệp không
quan trọng, nhưng sẽ tốt hơn nếu thêm dòng này sau các dòng khác dành cho
vịec thực hiện các trình cung cấp an ninh đã định trước.
Để sử dụng
mã Rampart trong một bản cài đặt máy chủ Axis2, bạn cần phải tạo một tệp
axis2.war mới, có bao gồm các tệp .jar và .mar của Rampart được bổ sung
thêm. Bạn có thể dùng build.xml của Ant đã cung cấp trong thư mục webapp
để tạo axis2.war, với điều kiện đã thực hiện sửa đổi sau đây: xoá dòng
<exclude name="axis2-codegen*.jar"/>
ở gần cuối của tệp. Sau đó, mở một cửa sổ dòng lệnh tại thư mục webapp
Axis2 và chạy ant. Sau khi build.xml chạy, bạn
có thể tìm thấy ứng dụng Web axis2.war trong thư mục dist của bản cài đặt
Axis2.
Ứng dụng được cung cấp trong mã ví dụ (xem Tải về) dựa trên một ví dụ mà tôi thường sử dụng
trong Liên kết dữ liệu Axis2
("Axis2 Data Binding") để giải thích các lựa chọn liên kết dữ liệu
cho Axis2. Với bài viết này và các bài viết tiếp theo về sự hỗ trợ
WS-Security của Axis2, tôi đã cắt bớt đi, xuống chỉ còn ba hoạt động:
getBook, addBook, và getBooksByType. Để giữ cho
đơn giản, chỉ có phiên bản mã Axis Data Binding (ADB- Liên kết dữ liệu
Axis) được cung cấp, nhưng đây không phải là một yêu cầu bắt buộc để làm
việc với WS-Security trong Axis2 — Rampart thực hiện
WS-Security ở một mức độ độc lập với các kỹ thuật liên kết dữ liệu mà mã
của bạn sử dụng, do đó nó làm việc với tất cả các hình thức liên kết dữ
liệu được Axis2 hỗ trợ.
Thư mục gốc của mã ví dụ là jws04code. Bên trong thư mục này, bạn sẽ tìm thấy các tệp build.xml và build.properties của Ant, tệp library.wsdl đưa ra định nghĩa dịch vụ cho ứng dụng ví dụ, một tệp log4j.properties được sử dụng để cấu hình đăng nhập phía khách và một số tệp XML định nghĩa thuộc tính (tất cả các tệp có tên dạng XXX-policy-client.xml hoặc XXX-policy-server.xml). Tệp build.properties cấu hình hoạt động của ứng dụng ví dụ. Liệt kê 2 cho thấy phiên bản được cung cấp với tệp các thuộc tính này:
Liệt kê 2. Tệp build.properties được cung cấp
# set axis-home to your Axis2 installation directory axis-home=PATH_TO_AXIS2_INSTALLATION # set the connection protocol to be used to access services (http or https) protocol=http # set the name of the service host host-name=localhost # set the port for accessing the services (change this for monitoring) host-port=8080 # set the base path for accessing all services on the host base-path=/axis2/services/ # set the name of the policy file to be used by the client client-policy=plain-policy-client.xml # set the name of the policy file to be used by the server server-policy=plain-policy-server.xml |
Trước
khi thử các ví dụ này, bạn cần phải chỉnh sửa tệp build.properties và
thiết lập đường dẫn thực tế tới bản cài đặt Axis2 của bạn (với Rampart đã
thêm vào, như đã thảo luận trong phần trước). Nếu bạn đang sử dụng một máy
chủ (host) hay số hiệu cổng khác cho máy chủ của bạn, bạn cũng cần phải
sửa đổi các giá trị host-name và host-port. Tôi sẽ thảo luận về các giá trị còn
lại ở phần sau trong bài viết này
WS-Security xác định
một số kiểu thẻ bài (tokens) (bao gồm các thẻ bài là một phần của đặc tả
cốt lõi và những thẻ bài được định nghĩa trong lược thảo như các
phần mở rộng trình cắm thêm (plug-in) cho đặc tả đó), với nhiều tùy chọn
để xây dựng và sử dụng các thẻ bài như thế nào. Mục đích của bài viết này
là cấu hình và sử dụng Rampart với Axis2, vì vậy tôi sẽ chỉ sử dụng thẻ
bài có ích đơn giản nhất làm một ví dụ: thẻ bài UsernameToken, được định nghĩa bởi lược thảo UsernameToken.
WS-SecurityPolicy của UsernameToken
Mục đích của một UsernameToken chỉ là
để chuyển tải thông tin về tên người dùng và mật khẩu như một phần của các
tiêu đề WS-Security. Dạng cơ bản nhất của UsernameToken gửi cả tên người dùng và mật khẩu dưới dạng văn
bản tường minh. Đây không phải là tối ưu, theo quan điểm an ninh (mặc dù
không có gì sai với việc sử dụng cách tiếp cận này trên các kết nối an
toàn), nhưng thật dễ dàng để nhìn thấy những gì đang gửi đi, tạo cho nó
một điểm khởi đầu có ích.
Cấu hình WS-SecurityPolicy cho một UsernameToken được gửi dưới dạng văn bản có thể
đơn giản như hiển thị trong Liệt kê 3. Chính sách
này (khi hiển thị ở đây, một dòng được phân tách thành hai dòng để vừa
chiều rộng trang — không hợp lệ cho việc sử dụng thực tế)
bao gồm một trình bao gói (wrapper) WS-Policy tiêu chuẩn (các phần tử có
sử dụng tiền tố wsp) bọc bên ngoài một xác nhận
UsernameToken của
WS-SecurityPolicy.
Liệt kê 3. WS-SecurityPolicy của
UsernameToken văn bản tường minh
<wsp:Policy wsu:Id="UsernameToken" xmlns:wsu=
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:SupportingTokens
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<sp:UsernameToken sp:IncludeToken="http://docs.oasis-open.org/
ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient"/>
</wsp:Policy>
</sp:SupportingTokens>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy> |
UsernameToken trong Liệt kê
3 sử dụng một thuộc tính IncludeToken
để xác định kiểu luồng thông báo cần phải có thêm thẻ bài —
trong trường hợp này, tất cả các luồng thông báo đi từ bên đưa ra một yêu
cầu (có nghĩa là máy khách) đến bên nhận một yêu cầu (máy chủ). Bạn có thể
sử dụng các giá trị khác đã định nghĩa cho thuộc tính IncludeToken để chỉ định việc sử dụng thẻ bài, nhưng đối với
một UsernameToken nói chung đây là giá trị duy
nhất có ý nghĩa.
WS-Policy và WS-SecurityPolicy được thiết kế để hỗ
trợ nhúng trong các định nghĩa dịch vụ WSDL. Các tham chiếu được sử dụng
để kết hợp một chính sách với một hoặc nhiều định nghĩa <wsdl:binding>, <wsdl:binding>/<wsdl:operation>, hoặc <wsdl:message>. Axis2 1.4.x thực hiện việc xử lý sơ bộ
cho các chính sách nhúng trong WSDL, nhưng với Axis2 1.4.1 việc triển khai
thực hiện chưa mạnh. Thay vào đó bài viết này gắn các chính sách trực tiếp
tới máy khách và máy chủ để tương thích với mã 1.4.1.
Đối với phía máy chủ, bạn áp dụng một chính sách bằng cách
thêm nó vào tệp cấu hình services.xml được bao gồm trong tệp lưu trữ dịch
vụ .aar của Axis2. Chính sách này có thể được thêm trực tiếp như là phần
tử con của một phần tử <service> để áp
dụng cho tất cả các hoạt động được dịch vụ đó định nghĩa. Bạn cũng cần
phải thêm một phần tử <module> vào tệp
services.xml để nói cho Axis2 rằng mô đun Rampart phải được bao gồm vào
trong cấu hình cho dịch vụ này. Liệt kê 4 là một
phiên bản đã chỉnh sửa của services.xml được sử dụng bởi ứng dụng ví dụ,
đã in đậm tham chiếu mô-đun và thông tin chính sách được bổ sung
thêm:
Liệt kê 4. services.xml với chính sách đã nhúng thêm
<serviceGroup>
<service name="library-username">
<messageReceivers>
<messageReceiver
class="com.sosnoski.ws.library.adb.LibraryUsernameMessageReceiverInOut"
mep="http://www.w3.org/ns/wsdl/in-out"/>
</messageReceivers>
<parameter
name="ServiceClass">com.sosnoski.ws.library.adb.LibraryUsernameImpl</parameter>
<parameter name="useOriginalwsdl">true</parameter>
<parameter name="modifyUserWSDLPortAddress">true</parameter>
<operation mep="http://www.w3.org/ns/wsdl/in-out" name="getBook"
namespace="http://ws.sosnoski.com/library/wsdl">
<actionMapping>urn:getBook</actionMapping>
<outputActionMapping>http://.../getBookResponse</outputActionMapping>
</operation>
...
<module ref="rampart"/>
<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
xmlns:wsu="http://.../oasis-200401-wss-wssecurity-utility-1.0.xsd"
wsu:Id="UsernameToken">
<wsp:ExactlyOne>
<wsp:All>
<sp:SupportingTokens
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<sp:UsernameToken
sp:IncludeToken="http://.../IncludeToken/AlwaysToRecipient">
<wsp:Policy>
<sp:HashPassword/>
</wsp:Policy>
</sp:UsernameToken>
</wsp:Policy>
</sp:SupportingTokens>
<ramp:RampartConfig xmlns:ramp="http://ws.apache.org/rampart/policy">
<ramp:passwordCallbackClass>...PWCBHandler</ramp:passwordCallbackClass>
</ramp:RampartConfig>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
</service>
</serviceGroup> |
Nếu bạn so sánh các chính sách nhúng trong Liệt kê 4 với các chính sách cơ bản trong Liệt kê 3, bạn sẽ thấy một phần tử được thêm vào —
phần tử <ramp:RampartConfig>. Phần tử này
cung cấp các phần mở rộng đặc thù của Rampart cho thông tin chính sách,
trong trường hợp này là đưa ra tên của một lớp được sử dụng để xử lý các
cuộc gọi lại mật khẩu. Cuộc gọi lại là cách để mã máy chủ của bạn có thể
xác minh tổ hợp tên người dùng và mật khẩu được cung cấp bởi máy khách khi
có một yêu cầu.
Liệt kê 5 cho thấy việc thực hiện thực tế của lớp gọi lại, được áp dụng cho mật khẩu văn bản tường minh. Trong trường hợp này, cả hai tên người dùng và mật khẩu được cung cấp cho cuộc gọi lại và tất cả những thứ mà các cuộc gọi lại cần làm là xác minh tổ hợp đó. Nếu tên người dùng và mật khẩu khớp với giá trị dự kiến, chỉ đơn giản trả về; nếu không, nó đưa ra một lỗi ngoại lệ để báo hiệu có lỗi.
Liệt kê 5. Mã gọi lại mật khẩu
import org.apache.ws.security.WSPasswordCallback;
public class PWCBHandler implements CallbackHandler
{
public void handle(Callback[] callbacks)
throws IOException, UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
WSPasswordCallback pwcb = (WSPasswordCallback)callbacks[i];
String id = pwcb.getIdentifer();
if (pwcb.getUsage() == WSPasswordCallback.USERNAME_TOKEN_UNKNOWN) {
// used when plain-text password in message
if (!"libuser".equals(id) || !"books".equals(pwcb.getPassword())) {
throw new UnsupportedCallbackException(callbacks[i], "check failed");
}
}
}
}
} |
Đối với một ứng dụng thực tế, lẽ tự nhiên là bạn muốn sử dụng một số cơ chế khác (chẳng hạn như một cơ sở dữ liệu hoặc một cơ chế an ninh bên ngoài) để xác minh tổ hợp tên người dùng và mật khẩu. Kỹ thuật gọi lại cho phép bạn sử dụng bất kỳ kỹ thuật xác nhận hợp lệ nào mà bạn muốn như là một phần mở rộng của việc xử lý an ninh Rampart.
Để sử dụng Rampart cho mã máy khách của bạn, trước tiên bạn cần phải có sẵn mô đun để sử dụng với Axis2. Bạn có thể làm điều này bằng cách cấu hình một cấu trúc kho lưu trữ Axis2 cho máy khách, nhưng nói chung sẽ dễ dàng hơn khi bao gồm thêm tệp mô đun rampart.mar (và bất kỳ các module nào khác mà bạn cần phải sử dụng) vào trong đường dẫn lớp của bạn. Ví dụ được cung cấp sử dụng cách tiếp cận đường dẫn lớp.
Sau đó, bạn cần phải cấu hình chính sách an ninh và bất kỳ các tham số nào có liên quan cho máy khách. Cách dễ nhất để xử lý cấu hình này là thiết lập các giá trị trực tiếp trên gốc dịch vụ. Liệt kê 6 cho thấy cấu hình được thực hiện trong mã ví dụ này như thế nào:
Liệt kê 6. Cấu hình máy khách
/**
* Load policy file from classpath.
*/
private static Policy loadPolicy(String name) throws XMLStreamException {
ClassLoader loader = WebServiceClient.class.getClassLoader();
InputStream resource = loader.getResourceAsStream(name);
StAXOMBuilder builder = new StAXOMBuilder(resource);
return PolicyEngine.getPolicy(builder.getDocumentElement());
}
public static void main(String[] args) throws IOException, XMLStreamException {
// check for required command line parameters
if (args.length < 4) {
System.out.println("Usage:\n java " +
"com.sosnoski.ws.library.adb.WebServiceClient protocol host port path");
System.exit(1);
}
// create the client stub
String target = args[0] + "://" + args[1] + ":" + args[2] + args[3];
System.out.println("Connecting to " + target);
LibraryUsernameStub stub = new LibraryUsernameStub(target);
// configure and engage Rampart
ServiceClient client = stub._getServiceClient();
Options options = client.getOptions();
options.setProperty(RampartMessageData.KEY_RAMPART_POLICY,
loadPolicy("policy.xml"));
options.setUserName("libuser");
options.setPassword("books");
client.engageModule("rampart");
|
Phần
cấu hình là khối mã cuối cùng trong Liệt kê 6. Nó lấy cá thể org.apache.axis2.client.ServiceClient từ gốc dịch
vụ được tạo ra và thiết lập thông tin chính sách (được nạp từ đường dẫn
lớp) và tên người dùng/mật khẩu trong các tùy chọn của máy khách. Sau đó
nó gắn mô đun Rampart vào trong cấu hình Axis2 mà máy khách sử dụng. Một
khi điều này được thực hiện, bạn có thể sử dụng gốc này để truy cập dịch
vụ giống như bạn làm khi không có WS-Security và Rampart tự động thêm
UsernameToken cho mỗi yêu cầu.
Với Ant
đã cài đặt, bạn có thể chỉ cần chạy ant từ một
cửa sổ dòng lệnh mở trong thư mục mã ví dụ để xây dựng cả mã máy khách lẫn
mã máy chủ. Sau đó bạn có thể triển khai tệp library-username.aar đã tạo
ra tới bản cài đặt máy chủ Axis2 của bạn (tất nhiên là bản có bao gồm các
tệp .jar và .mar của Rampart) và thử chạy máy khách bằng cách gõ nhập lệnh
ant run trong cửa sổ dòng lệnh. Nếu tất cả
mọi thứ được thiết lập đúng, bạn sẽ thấy xuất hiện kết quả như trong Hình 1:
Hình 1. Kết quả xuất ra cửa sổ dòng lệnh khi chạy ứng dụng
Tất nhiên, nếu chỉ chạy máy khách với máy chủ thì sẽ không hiển thị cho bạn
những gì đang xảy ra. Bạn có thể sử dụng một công cụ ví dụ như TCPMon để
hành động như một bên trung gian giữa máy khách và máy chủ và nắm bắt sự
trao đổi thông báo để xem UsernameToken đang
hoạt động thế nào (xem Tài nguyên). Để làm điều
này, trước tiên bạn cần phải thiết lập TCPMon và chấp nhận các kết nối từ
máy khách tới một cổng, sau đó nó chuyển tiếp tới máy chủ đang chạy trên
một cổng khác (hoặc một máy chủ khác). Rồi sau đó bạn có thể chỉnh sửa tệp
build.properties và thay đổi giá trị host-port
thành cổng nghe của TCPMon. Nếu bạn một lần nữa nhập ant run trong cửa sổ dòng lệnh, thì bạn sẽ thấy các thông điệp
được trao đổi. Liệt kê 7 hiển thị một ví dụ bắt
giữ thông điệp của máy
khách:
Liệt kê 7. Thông báo của máy khách với
UsernameToken
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<wsse:Security xmlns:wsse="...wss-wssecurity-secext-1.0.xsd"
soapenv:mustUnderstand="1">
<wsse:UsernameToken xmlns:wsu="...wss-wssecurity-utility-1.0.xsd"
wsu:Id="UsernameToken-1815911473">
<wsse:Username>libuser</wsse:Username>
<wsse:Password Type="...wss-username-token-profile-1.0#PasswordText"
>books</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<ns2:getBooksByType xmlns:ns2="http://ws.sosnoski.com/library/wsdl">
<ns2:type>scifi</ns2:type>
</ns2:getBooksByType>
</soapenv:Body>
</soapenv:Envelope> |
Một UsernameToken văn bản
tường minh cơ sở không trực tiếp cung cấp nhiều bảo đảm an ninh, vì cả hai
tên người dùng lẫn mật khẩu tương ứng đều nhìn thấy được với bất cứ ai có
khả năng theo dõi một thông điệp. Nếu bạn sử dụng một kênh truyền dẫn được
mật mã hóa, điều này không thực sự là một vấn đề — miễn là
việc mật mã hóa kênh là chắc chắn, không có bất kỳ phía bên ngoài nào có
thể theo dõi một thông điệp. Thật thuận tiện là WS-SecurityPolicy đã định
nghĩa một cách để bắt buộc sử dụng một kênh mật mã hóa, như thể hiện trong
Liệt kê 8 (một lần nữa, dòng mã đã được chia
cắt ra cho vừa với chiều rộng trang — hãy xem tệp
secure-policy-server.xml của gói mã ví dụ để thấy một chính sách thực
sự):
Liệt kê 8. Chính sách yêu cầu kết nối HTTPS
<wsp:Policy wsu:Id="UsernameToken" xmlns:wsu=
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:TransportBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
<wsp:Policy>
<sp:TransportToken>
<wsp:Policy>
<sp:HttpsToken RequireClientCertificate="false"/>
</wsp:Policy>
</sp:TransportToken>
</wsp:Policy>
</sp:TransportBinding>
<sp:SupportingTokens
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<sp:UsernameToken sp:IncludeToken="http://docs.oasis-open.org/
ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient"/>
</wsp:Policy>
</sp:SupportingTokens>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
|
Phần
trong Liệt kê 8 hiển thị chữ in đậm là phần được
thêm vào, bao gồm một phần tử <sp:TransportBinding> và phần tử <sp:HttpsToken> được lồng bên trong. Phần tử <sp:HttpsToken> nói rằng một kết nối HTTPS
an toàn phải được sử dụng trong trao đổi thông tin với dịch vụ. Nếu bạn cố
gắng xây dựng service.aar với chính sách này (bằng cách thay đổi giá trị
server-policy trong tệp build.properties
thành secure-policy-server.xml, và sau đó chạy
ant build-server) và triển khai nó, bạn sẽ
thấy rằng Rampart đòi thi hành yêu cầu này, từ chối bất kỳ kết nối HTTP
thông thường nào.
Nếu bạn muốn thử một kết nối HTTPS tới dịch vụ này
bạn có thể làm như vậy, nhưng trước tiên bạn cần phải cấu hình máy chủ Web
của bạn để hỗ trợ HTTPS. (Tomcat có các hướng dẫn tốt cho điều này, tại
//tomcat-docs/ssl-howto.html). Bạn cũng cần phải thay đổi giá trị của
protocol (giao thức) trong tệp
build.properties thành https, và nếu bạn đang
sử dụng giấy chứng nhận tự ký cho máy chủ Web, bạn cần phải chuyển một kho
lưu trữ tin cậy tới máy khách khi chạy đích test của Ant. Tệp build.xml được cung cấp có một dòng, đã bị
đánh dấu chú thích, để làm điều này, vì vậy bạn chỉ cần bỏ dấu chú thích ở
đầu dòng này và thiết lập vị trí của tệp kho lưu trữ tin cậy thích hợp
trên hệ thống của bạn.
Một cách khác để làm cho UsernameToken làm việc an toàn hơn, thậm chí trên các đường
liên kết không được mật mã hóa. Phương pháp này sử dụng một giá trị
digest được tính toán trên một chuỗi ký tự, được tạo thành từ
hai giá trị văn bản khác, kết hợp với mật khẩu. Một trong hai giá trị văn
bản ấy nonce (lúc này), là một giá trị ngẫu nhiên được bên gửi tạo
ra cho mỗi yêu cầu. Giá trị kia, dấu ấn thời gian tạo lập, chính là thời
điểm khi bên gửi đã tạo ra UsernameToken. Cả
hai giá trị này được gồm chứa trong UsernameToken dưới dạng văn bản rõ. Khi được cả máy khách và
máy chủ sử dụng đúng, tổ hợp của các giá trị này với mật khẩu trong digest
làm cho máy chủ có khả năng kiểm tra rằng đã sử dụng một mật khẩu đúng khi
tạo digest, trong khi bất kỳ phía bên ngoài nào rất khó làm giả mật khẩu
hợp lệ. Liệt kê 9 cho một ví dụ chính sách để sử
dụng mật khẩu digest, tiếp theo là bắt giữ thực tế một thông báo khi sử
dụng mật khẩu digest (cả hai được định dạng lại để vừa với chiều rộng
trang — xem tệp hash-policy-client.xml để thấy chính sách
thực sự). Các điểm khác biệt với chính sách ban đầu lại một lần nữa được
in
đậm.
Liệt kê 9. Chính sách sử dụng mật khẩu digest
<wsp:Policy wsu:Id="UsernameToken" xmlns:wsu=
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
<wsp:ExactlyOne>
<wsp:All>
<sp:SupportingTokens
xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
<wsp:Policy>
<sp:UsernameToken sp:IncludeToken="http://docs.oasis-open.org/
ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
<wsp:Policy> <sp:HashPassword/> </wsp:Policy>
</sp:UsernameToken>
</wsp:Policy>
</sp:SupportingTokens>
</wsp:All>
</wsp:ExactlyOne>
</wsp:Policy>
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<wsse:Security xmlns:wsse=".../oasis-200401-wss-wssecurity-secext-1.0.xsd"
soapenv:mustUnderstand="1">
<wsse:UsernameToken xmlns:wsu="...wss-wssecurity-utility-1.0.xsd"
wsu:Id="UsernameToken-1421876889">
<wsse:Username>libuser</wsse:Username>
<wsse:Password Type="...wss-username-token-profile-1.0#PasswordDigest"
>/Wt/2yDdZwa8a5qd7U70hrp29/w=</wsse:Password>
<wsse:Nonce>4ZQz5ytME/RXfChuKJ03iA==</wsse:Nonce>
<wsu:Created>2009-03-17T11:20:57.467Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<ns2:getBooksByType xmlns:ns2="http://ws.sosnoski.com/library/wsdl">
<ns2:type>scifi</ns2:type>
</ns2:getBooksByType>
</soapenv:Body>
</soapenv:Envelope> |
Trong bài viết này, bạn đã thấy cách sử dụng Axis2 và Rampart để xử lý một hình thức cơ bản của WS-Security dựa trên chính sách. Trong bài viết Java Web services tiếp theo, bạn sẽ tìm hiểu về hai đặc tính mạnh của WS-Security: mật mã hóa và các chữ ký XML Sử dụng mật mã hóa XML cho phép bạn giữ bí mật nội dung thông báo của bạn khi vận hành trên bất kỳ kiểu kết nối nào, ngay cả khi các bên trung gian không đáng tin cậy tham gia vào việc xử lý. Sử dụng các chữ ký XML cung cấp cho bạn đảm bảo rằng các thông điệp thực sự từ người nhận là đã khởi tạo yêu cầu và rằng nội dung thông điệp đã không bị giả mạo trong lúc truyền dẫn. Mật mã hóa và chữ ký là cơ sở cho hầu hết các triển khai thực hiện an ninh doanh nghiệp, do đó hãy đọc lại để xem bạn có thể áp dụng các đặc tính này trong các dịch vụ Web riêng của bạn như thế nào.
| Mô tả | Tên | Kích thước | Phương thức tải |
|---|---|---|---|
| Source code for this article | j-jws4.zip | 10KB | HTTP |
Học tập
- Java Web services (Dennis Sosnoski, developerWorks):
Đọc toàn bộ loạt bài này.
- "Các dịch vụ Web Java: Liên kết dữ liệu Axis2" (Dennis Sosnoski,
developerWorks, 7. 2007) bàn về các tùy chọn liên kết dữ liệu chính cho
Axis2. Mã ví dụ mẫu của nó là cơ sở của mã mẫu cho chuyên mục
này.
-
Apache Axis2/Java:
Truy cập vào trang chủ của dự án với máy dịch vụ Web Axis2.
-
Rampart: Tìm hiểu
thêm về mô đun WS-Security của Rampart cho Axis2.
- "Các dịch vụ Web và kiến trúc Axis2" (Eran Chinthaka,
developerWorks, 11.2006): Tìm hiểu cách các mô đun như Rampart mở rộng
Axis2 như thế nào.
-
Hiểu các đặc tả các dịch vụ Web: Loạt bài các hướng dẫn này giới
thiệu nhiều tiêu chuẩn dịch vụ Web quan trọng, bao gồm:
- "Hiểu đặc tả các dịch vụ Web: Web Service Description Language (WSDL-Ngôn ngữ mô tả dịch vụ Web)" (Nicholas Chase, developerWorks, 07.2006).
- "Hiểu đặc tả các dịch vụ Web: WS-Security" (Nicholas Chase, developerWorks, 08.2006).
- "Hiểu đặc tả các dịch vụ Web: WS-Policy" (Tyler Anderson, developerWorks, 02.2007).
-
OASIS Web Services Security (WSS) TC: Đây là tổ chức chịu trách
nhiệm về đặc tả WS-Security và các lược thảo thẻ bài. Bạn có thể tìm thấy
ở đây các đường liên kết đến tất cả các phiên bản của các tiêu chuẩn
này.
-
Nhóm công tác về chính sách
các dịch vụ Web W3C: Nhóm này định nghĩa đặc tả
WS-Policy.
-
OASIS Web Services Secure Exchange (WS-SX) TC: Tổ chức này chịu
trách nhiệm về WS-SecurityPolicy và các đặc tả có liên quan.
- Duyệt qua hiệu sách công nghệ để tìm các sách về chủ đề này và các chủ đề
kỹ thuật khác.
-
Vùng công
nghệ Java của developerWorks: Tìm hàng trăm bài viết về mọi khía
cạnh của lập trình Java.
Lấy sản phẩm và công nghệ
-
Apache Axis2: Tải về
bản phát hành Axis2 mới nhất.
-
Rampart: Tải mô
đun Rampart cho Axis2.
-
The Legion of
the Bouncy Castle: Tải về tệp .jar của Bouncy Castle phù hợp với
thời gian chạy Java của bạn.
-
TCPMon: Tải
về tiện ích mã nguồn mở này để theo dõi các kết nối TCP.
Thảo luận
- Đọc các
blog của developerWorks và dành tâm trí cho cộng đồng My developerWorks.
Dennis Sosnoski là một nhà tư vấn và nhà trợ giúp đào tạo chuyên về các dịch vụ Web và SOA dựa trên-Java. Kinh nghiệm phát triển phần mềm chuyên nghiệp của ông trải suốt hơn 30 năm qua, với một thập kỉ cuối tập trung vào các công nghệ XML và Java phía máy chủ. Dennis là nhà phát triển hàng đầu về dụng cụ liên kết dữ liệu XML JiBX mã nguồn mở, cũng là một người có duyên nợ với khung công tác của các dịch vụ Web Apache Axis2. Ông cũng là một trong những thành viên của nhóm chuyên gia đặc tả kỹ thuật của Jax-WS 2.0 và JAXB 2.0. Xem trang web của ông để có thông tin về các dịch vụ đào tạo và tư vấn của ông.