PCI DSS là gì?

PCI DSS là gì?


Tiêu chuẩn bảo mật PCI DSS (Payment Card Indutry Data Security Standard) được hình thành bởi Hội đồng Tiêu chuẩn Bảo mật - PCI Security Standards Council với các thành viên là các tổ chức cung cấp thẻ tín dụng uy tín hàng đầu như Visa, MasterCard, American Express, Discover Financial Services, JCB International. Tiêu chuẩn này phù hợp với các ngân hàng, website thương mại điện tử, nhằm hỗ trợ các tổ chức thanh toán thẻ hạn chế các rủi ro trong áp dụng CNTT, bảo vệ dữ liệu của khách hàng sử dụng thẻ.


Các ngân hàng, doanh nghiệp Việt Nam muốn áp dụng tiêu chuẩn bảo mật PCI DSS cần sẵn sàng đáp ứng 12 yêu cầu như duy trì hệ thống tường lửa để bảo vệ dữ liệu thẻ, mã hóa thông tin thẻ trên đường truyền khi giao dịch, duy trì hệ thống và ứng dụng đảm bảo an ninh mạng, xây dựng chính sách bảo vệ thông tin...

12 yêu cầu về bảo mật thông tin của PCI DSS:

1. Xây dựng và duy trì hệ thống tường lửa nhằm bảo vệ dữ liệu thẻ thanh toán

2. Không dùng các tham số hoặc mật khẩu được thiết lập sẵn từ các nhà cung cấp hệ thống (thiết bị mạng, đường truyền Internet…)

3. Bảo vệ dữ liệu thẻ thanh toán khi lưu trữ trên hệ thống

4. Mã hóa thông tin thẻ trên đường truyền trong quá trình giao dịch

5. Sử dụng và cập nhật thường xuyên phần mềm phòng chống virus

6. Xây dựng - duy trì hệ thống và các ứng dụng đảm bảo an ninh mạng

7. Hạn chế việc tiếp cận với dữ liệu thẻ thanh toán

8. Cấp phát và theo dõi các tài khoản truy nhập hệ thống

9. Giới hạn các phương pháp tiếp cận vật lý với dữ liệu thẻ

10. Kiểm tra và lưu trữ tất cả các truy nhập vào hệ thống và dữ liệu thẻ

11. Thường xuyên đánh giá và thử nghiệm lại quy trình an ninh hệ thống

12. Xây dựng chính sách bảo vệ thông tin tại doanh nghiệp.



PCI DSS yêu cầu việc đánh giá bảo mật phải được tiến hành ở bên ngoài (Outside) lẫn bên trong (Inside) mạng lưới của tổ chức. Đối với yêu cầu ở bên ngoài, ta có thể giả định rằng đó là môi trường Internet, còn việc xác định điểm bắt đầu để đánh giá bên trong mạng nội bộ có thể gây ra sự nhầm lẫn.


Thông thường giả định được sử dụng nhiều nhất đối với môi trường bên trong mạng nội bộ chính là mạng lưới điện toán thông thường của tổ chức, hoặc bất kỳ mạng lưới nào khác mà người dùng nội bộ được kết nối đến.


Môi trường dữ liệu chủ thẻ (CDE) thường được tách biệt hoàn toàn so với mạng lưới người dùng đầu cuối, điều này sẽ gây khó khăn cho việc tiến hành đánh giá bảo mật khi xuất phát điểm của chúng ta nằm ở mạng lưới người dùng đầu cuối, khía cạnh này là điều rất quan trọng mà chúng ta cần phải cân nhắc. Vì các Firewall đã được triển khai chịu trách nhiệm phân tách môi trường CDE và mạng lưới người dùng đầu cuối sẽ làm giảm bớt khả năng thu thập thông tin về hệ thống (Footprinting) của các chuyên gia đánh giá.

Tổ chức thực hiện loại hình đánh giá này cần phải lưu ý rằng, kết quả của cuộc kiểm tra có thể sẽ không cho thấy được một bức tranh toàn diện về các lỗ hổng trong phạm vi đánh giá.

Phương pháp đánh giá bảo mật truyền thống bao gồm 2 cách tiếp cận : WhiteBoxBlackBox. PCI DSS cũng khá cởi mở về những cách tiếp cận này : Cả hai cách tiếp cận đều được chấp nhận là cách đánh giá bảo mật hợp lệ để đáp ứng yêu cầu 11.3.

Tuy nhiên đối với cách tiếp cận BlackBox, tổ chức bắt buộc phải đảm bảo chuyên gia đánh giá ít nhất phải có thể truy cập được đến tất cả các địa chỉ IP nằm trong phạm vi đánh giá từ xuất phát điểm của anh ta.


pci dss whitebox va blackbox
Ví dụ đối với loại hình đánh giá bảo mật bên ngoài (External), chuyên gia đánh giá bắt buộc phải biết dãy địa chỉ Public IP nằm trong phạm vi đánh giá. Còn một cách tiếp cận đánh giá đặc biệt khác là Blind BlackBox, đây là cách tiếp cận mà gần như tổ chức sẽ không cung cấp bất kỳ thông tin nào cho các chuyên gia đánh giá, cách tiếp cận này phù hợp trong một số hoàn cảnh nhất định.

Tuy nhiên cách tiếp cận này cần phải tránh hoàn toàn đối với PCI DSS, vì các QSAs có thể thấy rằng phạm vi đánh giá chưa bao gồm tất cả các hệ thống có liên quan (Do các chuyên gia đánh giá có thể không tìm thấy được mục tiêu).
Hướng dẫn remote debug server glassfish

Hướng dẫn remote debug server glassfish

Chúng ta vẫn hay dùng các IDE như NetBeans, Eclipse để debug một ứng dụng bằng cách right click vào project và chọn debug. Việc này thật là simple trên máy local nhưng để chuyển sang debug ở máy server từ xa thì làm cách nào? Trong bài này tôi sẽ hướng dẫn cho các bạn cách remote debug server glassfish bằng IDE NetBeans. Để debug một ứng dụng từ xa trên server glassfish ta phải chắc chắn rằng server này đang chạy ở chế độ debug.

1. Chạy server ở mode debug

Cách 1:

Vào thư mục bin của glassfish gõ lệnh sau
  asadmin
  start-domain --debug=true

Cách 2:

Cấu hình JVM Setting trong server-config tại màn hình glassfish admin.
Chắc chắn rằng server glassfish đang chạy bạn vào màn hình admin bằng đường dẫn sau:
http://localhost:4848/common/index.jsf

Tại màn hình glassfish admin bạn vào đường dẫn sau  Configurations > server-config > JVM Setting để enable debug.

Enable remote debug cho glassfish server

H1. Enable remote debug cho glassfish server

Note: Port 9009 là port debug mặc định của glassfish

Sau khi enable debug xong ta save lại và restart lại glassfish. Lúc này server của chúng ta đã sẵn sàng cho việc debug.

 2. Dùng IDE NetBeans để debug ứng dụng ở port 9009


Ta mở IDE NetBeans lên vào menu Debug > Attach Debug sẽ xuất hiện màn hình Attach như bên dưới. 

Host: Bạn nhập địa chỉ IP máy server
Port: 9009


NetBeans Attach debug remote server



H2 - NetBeans Attach debug remote server.

 Sau khi điền đầy đủ thông tin về Host, Port bạn click 'OK' Netbeans sẽ chuyển qua chế độ debug. Bạn debug như bình thường tại local.

Good luck.!

Glassfish Server là gì? Hướng đẫn download và cài đặt Glassfish Server.

Glassfish Server là gì? Hướng đẫn download và cài đặt Glassfish Server.


1. Giới thiệu

Glassfish server là một application server mã nguồn mở được phát triền dựa trên nền JavaEE hổ trợ đầy đủ các tính năng cần thiết của JavaEE như web ứng dụng, Enterprise JavaBeans, JPA, JavaServer Faces, JMS, RMI, JavaServer Pages, Servlets, etc. Nó cho phép những nhà phát triển ứng dễ quản lý, cấu hình nhanh và linh hoạt. Glass server support nhiều nền tảng như windows, Linux, Mac Os... 

2. Cài đặt glassfish server

a. Dowload glassfish

Bạn có thể download glassfish từ:  https://glassfish.java.net/download.html 


Download và cài đặt glassfish server.

H2.1 - Download và cài đặt glassfish server. 

Sau khi tải về bạn giải nén file ‘glassfish­-4.1.zip’ vào nơi cần thiết.

b. Chạy glassfish

Từ thư mục cài đặt glassfish ta gõ lệnh sau để chạy server 

./bin/asadmin start­domain

Sau khi server chạy xong ta vào màn hình quản trị bằng link sau:
http://localhost:4848
login với user là admin / password để trống hoặc 'changeit'.



H2.2 - Màn hình login glassfish. 

Sau khi login thành công bạn sẽ vào trang quản trị của glassfish server.

glassfish admin.

H2.3 - Màn hình glassfish admin. 

Glassfish default administrator values

H2.4 - Bảng giá trị  glassfish server. 

c. Stop và start glassfish

Start glassfish : asadmin start­domain 
Stop glassfish : asadmin stop­domain

d. Deploy và undeploy ứng dụng

Deploy ứng dụng : asadmin deploy [tên file ứng dụng] 
Undeploy ứng dụng: asadmin undeploy [tên ứng dụng]

3. Dùng glassfish với IDE

Ngoài ra chúng ta có thể dùng một số IDE như Eclipse, Netbeans để chạy và quản lý ứng dụng với server glassfish.


Glassfish trên IDE Netbeans.

H3.1 - Glassfish trên IDE Netbeans.

4. Kết luận

Glassfish server là một trong những server có đầy đủ các chức năng để chạy các ứng dụng Java web, Java EE. Chúng ta sử dụng Glassfish server cho những ứng dụng lớn như ngân hàng, tài chính có nhiều thành viên và đòi hỏi độ bảo mật cao.

Đối với những nhà lập trình, sử dụng Glassfish server nên tích hợp vào những IDE như eclipse, netbeans để thao tác nhanh hơn và nâng cao hiệu quả công việc. 



(Hai Nguyen) 
Exception là gì? Cách quản lý lỗi tốt nhất trong Java.

Exception là gì? Cách quản lý lỗi tốt nhất trong Java.

1. Exception là gì?

Exception là một sự kiện xảy ra trong quá trình thực thi một chương trình Java nó làm phá vỡ cái flow bình thường của một chương trình.

Khi một lỗi xảy ra trên một method, method đó sẽ tạo ra một object và đưa nó vào Runtime System. Object đó được gọi là Exception Object, nó chứa tất cả các thông tin về lỗi và trạng thái của chương trình khi xảy ra lỗi. Sau đó Runtime System sẽ xử lý sẽ tìm cách xử lý lỗi này.

Quá trình xử lý Exception được gọi là catch Exception, nếu Runtime System không xử lý được ngoại lệ thì chương trình sẽ kết thúc.  

2. Mô hình Exception trong Java


Exception in Java


Mô hình exception trong Java


3. Các loại Exception trong Java

Trong Java có 2 loại Exception là Checked exceptionsUnChecked exceptions.


Checked exceptions:

Là loại exception xảy ra trong lúc compile time, nó cũng có thể được gọi là compile time exceptions. Loại exception này không thể bỏ qua được trong quá trình compile, bắt buộc ta phải handle nó.

Ví dụ: IOException, FileNotFoundException....

UnChecked exceptions:

Là loại exception xảy ra tại thời điểm thực thi chương trình, nó cũng có thể gọi là runtime exceptions đó là programming bugs, lỗi logic của chương trình... Loại exception này được bỏ qua trong quá trình compile, không bắt buộc ta phai handle nó.

Ví dụ: NumberFormatException, ArrayIndexOutOfBoundsException...

Errors: 

Là những vấn đề nghiêm trọng liên quan đến môi trường thực thi của ứng dụng, hệ thống. Nó thường làm chết chương trình.

Ví dụ: OutOfMemoryError, LinkageError, and StackOverflowError.

4. Cách bắt lỗi trong Java

Để bắt lỗi trong Java ta sử dụng từ khóa try - catchfinally blocks. Ta cũng có thể dùng try-with-resources có từ Java 7. try-with-resources được dùng riêng biệt trong trường hợp xử dụng Closeable resources như là streams.
Java try catch and finally

Có 2 cách xử lý lỗi trong Java là xử lý lỗi trực tiếp bằng try-catch và xử lý lỗi giáng tiếp bằng throws 

a. try-catch:

Xử lý lỗi tại chổ tại khối lệnh có thể phát sinh ra lỗi và chương trình có thể chạy tiếp những lệnh tiếp theo. Hoặc là bắt lỗi để chuyển thành một lỗi khác và đưa ra ngoài xử lý.

Cú pháp:

Single catch block
cu phap try catch java

Multiple catch blocks
cu phap try catch java


Ví dụ:

Kết quả:

Error: String index out of range: -20
After error..
continuing........

Ta thấy rằng sau khi xảy ra lỗi chương trình vẫn tiếp tục chạy những lệnh tiếp theo..

b. throws:

Là để ném lỗi ra ngoài để xử lý lỗi.. không chạy tiếp những lệnh tiếp theo trong method sau khi đã ném lỗi.

Ví dụ:


Kết quả:

Error: Get name has error..
Finish........

Ta thấy sau khi ném lỗi StringIndexOutOfBoundsException ra ngoài thì "continuing........" không được in ra.. tức là những lệnh tiếp theo không được chạy. Và lỗi này đã được đưa ra ngoài đễ xử lý.

Note: 
  • Throw: để quăng ra Exception ở bất kỳ dòng nào trong phương thức (sau đó dùng try-catch để bắt hoặc throws cho thằng khác sử lý)
  • Throws: Chỉ có phương thức mới được sử dụng. Khi một phương thức có throw bên trong mà không bắt lại (try – catch) thì phải ném đi (throws) cho thằng khác xử lý.
Hướng Dẫn Cấu Hình HTTPS - SSL CHO TOMCAT (How to configure Tomcat to support https or SSL)

Hướng Dẫn Cấu Hình HTTPS - SSL CHO TOMCAT (How to configure Tomcat to support https or SSL)

1. Tạo Keystore

Chắc chắn rằng máy tính của bạn đã cài Java JDK, đã tạo biến môi trường JAVA_HOME PATH tới %JAVA_HOME%/bin. Nếu chưa hãy xem lại bài viết này:
http://hainguyenngoc.blogspot.com/p/huong-dan-download-cai-at-java.html

Để tạo keystore ta dùng công cụ keytool (Key and Certificate Management Tool) của java. Bạn mở cmd (command line) và gõ lệnh sau:


keytool -genkey -alias tomcat -keypass changeit -keyalg RSA -keystore D:\mykeystore.jks

Sau đó bạn đặt password và các thông tin cần thiết của chuẩn X.509 certificate
(Passwod thường dùng là changeit)




File mykeystore.jks sẽ được lưu ở ổ đĩa D: (mặc định nếu ta không chỉ định thư mục lưu nó sẽ tạo ra tại thư mực C:\Users\<your user>)

Note: Nếu trong quá trình tạo keystore bạn gặp lỗi " (A required privilege is not held by the client)"  thì hãy kiểm tra lại quyền truy cập của user.


Để biết thêm về keytool bạn xem tại đây



2. Cấu hình Connector trong file server.xml

Sau khi đã  tạo keystore xong bạn vào thư mục tomcat server mở file %Tomcat_Home%\conf\server.xml lên và thêm vào thẻ connector để support https  /SSL.
(Thẻ này đã có trong file server.xml nhưng đã được comment bạn tìm và bỏ comment đi)

 
 <!-- Define a SSL HTTP/1.1 Connector on port 8443
         This connector uses the JSSE configuration, when using APR, the 
         connector should be using the OpenSSL style configuration
         described in the APR documentation -->

 <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
               maxThreads="150" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS" 
        keystoreFile="D:\mykeystore.jks"
        keystorePass="changeit" /
Note:   keystorePass="changeit" là password của keystore đã được tạo ra bằng "keytool" ở bước 1.

3. Kiểm tra kết quả

Save lại file server.xml và mở trinh duyệt nhập link : https://localhost:8443/

!@Good luck...
Ajax Websocket là gì? Các kỹ thuật Reverse Ajax.

Ajax Websocket là gì? Các kỹ thuật Reverse Ajax.

Ajax (Asynchronous JavaScript và XML), một kỹ thuật dành cho trình duyệt dựa trên JavaScript, cho phép sử dụng một đoạn mã lệnh để đáp ứng các yêu cầu HTTP cho từng thành phần mà không cần phải refresh lại toàn bộ trang web. Ajax đã được ứng dụng hơn 10 năm nay. Mặc dù tên của nó có kèm theo XML, nhưng bạn có thể truyền tải bất cứ thứ gì trong một yêu cầu Ajax. Dữ liệu được sử dụng phổ biến nhất là JSON, nó có cú pháp gần với cú pháp của JavaScript và tiêu thụ ít băng thông hơn. Liệt kê 1 là ví dụ về một yêu cầu Ajax để lấy ra tên của một vùng địa phương từ mã bưu chính của nó.
Liệt kê 1. Ví dụ về yêu cầu Ajax
var url = 'http://www.geonames.org/postalCodeLookupJSON?postalcode=' 
    + $('#postalCode').val() + '&country=' 
    + $('#country').val() + '&callback=?'; 
$.getJSON(url, function(data) { 
    $('#placeName').val(data.postalcodes[0].placeName); 
});
Bạn có thể xem cách hoạt động của ví dụ trên trong file listing1.html có ở đây.
Về cơ bản Reverse Ajax là một khái niệm: có thể gửi dữ liệu từ máy chủ đến máy khách. Trong một yêu cầu Ajax của HTTP tiêu chuẩn, dữ liệu được gửi đến máy chủ. Reverse Ajax có thể được mô phỏng để tạo ra một yêu cầu Ajax, theo những cách cụ thể được nêu ra trong bài viết này, do đó, máy chủ có thể gửi các sự kiện đến máy khách càng nhanh càng tốt (giao tiếp với độ trễ thấp).
WebSockets, có kèm theo HTML5, là một kỹ thuật mới hơn. Nhiều trình duyệt đã hỗ trợ nó (Firefox, Google Chrome, Safari và những trình duyệt khác). WebSockets tạo nên các kênh truyền thông song song, hai chiều. Kết nối này được mở ra thông qua một yêu cầu HTTP được gọi là WebSockets handshake với một số header đặc biệt. Kết nối này được duy trì và bạn có thể viết và nhận dữ liệu bằng JavaScript, như thể bạn đang sử dụng một TCP socket nguyên bản. WebSockets sẽ được trình bày sau.

Các kỹ thuật Reverse Ajax

Mục tiêu của kỹ thuật Reverse Ajax là giúp các máy chủ đẩy thông tin đến máy khách. Theo mặc định các yêu cầu Ajax là không chính thống và chỉ có thể được bắt đầu từ máy khách đến máy chủ. Bạn có thể vượt qua hạn chế này bằng cách sử dụng các kỹ thuật để mô phỏng truyền thông đáp ứng giữa máy chủ và máy khách.

HTTP polling và JSONP polling

Polling bao gồm việc gửi một thông điệp từ phía máy khách đến máy chủ để yêu cầu một thông tin dữ liệu nào đó. Thực ra đây chỉ là một yêu cầu HTTP của Ajax. Để có được các sự kiện từ máy chủ càng sớm thì khoảng thời gian polling (thời gian giữa các yêu cầu) phải càng ngắn càng tốt. Có một nhược điểm là: nếu khoảng thời gian này càng ngắn, trình duyệt của máy khách sẽ đưa ra nhiều yêu cầu hơn, trong đó có những yêu cầu sẽ không trả về bất kỳ dữ liệu có ích nào khiến cho băng thông bị hao tốn và xử lý tài nguyên vô ích.
Bảng thời gian trong Hình 1 cho thấy cách mà máy khách gửi các yêu cầu polling nhưng chẳng có thông tin nào được trả về cả. Máy khách phải chờ đến lần polling tiếp theo để có được hai sự kiện do máy chủ thu nhận được.
Hình 1. Reverse Ajax với việc polling của HTTP
Sơ đồ mô tả yêu cầu HTTP hỏi vòng Ajax được gửi mỗi lần 5 giây. Đáp ứng đầu tiên không chứa dữ liệu nào. Sau đó hai sự kiện đến bên phía máy chủ. Chúng cần chờ hỏi vòng lần thứ hai, khoảng 4 giây sau, để gửi trở lại đáp ứng tới máy khách. Rồi hỏi vòng lần thứ ba không trả về gì cả do không có sự kiện nào xảy ra.
Về bản chất, polling của JSONP giống như polling của HTTP. Tuy nhiên, có sự khác biệt ở chỗ với JSONP bạn có thể đưa ra yêu cầu giữa các domain (các yêu cầu không có trong domain của bạn). JSONP được dùng trong Liệt kê 1 để nhận về một tên địa phương từ một mã bưu chính. Thường thì có thể nhận ra một yêu cầu JSONP bằng cách xem tham số gọi lại và nội dung trả về của nó, đó chính là mã JavaScript có thể chạy được.
Để thực hiện polling trong JavaScript, bạn có thể sử dụng hàm setInterval để định thời gian gửi các yêu cầu Ajax, như trong Liệt kê 2:
Liệt kê 2. Polling trong JavaScript
setInterval(function() { 
    $.getJSON('events', function(events) { 
        console.log(events); 
    }); 
}, 2000);
Đoạn mã demo kỹ thuật polling ở đây cho thấy phương pháp này tiêu thụ băng thông như thế nào. Khoảng thời gian cho các lần polling ngắn nhưng có thể bạn sẽ nhận các kết quả trả về mà chẳng có sự kiện (event) mới nào. Liệt kê 3 hiển thị kết quả của việc polling ở ví dụ mẫu.
Liệt kê 3. Kết quả của đoạn demo polling trong ví dụ mẫu
[client] checking for events... 
[client] no event 
[client] checking for events... 
[client] 2 events 
[event] At Sun Jun 05 15:17:14 EDT 2011 
[event] At Sun Jun 05 15:17:14 EDT 2011 
[client] checking for events... 
[client] 1 events 
[event] At Sun Jun 05 15:17:16 EDT 2011
Polling trong JavaScript có các ưu và nhược điểm.
  • Ưu điểm: Nó thực sự dễ thực hiện và không đòi hỏi bất kỳ tính năng đặc biệt nào ở phía máy chủ. Nó cũng làm việc trong tất cả các trình duyệt.
  • Nhược điểm: Phương pháp này hiếm khi được sử dụng vì nó không hề linh động. Hãy tưởng tượng, giả sử có 100 máy khách, trong đó mỗi máy gửi các yêu cầu polling trong 2 giây thì số lượng băng thông và tài nguyên bị hao tốn như thế nào, ở đây 30% yêu cầu được trả về không hề có chút dữ liệu.

Piggyback

Piggyback polling là một phương pháp thông minh hơn nhiều so với polling đơn thuần vì nó có xu hướng loại bỏ tất cả các yêu cầu không cần thiết (các yêu cầu không trả về dữ liệu nào). Không cần định sẵn một khoảng thời gian interval nào cả; yêu cầu sẽ được gửi đi khi máy khách cần gửi một yêu cầu đến máy chủ. Sự khác biệt nằm ở cách phản hồi được chia thành hai phần: phản hồi với dữ liệu được yêu cầu và các sự kiện từ máy chủ. Hình 2 chính là ví dụ.
Hình 2. Reverse Ajax với Piggyback polling
Sơ đồ mô tả máy khách gửi một yêu cầu gửi lên và nhận một đáp ứng hỗn hợp. Không có sự kiện nào xuất hiện trên máy chủ, nên đáp ứng hỗn hợp chỉ chứa đáp ứng của yêu cầu. Sau đó hai sự kiện đến phía máy chủ, nhưng chúng cần chờ yêu cầu máy khách tiếp theo sao cho đáp ứng hỗn hợp sẽ chứa cả hai các sự kiện cộng với dáp ứng của yêu cầu bình thường. Nếu máy khách không khởi động bất kỳ hành động nào, thì các sự kiện đã tới máy chủ sẽ không được gọi ra.
Khi thực hiện kỹ thuật Piggyback, thông thường tất cả các yêu cầu Ajax gửi đến máy chủ có thể được trả về một phản hồi hỗn hợp. Ví dụ mẫu về cách thực hiện kỹ thuật này có ở đây và trong Liệt kê 4 dưới đây.
Liệt kê 4. Ví dụ mẫu về mã piggyback
$('#submit').click(function() { 
    $.post('ajax', function(data) { 
        var valid = data.formValid; 
        // process validation results 
        // then process the other part of the response (events) 
        processEvents(data.events); 
    }); 
});
Liệt kê 5 hiển thị kết quả khi sử dụng phương pháp piggyback.
Liệt kê 5. Kết quả piggyback

[client] checking for events... 
[server] form valid ? true 
[client] 4 events 
[event] At Sun Jun 05 16:08:32 EDT 2011 
[event] At Sun Jun 05 16:08:34 EDT 2011 
[event] At Sun Jun 05 16:08:34 EDT 2011 
[event] At Sun Jun 05 16:08:37 EDT 2011
Bạn có thể thấy kết quả của việc kiểm tra hợp lệ một khuôn mẫu (form validation) và các sự kiện được thêm vào phản hồi. Một lần nữa, phương pháp này có những ưu và nhược điểm.
  • Ưu điểm: Không có các yêu cầu nào trả về mà không có dữ liệu, vì máy khách kiểm soát khi nó gửi các yêu cầu, nên bạn tiêu thụ ít tài nguyên hơn. Nó cũng làm việc trong tất cả các trình duyệt và không yêu cầu các tính năng đặc biệt ở phía máy chủ.

  • Nhược điểm: Bạn sẽ không biết khi nào mà các sự kiện ở phía máy chủ được gửi tới máy khách vì nó đòi hỏi phải có một hành động từ phía máy khách để yêu cầu chúng.


WebSockets

WebSockets mới xuất hiện trong HTML5, là một kỹ thuật Reverse Ajax mới hơn Comet. WebSockets cho phép các kênh giao tiếp song song hai chiều và hiện đã được hỗ trợ trong nhiều trình duyệt (Firefox, Google Chrome và Safari). Kết nối được mở thông qua một HTTP request (yêu cầu HTTP), được gọi là liên kết WebSockets với những header đặc biệt. Kết nối được duy trì để bạn có thể viết và nhận dữ liệu bằng JavaScript như khi bạn đang sử dụng một TCP socket đơn thuần.
Một URL WebSocket được bắt đầu bằng cách gõ ws:// hoặc wss:// (trên SSL).
Hình 1 cho thấy cách giao tiếp khi sử dụng WebSockets. Một liên kết HTTP được gửi đến máy chủ với các header cụ thể. Sau đó, một loại socket Javascript có sẵn trên máy chủ hoặc máy khách sẽ được sử dụng để nhận dữ liệu không đồng bộ thông qua một trình xử lý sự kiện.
Hình 1. Reverse Ajax với WebSockets
Reverse Ajax với WebSockets
Bạn có thể tải về mã nguồn cho bài này. Khi bạn chạy ví dụ này, bạn sẽ thấy kết quả tương tự như Liệt kê 1. Nó cho thấy các sự kiện đã xảy ra bên phía máy chủ và cũng xuất hiện ngay lập tức bên phía máy khách như thế nào. Khi máy khách gửi đi dữ liệu nào đó, máy chủ sẽ báo lại cho máy khách.
Liệt kê 1. Ví dụ mẫu WebSocket bằng JavaScript
[client] WebSocket connection opened 
[server] 1 events 
[event] ClientID = 0 
[server] 1 events 
[event] At Fri Jun 17 21:12:01 EDT 2011 
[server] 1 events 
[event] From 0 : qqq 
[server] 1 events 
[event] At Fri Jun 17 21:12:05 EDT 2011 
[server] 1 events 
[event] From 0 : vv
Thông thường, trong JavaScript bạn sẽ sử dụng WebSockets như được trình bày trong Liệt kê 2, nếu trình duyệt của bạn có hỗ trợ nó.
Liệt kê 2. Mã JavaScript ở máy khách
var ws = new WebSocket('ws://127.0.0.1:8080/async'); 
ws.onopen = function() { 
    // called when connection is opened 
}; 
ws.onerror = function(e) { 
    // called in case of error, when connection is broken in example 
}; 
ws.onclose = function() { 
    // called when connexion is closed 
}; 
ws.onmessage = function(msg) { 
    // called when the server sends a message to the client. 
    // msg.data contains the message. 
}; 
// Here is how to send some data to the server 
ws.send('some data'); 
// To close the socket:
ws.close();
Dữ liệu được gửi và nhận có thể là kiểu bất kỳ nào. Có thể xem WebSockets giống như TCP socket, vì thế tùy thuộc vào máy khách và máy chủ để biết kiểu dữ liệu nào đang được gửi qua. Ví dụ ở Liệt kê 2 đang gửi các chuỗi JSON.
Khi một đối tượng Websocket Javascript được tạo ra, nếu xem kỹ các HTTP request trong giao diện trình duyệt (hoặc Firebug) của lần kết nối đó, bạn sẽ thấy các header đặc trưng của WebSocket. Liệt kê 3 là một ví dụ.
Liệt kê 3. Ví dụ mẫu về HTTP request và các header phản hồi
Request URL:ws://127.0.0.1:8080/async 
Request Method:GET 
Status Code:101 WebSocket Protocol Handshake 

Request Headers 
Connection:Upgrade 
Host:127.0.0.1:8080 
Origin:http://localhost:8080 
Sec-WebSocket-Key1:1 &1~ 33188Yd]r8dp W75q 
Sec-WebSocket-Key2:1   7;    229 *043M 8 
Upgrade:WebSocket 
(Key3):B4:BB:20:37:45:3F:BC:C7 

Response Headers 
Connection:Upgrade 
Sec-WebSocket-Location:ws://127.0.0.1:8080/async 
Sec-WebSocket-Origin:http://localhost:8080 
Upgrade:WebSocket 
(Challenge Response):AC:23:A5:7E:5D:E5:04:6A:B5:F8:CC:E7:AB:6D:1A:39
Các header được dùng trong các liên kết WebSocket để ủy quyền và thiết lập các kết nối long-lived. Đối tượng WebSocket JavaScript cũng chứa hai đặc tính hữu dụng:
ws.url
Trả về URL của máy chủ WebSocket.
ws.readyState
Trả về giá trị của trạng thái kết nối hiện tại:
  • CONNECTING = 0
  • OPEN = 1
  • CLOSED = 2
Về phía máy chủ, việc xử lý WebSockets phức tạp hơn một chút. Vẫn chưa có đặc tả Java chuẩn hỗ trợ WebSockets. Để sử dụng các tính năng WebSockets của web container (ví dụ, Tomcat hoặc Jetty), bạn phải ghép mã ứng dụng với các thư viện đặc thù.
Ví dụ trong thư mục websocket của mã nguồn mẫu sử dụng API WebSocket của Jetty do chúng tôi đang sử dụng Jetty container. Liệt kê 4cho thấy trình xử lý WebSocket. (Phần 3 của loạt bài này sẽ sử dụng các API WebSocket khác nhau cho các tầng bên dưới).
Liệt kê 4. Trình xử lý WebSocket cho một Jetty container
public final class ReverseAjaxServlet extends WebSocketServlet { 
    @Override 
    protected WebSocket doWebSocketConnect(HttpServletRequest request,
                                           String protocol) { 
        return [...] 
    } 
}
Với Jetty, có một số cách để xử lý một liên kết WebSocket. Một cách dễ dàng là phân lớp WebSocketServlet của Jetty và thực thi phương thức doWebSocketConnect Phương thức này sẽ yêu cầu bạn trả về một thể hiện của WebSocket interface. Bạn phải thực thi interface này và trả về một loại thông tin gọi là endpoint đại diện cho liên kết WebSocket. Liệt kê 5 cung cấp một ví dụ mẫu.
Liệt kê 5. Ví dụ về thực thi WebSocket 
class Endpoint implements WebSocket { 

    Outbound outbound; 

    @Override 
    public void onConnect(Outbound outbound) { 
        this.outbound = outbound;    
    } 

    @Override 
    public void onMessage(byte opcode, String data) { 
        // called when a message is received 
        // you usually use this method 
    } 

    @Override 
    public void onFragment(boolean more, byte opcode, 
                           byte[] data, int offset, int length) { 
        // when a fragment is completed, onMessage is called. 
        // Usually leave this method empty. 
    } 

    @Override 
    public void onMessage(byte opcode, byte[] data, 
                          int offset, int length) { 
        onMessage(opcode, new String(data, offset, length)); 
    } 

    @Override 
    public void onDisconnect() { 
        outbound = null; 
    } 
}
Để gửi một thông báo đến máy khách, bạn xuất thông báo ra outbound, như thể hiện trong Liệt kê 6:
Liệt kê 6. Gửi một thông báo đến máy khách
if (outbound != null && outbound.isOpen()) {
    outbound.sendMessage('Hello World !');
}
Để ngắt kết nối máy khách và đóng kết nối WebSocket, hãy sử dụng outbound.disconnect();.
WebSockets là một cách rất mạnh để thực hiện giao tiếp hai chiều mà không có độ trễ nào. Firefox, Google Chrome, Opera và các trình duyệt hiện đại khác đều hỗ trợ nó. Theo trang web jWebSocket:
  • Chrome có WebSockets nguyên gốc kể từ phiên bản 4.0.249.
  • Safari 5.x có WebSockets nguyên gốc.
  • Firefox 3.7a6 và 4.0b1+ có WebSockets nguyên gốc.
  • Opera có WebSockets nguyên gốc kể từ phiên bản 10.7.9067.
Để biết thêm thông tin về jWebSocket, xem phần Tài nguyên.

Ưu điểm 

WebSockets cung cấp khả năng giao tiếp hai chiều mạnh mẽ, có độ trễ thấp và dễ xử lý lỗi. Không cần phải có nhiều kết nối như phương pháp Comet long-polling và cũng không có những nhược điểm như Comet streaming. API cũng rất dễ sử dụng trực tiếp mà không cần bất kỳ các tầng bổ sung nào, so với Comet, thường đòi hỏi một thư viện tốt để xử lý kết nối lại, thời gian chờ timeout, các Ajax request (yêu cầu Ajax), các tin báo nhận và các dạng truyền tải tùy chọn khác nhau (Ajax long-polling và jsonp polling).

Nhược điểm

Những nhược điểm của WebSockets gồm có:
  • Nó là một đặc tả mới của HTML5, nên nó vẫn chưa được tất cả các trình duyệt hỗ trợ.
  • Không có phạm vi yêu cầu nào. Do WebSockets là một TCP socket chứ không phải là HTTP request, nên không dễ sử dụng các dịch vụ có phạm vi-yêu cầu, như SessionInViewFilter của Hibernate. Hibernate là một framework kinh điển cung cấp một bộ lọc xung quanh một HTTP request. Khi bắt đầu một request, nó sẽ thiết lập một contest (chứa các transaction và liên kết JDBC) được ràng buộc với luồng request. Khi request đó kết thúc, bộ lọc hủy bỏ contest này.

Kết luận

WebSockets là một giải pháp Reverse Ajax mạnh, mặc dù còn một vài nhược điểm. Hiện tại nó không được hỗ trợ trên tất cả các trình duyệt và không dễ sử dụng bên phía máy chủ bằng Java mà không có sự giúp đỡ của một thư viện Reverse Ajax. Vì bạn vẫn không sử dụng một kiểu dáng yêu cầu-đáp ứng tiêu chuẩn, nên bạn không thể dựa vào việc thực thi chuỗi bộ lọc cho các phạm vi. Comet và WebSockets yêu cầu các tính năng đặc trưng phía máy chủ của các container, nên bạn cần phải chú ý khi ứng dụng một container mới bởi vì nó có thể sẽ không co giãn được.
(Theo ibm.com)
Hướng đẫn sử dụng Amazon’s S3 với Java

Hướng đẫn sử dụng Amazon’s S3 với Java

Trong hướng dẫn này, tôi sẽ giải thích làm thế nào để sử dụng lưu trữ S3 của Amazon với các API Java được cung cấp bởi Amazon. Các ví dụ cho bạn thấy làm thế nào để tạo ra một bucket, liệt kê nội dung của bucket, tạo ra một folder vào một bucket, upload một file, cung cấp quyền truy cập cho các file và cuối cùng là làm thế nào để xóa tất cả những thứ đã tạo ra.

Tạo tài khoản Amazon


Mở http://aws.amazon.com/, và sau đó nhấn Sign Up và t
hực hiện theo các hướng dẫn trên màn hình.

Để cung cấp thông tin truy cập cho một người sử dụng IAM. 
Đăng nhập vào Management Console AWS và mở giao diện điều khiển IAM tại https://console.aws.amazon.com/iam/.

    1. Click vào Users để xem người sử dụng IAM của bạn.

    2. Nếu bạn không có bất kỳ người sử dụng IAM thiết lập, nhấn Create User để tạo.
    3. Click vào sử dụng IAM cho người mà bạn muốn cung cấp thông tin truy cập.
    4. Dưới Credentials Security, Click  vào Manage Access Keys.
    5. Click vào Tạo Access Key để tạo một khóa truy cập mới.
    6. Trên hộp thoại hiện ra, nhấn nút Download Credentials để tải về các tập tin ủy nhiệm cho máy tính của bạn, hoặc bấm Hiện Credentials tài Security để xem quyền truy cập của người sử dụng IAM ID access key ID và secret access key.
Chú ý: Bạn không thể có được secret access key một khi bạn đóng hộp thoại. Nếu bạn bị mất secret access key, bạn sẽ cần phải tạo ra một access key mới.
   7. Click Close để đóng hộp thoại.


Setting up project

1. Bạn cần download AWS SDK cho Java tại http://aws.amazon.com/sdk-for-java/ hoặc thêm dependency vào maven project.

        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-java-sdk-s3</artifactId>
            <version>1.10.10</version>
        </dependency>
        <dependency>
            <groupId>com.amazonaws</groupId>
            <artifactId>aws-java-sdk-dynamodb</artifactId>
            <version>1.10.10</version>
       </dependency>

2. Lấy access key ID và secret access key đã tạo ở bước trên bạn sẽ cần để kết nối với S3
3. Thêm quyền “AWSConnector” “AmazonS3FullAccess” cho user. (Tạo group và thêm quyền sau đó thêm user vào group).


Authenticate with Amazon S3

Có 4 cách để bạn authenticate với Amazon S3: 
1. Sử dụng default credential profile file :
Tạo file credentials với nội dung sau :

  1. # Move this credentials file to (~/.aws/credentials)
  2. # after you fill in your access and secret keys in the default profile
  3. # WARNING: To avoid accidental leakage of your credentials,
  4. # DO NOT keep this file in your source directory.
  5. [default]
  6. aws_access_key_id=
  7. aws_secret_access_key=
sau đó lưu vào thư mục C:\Users\user\.aws\credentials cho windows và /home cho Linux
(Dùng lệnh mkdir để tạo thư mục .aws)

Nếu bạn chọn cách này thì get credentials bằng cách
AWSCredentials credentials = new ProfileCredentialsProvider().getCredentials();
2. Sử dụng biến môi trường set biến môi trường trong hệ thống với tên là:
AWS_ACCESS_KEY_ID và AWS_SECRET_ACCESS_KEY

3. Sử dụng java system properties sau đó dùng SystemPropertiesCredentialsProvider để load lên trong chương trình.

4. Cách hay dùng là set credentials trong lúc chạy bằng keys
AWSCredentials credentials = new BasicAWSCredentials("YourAccessKeyID", "YourSecretAccessKey");

Create S3 Client

AmazonS3 s3client = new AmazonS3Client(credentials);

Create a bucket

String bucketName = "bucketName";
s3client.createBucket(bucketName);

List all buckets

for (Bucket bucket : s3client.listBuckets()) {
 System.out.println(" - " + bucket.getName());
}

Create folder in bucket

public static void createFolder(String bucketName, String folderName, AmazonS3 client) {
 // create meta-data for your folder and set content-length to 0
 ObjectMetadata metadata = new ObjectMetadata();
 metadata.setContentLength(0);

 // create empty content
 InputStream emptyContent = new ByteArrayInputStream(new byte[0]);

 // create a PutObjectRequest passing the folder name suffixed by /
 PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName,
    folderName + SUFFIX, emptyContent, metadata);

 // send request to S3 to create folder
 client.putObject(putObjectRequest);
}

Complete Example

  1. public class MyAmazonS3Client extends AmazonS3Client { private static final String SUFFIX = "/"; private static MyAmazonS3Client instance = null; public MyAmazonS3Client () { super(); } public MyAmazonS3Client (AWSCredentials awsCredentials) { super(awsCredentials); } public static MyAmazonS3Client getS3Client() { if (instance == null) { instance = new MyAmazonS3Client (); } return instance; } public static MyAmazonS3Client getS3Client(AWSCredentials awsCredentials) { if (instance == null) { instance = new MyAmazonS3Client (awsCredentials); } return instance; } /** * Get S3 Client with Access Key and Secret Key * * @param awsAccessKey * @param awsSecretKey * @return AmazonS3 */ public static MyAmazonS3Client getS3Client(String awsAccessKey, String awsSecretKey) { AWSCredentials credentials = new BasicAWSCredentials(awsAccessKey, awsSecretKey); return getS3Client(credentials); } public void createFolder(String bucketName, String folderName) { // create meta-data for your folder and set content-length to 0 ObjectMetadata metadata = new ObjectMetadata(); metadata.setContentLength(0); // create empty content InputStream emptyContent = new ByteArrayInputStream(new byte[0]); // create a PutObjectRequest passing the folder name suffixed by / PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, folderName + SUFFIX, emptyContent, metadata); // send request to S3 to create folder this.putObject(putObjectRequest); } public void uploadFile(String bucketName, String s3filePath, File fileUpload, CannedAccessControlList accessControlList) { // upload file to folder and set it to public this.putObject(new PutObjectRequest(bucketName, s3filePath, fileUpload) .withCannedAcl(accessControlList)); } /** * Get file from S3 at an InputStream * * @param bucketName - The name of the Amazon S3 bucket * @param s3filePath - The path to file on S3. * @return InputStream */ public InputStream getFileInputStream(String bucketName, String s3filePath) { S3Object object = this.getObject(new GetObjectRequest(bucketName, s3filePath)); return object.getObjectContent(); } /** * Get file from S3 * * @param bucketName * @param s3filePath * @param fileLocalPath path file you want to save at local * @return File * @throws IOException */ public File getFile(String bucketName, String s3filePath, String fileLocalPath) throws IOException { S3Object object = this.getObject(new GetObjectRequest(bucketName, s3filePath)); File file = new File(fileLocalPath); try ( // read this file into InputStream InputStream inputStream = object.getObjectContent(); // write the inputStream to a FileOutputStream OutputStream outputStream = new FileOutputStream(file)) { int read = 0; byte[] bytes = new byte[1024]; while ((read = inputStream.read(bytes)) != -1) { outputStream.write(bytes, 0, read); } } return file; } /** * @param bucketName - The name of the Amazon S3 bucket containing the * object to delete. * @param s3filePath - The path to file on S3. */ public void deleteFile(String bucketName, String s3filePath) { // upload file to folder and set it to public this.deleteObject(new DeleteObjectRequest(bucketName, s3filePath)); } /** * Delete folder on S3 * * @param bucketName * @param folderName */ public void deleteFolder(String bucketName, String folderName) { List<S3ObjectSummary> fileList = this.listObjects(bucketName, folderName).getObjectSummaries(); for (S3ObjectSummary file : fileList) { this.deleteObject(bucketName, file.getKey()); } this.deleteObject(bucketName, folderName); } }