Sử dụng XForms để tạo công cụ kế toán, Phần 2: Đăng nhập và các tài khoản

Tác dụng của XForms với xác thực người dùng

Loạt bài viết sáu phần trình bày về cách làm thế nào tận dụng sức mạnh của XForms kết hợp với MySQL và PHP để hỗ trợ tiến trình tạo ra một công cụ kế toán trực tuyến được gọi là X-Trapolate. Tất cả công nghệ lập trình tốt đều xử lý một mảng các bài toán mà nó có thể giải quyết tốt. Loạt bài này nêu bật những vấn đề mà XForms giải quyết một cách hiệu quả, chẳng hạn như nhu cầu về những tính toán trực tuyến và tương tác cao. Phần 2 của loạt bài sáu phần này trình bày về cách làm thế nào để tận dụng sức mạnh của XForms cùng chung với PHP và MySQL để tạo ra các chức năng cơ bản "login" ("đăng nhập"), "registration" ("đăng ký"), và "account management" (quản lý tài khoản) đã gặp trong nhiều ứng dụng Web hiện đại.

Stony Yakovac, Kỹ sư phần mềm, 自由职业者

Stony Yakovac là một kỹ sư và là một nhà viết sách tự do, ông đang sống tại Lava Hot Springs, bang Idaho, Hoa Kỳ. Ông làm cho rất nhiều dự án thuộc nhiều lĩnh vực, bao gồm các thiết kế về phần mềm và phần cứng số



07 07 2009

Trước khi bạn bắt đầu

Bài hướng dẫn này là dành cho những nhà phát triển ứng dụng Web khám phá kỹ thuật xử lý biểu mẫu Web của XForms. Bài hướng dẫn này là bài hướng dẫn đầu tiên và là phần thứ hai của Loạt bài sáu phần. Biểu mẫu đăng nhập và những biểu mẫu đăng ký tài khoản được trình bày trong bài hướng dẫn này. Trước tiên, bài hướng dẫn này đưa ra vài điều cơ bản về việc phát triển XForms bao gồm đầu vào văn bản, mật khẩu che giấu đầu vào văn bản và những cấu trúc dữ liệu được yêu cầu. Sau đó bài hướng dẫn sẽ bao trùm việc xử lý dữ liệu XForms trong PHP cũng như việc hỗ trợ những cấu trúc dữ liệu MySQL. Phần cuối cùng của việc đăng nhập cho biết điều gì sẽ xảy ra khi một đăng nhập thành công hoặc không thành công. Một yêu cầu để có thể đăng nhập được là phải có một tài khoản. Việc tạo tài khoản có thể được thực hiện qua quá trình đăng ký, điều này được trình bày sau phần đăng nhập.

Về bài hướng dẫn này

Biểu mẫu đăng nhập gần như là có mặt khắp mọi nơi trên Internet, hỗ trợ mọi thứ từ truy cập vào e-mail tới những cổng mua sắm và thậm chí cả ngân hàng trực tuyến. Việc đăng nhập cung cấp cho những người sử dụng dữ liệu tùy ý theo tài khoản riêng của họ và cung cấp cho hệ thống cách để kiểm soát việc sử dụng. Những hướng tiếp cận tiêu biểu cho việc đăng nhập yêu cầu người dùng phải nhập vào một username (tên người sử dụng) và password (mật khẩu), sau đó chúng sẽ được xác thực với một cơ sở dữ liệu đã thiết lập trước khi thử đăng nhập. Bài hướng dẫn này không có mục đích là một ví dụ về bảo mật trong xác thực người dùng, thay vì đó bài hướng dẫn trình bày về cách sử dụng XForms theo thuật toán đã biết rõ dành cho việc đăng nhập và tạo tài khoản.

Việc đăng nhập yêu cầu tiến trình cơ bản sau đây và chúng cũng sẽ được đề cập trong bài hướng dẫn này:

  1. Nhập username và password vào những hộp nhập văn bản.
  2. Gửi username và password tới dịch vụ xác thực.
  3. Sử dụng username đã cho và tài khoản để quyết định nếu có một tài khoản với username và password cụ thể đã được định sẵn.
  4. Lưu trữ kết quả (đúng hoặc sai) để tất cả những hành động tiếp sau được thực hiện bởi người dùng đó sẽ được liên kết với việc xác thực đó một cách tự động.
  5. Cho phép người dùng truy cập nếu việc đăng nhập thành công hoặc từ chối truy cập và cung cấp một thông điệp để chỉ ra rằng username và password không được tìm thấy.

Về loạt bài này

Mục đích của loạt bài này là trình bày về tác dụng của XForms trong việc phát triển những ứng dụng Web cũng như cung cấp kiến thức cho người đọc về tác dụng của XForms.

  • Phần 1 là sự giới thiệu tới toàn bộ loạt bài viết tổng quan hoá tất cả các bộ phận của kết quả cuối cùng và những khía cạnh nào có trong mỗi phần trong đặc tả XForms.
  • Phần 2 trình bày về đăng nhập và quản lý tài khoản.
  • Phần 3 trình bày việc phát triển những biểu mẫu gắn liền với việc quản lý tài khoản.
  • Phần 4 tiếp tục trình bày về việc quản lý tài khoản và việc báo cáo những khía cạnh tính toán khác nhau của một doanh nghiệp.
  • Phần 5 trình bày việc quản lý nợ và những cải tiến.
  • Phần 6 kết thúc loạt bài viết với bản tóm tắt các công cụ phát triển, và một vài đề nghị để cải tiến và tiếp tục làm việc với bộ công cụ.

Các điều kiện tiên quyết

Bài hướng dẫn này sử dụng cơ sở dữ liệu MySQL cho việc lưu trữ và tham chiếu. Những câu lệnh SQL cần thiết xuất hiện xuyên suốt bài hướng dẫn do đó yêu cầu kiến thức làm việc với MySQL. PHPMyAdmin đưa ra truy nhập tương đương để cấu hình cơ sở dữ liệu MySQL cũng như khung nhìn và các thực thể từ giao diện đồ họa điều khiển bằng thực đơn.

Qua mục đích của loạt bài là để dạy cho người đọc về tác dụng của XForms, kiến thức cơ bản về XForms mà người đọc muốn. Có vài bài hướng dẫn rất hay và loạt bài có tính chất giới thiệu liên quan đến XForms sẵn có trên developerWorks (xem Tài nguyên). XForms được xây dựng trên XML, và do đó cũng yêu cầu phải có những hiểu biết cơ bản về XML.

Những kỹ thuật khác và những khái niệm có thể liên quan nhưng chúng có phạm vi ít hơn nhiều và không quan trọng với sự nhận thức của người đọc về chủ đề này. Một số phần mềm cũng được yêu cầu:

  • Trình duyệt có khả năng hiển thị XForms, chẳng hạn Firefox 2.0.1.
  • Một máy chủ Web với PHP đã được kích hoạt, chẳng hạn WAMP
  • Máy chủ SQL, MySQL, trong trường hợp này đó là một phần trong gói WAMP.

Tạo biểu mẫu đăng nhập

Bước đầu tiên trong việc bảo mật một ứng dụng là kiểm soát truy cập, điển hình là thông qua một mẫu biểu đăng nhập. Bạn làm thế nào để bảo đảm an toàn biểu mẫu đăng nhập?

Mục xác nhận đăng nhập

Tồn tại hai kiểu xác nhận đăng nhập, đó là username và password. Với tư cách là một cửa ngõ an ninh tiềm ẩn, biểu mẫu XForms phải cung cấp bảo mật chống lại loại hình tấn công cụ thể. Mặc dù bài hướng dẫn này không cung cấp hướng dẫn về vấn đề an ninh mạnh hay yếu, ở thời điểm đúng lúc, đặc trưng của XForms cung cấp sự bảo vệ chống lại một biểu mẫu của tấn công an ninh cụ thể, tấn công Peeping-Tom. Tấn công Peeping-Tom là tấn công mà đích thân những người quan sát canh phòng người dùng và có thể dễ dàng lấy được truy cập tới tài khoản của người dùng thông qua một biểu mẫu giống như trong Hình 1.

Hình 1. Một biểu mẫu đăng nhập không an toàn
Một biểu mẫu đăng nhập không an toàn

Những biểu mẫu HTML sớm cung cấp một giải pháp và giải pháp cơ bản tương tự cũng tồn tại ở XForms. Hiển thị ưu tiên để ngăn chặn kiểu tấn công Peeping-Tom là làm mờ mật khẩu, như biểu diễn trong Hình 2.

Hình 2. Biểu mẫu đăng nhập an toàn Peeping-Tom
Biểu mẫu đăng nhập an toàn Peeping-Tom

Định dạng và thông tin tương tự cũng tồn tại ở cả hai biểu mẫu. Dữ liệu đằng sau các biểu mẫu không khác nhau trong bất kì cách nào. Những dấu sao không đưa ra bất kì sự bảo vệ nào khỏi một trong số những tấn công an ninh khác nhau. Một số ví dụ của những tấn công như vậy là:

  • Tấn công kiểu Trojan Horse (Con ngựa thành Troa) -- Người tấn công tạo ra một biểu mẫu mà quan sát và hành động giống như biểu mẫu đăng nhập, nó lưu lại username và password cho riêng mình người đó sử dụng sau này.
  • Tấn công Network Intercept -- Người tấn công "hack" ("tấn công") vào mạng máy tính và thu nhận dữ liệu khi dữ liệu di chuyển từ máy tính của người sử dụng đến máy chủ.
  • Những tấn công giải mã -- Người tấn công giành được truy cập tới chuỗi mật khẩu và "bẻ khóa" mật mã, nghịch đảo thuật toán và thu được cặp username và password.

Để ngăn chặn những tấn công như vậy yêu cầu sự bảo mật nằm ngoài phạm vi của XForms. Những kiểu bảo mật như vậy đến từ những giao thức mã hóa, tường lửa, hệ thống máy tính cô lập và nhiều phương pháp khác để ngăn chặn những kẻ tấn công khỏi việc truy cập vào dữ liệu password và username. Ví dụ này đưa ra không nhiều những thách thức đối với kẻ tấn công và nó cũng thể hiện một máy bảo mật rất yếu bởi vì password và username di chuyển trên mạng máy tính như là một văn bản thuần túy, dễ dàng đọc từ mạng máy tính. Password tồn tại trong cơ sở dữ liệu như văn bản thuần túy, điều đó cũng thể hiện sự bảo mật vô cùng yếu. Mặc dù những điều này nên được chú ý nhưng phương pháp ngăn chặn tấn công Peeping-Tom cần được lưu ý như là một đặc tính hữu dụng.

Bí mật và dữ liệu nhập vào -- Làm ẩn đi hay không

Ví dụ 1 chứa một đoạn mã XForms cho việc hiển thị và thu được văn bản username và password như biểu diễn trong Hình 2. Phần tử hiển thị "input" phục vụ cho mục đích của hộp nhập username. Biểu mẫu của điều khiển hiển thị này nhìn chung tạo ra một số dòng đơn nhập vào hộp văn bản. Một trong số những đặc trưng của kỹ thuật XForms là đưa ra sự độc lập giữa hiển thị biểu mẫu với kiến trúc của biểu mẫu. Tương lai những thực thi của XForms cũng có thể thực hiện điều khiển hiển thị "input" như là một hằng đợi theo từng chữ một ở đó "label" (nhãn) được đọc tới người dùng và sự đáp ứng lại của người dùng được chuyển đổi sang văn bản trước khi gửi hồ sơ. Điều khiển password thực hiện giống như điều khiển "input" ngoại trừ các ký tự được biểu thị ra là những dấu sao thay vì những ký tự thực sự được đánh vào. Với mỗi điều khiển biểu mẫu, "label" ghi rõ một chỉ dẫn của dữ liệu tự nhiên được nhập vào điều khiển. Những điều khiển XForms hầu hết cho phép người lập trình chỉ rõ một nhãn và sử dụng nó trong một số trường hợp không rõ ràng nhưng hợp lý.

Ví dụ 1. Những điều khiển hiển thị username và password
            <xforms:input ref="instance('acctToolLoginInst')/username" >
               <xforms:label>Username : </xforms:label>
            </xforms:input><br/>
            <xforms:secret ref="instance('acctToolLoginInst')/password" >
               <xforms:label>Password : </xforms:label>
            </xforms:secret><br/>

Liên kết điều khiển biểu mẫu tới nơi lưu trữ

Ví dụ 1 chứa rất ít thông tin khác với thực tế là một "input" và một "secret" nên được diễn tả. Chỉ có mẩu thông tin quan tâm là ref. Những chỉ thị chứa trong các thẻ "<" và ">" là những đặc tính hoặc những thuộc tính. XForms cho phép chèn vào bất cứ thứ gì gần giống như là thuộc tính theo cách này; tuy nhiên chỉ có những thuộc tính cụ thể mới có nghĩa. Mọi điều khiển biểu mẫu phục vụ một mục đích sử dụng hoặc ref hoặc thuộc tính bind. Cả hai có thể thực hiện tương tự nhau. Sự khác biệt giữa chúng là bind tham chiếu đến một câu lệnh sẽ được thảo luận chi tiết ở phần sau của bài hướng dẫn này trong khi ref ám chỉ một nút dữ liệu XML.

XPath -- Tìm kiếm nơi lưu trữ dữ liệu

XForms được xây dựng trên XML; đó là cấu trúc dữ liệu trình bày đằng sau. Qua cấu trúc này, XForms có thể thay đổi cách biểu diễn của nó và lưu dữ liệu đã nhập vào biểu mẫu. Xâu ký tự chỉ rõ bởi "ref" đã được biết đến là XPath. XPath có thể đơn giản như là một phân cấp tham chiếu tới cái gì đó chẳng hạn như chuỗi "/top/down1/hereitis", hoặc phức tạp như một người lập trình có thể tưởng tượng ra mà không sử dụng dòng lệnh thứ hai. Ở điểm này, vài lời nói đùa làm bối rối những nhà vô địch thế giới về mã hóa thì thật hân hoan và vui vẻ. Bây giờ có một lý do để thấy được những gì có thể được hoàn thành trên một dòng. Một tập con những hàm của XPath là sẵn có trên XForms. Hàm "instance" đóng một vai trò quyết định trong XForms.

Những thể hiện -- Dữ liệu XForms bao hàm

XForms yêu cầu cấu trúc dữ liệu XML để hoạt động sau mỗi điều khiển biểu mẫu. Lần lượt, cấu trúc dữ liệu XML đó hoạt động trong một thể hiện. Thể hiện đó hoạt động bên trong một mô hình XForms. Một trang XHTML đơn có thể chứa một số không xác định những mô hình XForms và mỗi mô hình XForms có thể chứa một số không xác định các thể hiện. Hàm XPath instance cung cấp một máy cho việc tìm kiếm một thể hiện cụ thể. Từ điều này, phần còn lại của đường dẫn dùng thể hiện như là gốc và định vị một nút có liên quan đến thể hiện đó. Ví dụ 2 biểu diễn định nghĩa thể hiện sau một biểu mẫu đăng nhập.

Ví dụ 2. Thể hiện của cấu trúc dữ liệu XML
      <xforms:instance id="acctToolLoginInst" >
         <loginForm xmlns="">
            <username>stonyyakovac</username>
            <password>foo123</password>
            <message/>
            <menu/>
            <submitLogin/>
         </loginForm>
      </xforms:instance>

Có vài đặc trưng đáng chú ý xuất hiện trong Ví dụ 2. Từ khóa "instance" bao quanh một thể hiện. Từ khóa "id" chỉ rõ một thuộc tính của "instance" để xác định tên của riêng thể hiện đó. Từ khóa "id" đã chỉ ra trong Ví dụ 2 tương tự như nội dung của hàm XPath instance() trong Ví dụ 1. Hàm này liên kết những điều khiển biểu mẫu với những dữ liệu thể hiện cụ thể này. Đặc trưng đáng chú ý tiếp theo trong Ví dụ 2 là thuộc tính xmlns với loginForm. Từ loginForm không phải là một từ khóa; từ đó có thể được xác định bởi người lập trình như là văn bản hợp lệ bất kì. Từ loginForm dùng như là điểm tham chiếu đến một nút cho phần còn lại của dữ liệu. Mỗi thể hiện XForms có thể có đúng một nút con. Trong trường hợp này, nút con là loginForm. Chú ý rằng loginForm KHÔNG xuất hiện trong XPath tham chiếu đến nút này. Thuộc tính xmlns chỉ rõ không gian tên của thể hiện. Ở trường hợp này, biểu mẫu được xây dựng không có không gian tên. Nếu thuộc tính không gian tên này vắng mặt thì tất cả những điều khiển biểu mẫu sẽ không xuất hiện.

Một điều khác cần chú ý về cấu trúc dữ liệu thể hiện là sự có mặt của chuỗi khởi tạo cho "username" và "password". Việc thực thi thực tế của biểu mẫu đăng nhập sẽ không chứa những khởi tạo này nhưng trong trường hợp này, những khởi tạo này dùng như một lối tắt cho những mục đích gỡ lỗi với hiệu ứng của khởi nạp những điều khiển biểu mẫu với username là "stonyyakovac" và password là "foo123". Các nút lệnh "menu," "message," và "submitLogin" không biểu thị khởi tạo dữ liệu thể hiện.

Những nút lệnh hoạt động như thế nào

Như trước đây đã nói, việc thực thi XForms xác định việc biểu diễn của những điều khiển biểu mẫu; tuy nhiên, những biểu diễn này có chứa những nút lệnh. Những nút lệnh được biểu diễn trong Hình 1Hình 2, có chứa văn bản "Login" và "Create Account". Nói chung, người sử dụng đều hiểu rằng một nút lệnh thực hiện một hành động. Hai nút lệnh này xảy ra bởi vì văn bản trong định nghĩa XForms chỉ rõ sự khác nhau, tuy nhiên chúng được biểu thị tương tự. Ví dụ 3 biểu diễn mã hóa nhiệm vụ của hai nút lệnh này.

Ví dụ 3. Nút lệnh Submit và trigger
            <xforms:submit submission="submit_login" 
                     ref="instance('acctToolLoginInst')/submitLogin">
                  <xforms:label>Login</xforms:label>
            </xforms:submit>
            <xforms:trigger ref="instance('acctToolLoginInst')/newAcct">
               <xforms:label>Create Account</xforms:label>
               <xforms:load ev:event="DOMActivate" resource="register.xhtml"/>
            </xforms:trigger>

Trigger -- Nút lệnh tạo tài khoản

Nút Create Account hoạt động hoàn toàn độc lập với dữ liệu biểu mẫu trong trường hợp này. Định nghĩa "trigger" trong Ví dụ 3 đưa ra một nhãn và dòng lệnh khác, hành động load. XForms thực thi trigger như là một phần nào của ở cắm rỗng mà người phát triển phải cắm thứ gì đó vào đó. "Trigger" này có hành động load trong nó. Hành động load làm những gì mà bản thân tên của nó ám chỉ, nó tải một URL chỉ rõ bởi thuộc tính resource. Chìa khóa để làm cho nút này thực hiện như là một nút lệnh, nghĩa là load xảy ra khi nút lệnh được nhấn, đó là sự có mặt của thuộc tính ev:event. Phần ev của thuộc tính đó trước dấu ":" để chỉ một không gian tên mà đã được định nghĩa trước đó trong phần tử html. Ví dụ cho những định nghĩa này được trình bày trong Ví dụ 4. Ví dụ này cũng giải thích tại sao mọi phần tử XForms có "xforms" gắn vào nó. Từ nằm trong cặp dấu ngoặc kép, DOMActivate, chỉ thị hành động "load" xảy ra chỉ khi phần tử đính kèm được kích hoạt. Trong trường hợp này, phần tử đính kèm là trigger, vì vậy hành động "load" xảy ra khi nút lệnh được nhấn.

Ví dụ 4. Định nghĩa không gian tên
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
"http://www.w3.org/TR/xhtml1/D/tdxhtml1-strict.dtd">
<html
   xmlns="http://www.w3.org/1999/xhtml"
   xmlns:xforms="http://www.w3.org/2002/xforms" 
   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
   xmlns:ev="http://www.w3.org/2001/xml-events"
   xmlns:xlink="http://www.w3.org/1999/xlink"
>

Submit -- Nút đăng nhập

Nhìn chung những biểu mẫu Web đưa dữ liệu tới một vài đích. Đôi khi những tập lệnh CGI quen thuộc xử lý thông tin như kiểm tra thẻ mua sắm; và thỉnh thoảng những điều khác cũng xảy ra. Biểu mẫu này có một máy đăng ký đơn, mặc dù số những đặc tả đăng ký có thể được chỉ rõ. Nút lệnh "Login" liên kết đến máy đăng ký qua một phần tử XForms đặc biệt mà phần tử này phải được khai báo trong phần khai báo mô hình XForms. "submit_login" ID liên kết nút lệnh đến hành động được định nghĩa trong Ví dụ 5.

Ví dụ 5. Định nghĩa Submission
      <xforms:submission id="submit_login" 
                         action="login.php" method="post"  
                         instance="acctToolLoginInst" replace="instance" 
                         ref="instance('acctToolLoginInst')" />

Bản đăng ký XForms đã khai báo trong Ví dụ 5 biểu thị tác dụng của một vài thuộc tính khóa đối với sự thành công của biểu mẫu đăng nhập. Trước tiên, dù các thuộc tính như "id," "action," và "method" xác định rằng khi bản đăng ký tham chiếu "submit_login" (nút đăng nhập đã đề cập ở lúc trước) được nhấn, thì URL "login.php" sẽ được kích hoạt như một tập lệnh sử dụng định dạng post cho trao đổi dữ liệu. Có một yêu cầu tham chiếu tới nút XML trong thể hiện của XForms được xác định bằng ref, một lát nữa điều này sẽ trở nên quan trọng hơn. Hai thuộc tính cuối cùng dề thảo luận là instancereplace. Hai thuộc tính này, làm việc cùng nhau, chỉ thị cho bộ xử lý XForms sử dụng dữ liệu được trả về bởi tập lệnh PHP để thay thế cho dữ liệu được gán nhãn ID "acctToolLoginInst" của XForms.


Xác thực thông tin đăng ký bằng PHP

Cơ chế gửi thông tin của biểu mẫu gọi đến một tập lệnh PHP để sử dụng dữ liệu biểu mẫu XForms và dữ liệu trả về. Tập lệnh PHP thực thi những bước cơ bản sau đây:

  • Tìm kiếm dữ liệu người dùng.
  • Nhìn vào cơ sở dữ liệu để xem xét nếu dữ liệu hợp lệ.
  • Trả về một quyết định và dữ liệu liên quan đến quyết định đó.

Đoạn này sẽ xem xét làm thế nào để chấp nhận dữ liệu XForms trong PHP, làm thế nào để phân tích và giải mã dữ liệu, làm thế nào để truy cập vào cơ sở dữ liệu cũng như làm thế nào để đáp ứng lại cả những đăng nhập hợp lệ và không hợp lệ.

Sử dụng dữ liệu XML XForms trong PHP

XForms sử dụng XML như là một định dạng thay đổi dữ liệu ưu tiên của nó. Dữ liệu đăng ký đến biểu mẫu của một tài liệu XML. Ví dụ đầu tiên của PHP (Ví dụ 6) biểu thị sự thu hồi dữ liệu XML, phân tích dữ liệu XML và những phương pháp truy cập đến dữ liệu đó.

Ví dụ 6. Sử dụng dữ liệu biểu mẫu XML với PHP
<?php 
   if (!isset($HTTP_RAW_POST_DATA)) 
      $HTTP_RAW_POST_DATA = file_get_contents("php://input");
   $xml = $HTTP_RAW_POST_DATA;
   $doc = new DomDocument('1.0');
   $doc->loadXML($xml);
   $pass = $doc->getElementsByTagName("password")->item(0)->nodeValue;
   $uname = $doc->getElementsByTagName("username")->item(0)->nodeValue;

Bằng việc sử dụng lớp DomDocument được cài đặt sẵn với PHP5, XML đã trở nên dễ dàng với giao diện. Dòng "file_get_contents" là một biện pháp an toàn trong trước hợp dữ liệu chỉ tồn tại trên "standard in" của PHP thay vì được đặt một cách tự động vào biến HTTP_RAW_POST_DATA. Phương thức DOMDocumen, loadXML phân tích dữ liệu XML và lưu nó vào một cấu trúc dữ liệu để có thể được truy vấn như đã biểu diễn với phương thức getElementsByTagNam.

Khởi tạo cơ sở dữ liệu MySQL

Bước tiếp theo là "Nhìn vào cơ sở dữ liệu để xem xét nếu dữ liệu hợp lệ." Trước khi điều đó được hoàn thành, thì phải tao ra cơ sở dữ liệu. Việc mã hóa cho bài hướng dẫn này yêu cầu một máy chủ MySQL chạy trên "localhost" và tài khoản "root" không có mật khẩu, tên cơ sở dữ liệu là "acct1", tên bảng là "contact". Sử dụng cơ sở dữ liệu MySQL với tài khoản gốc đã cho phép và không có mật khẩu biểu thị một lỗ hổng an ninh cũng như tính chán nản nhưng với những mục đích phát triển thì điều này làm cho việc gỡ lỗi dễ dàng hơn. Cài đặt và chạy một máy chủ MySQL trên "localhost", trình duyệt thực hiện trên máy này cũng như trên Web. Bằng việc mặc định, cấu hình khởi tạo bao gồm một tài khoản gốc không có mật khẩu. Để tạo cơ sở dữ liệu "acctl" và bảng "contact" đã yêu cầu hãy đăng nhập vào máy chủ MySQL và thực hiện những lệnh sau đây (xem Ví dụ 7).

Ví dụ 7. Khởi tạo cơ sở dữ liệu MySQL
CREATE DATABASE 'acct1' ;
CREATE TABLE 'contact' (
'contactId' INT( 11 ) NOT NULL ,
'username' VARCHAR( 20 ) NOT NULL ,
'password' VARCHAR( 20 ) NOT NULL ,
'prefix' VARCHAR( 10 ) NOT NULL ,
'firstName' VARCHAR( 20 ) NOT NULL ,
'lastName' VARCHAR( 20 ) NOT NULL ,
'company' VARCHAR( 20 ) NOT NULL ,
'addr1' VARCHAR( 40 ) NOT NULL ,
'addr2' VARCHAR( 40 ) NOT NULL ,
'city' VARCHAR( 20 ) NOT NULL ,
'zip' VARCHAR( 10 ) NOT NULL ,
'state' VARCHAR( 2 ) NOT NULL ,
workNum' VARCHAR( 12 ) NOT NULL ,
'homeNum' VARCHAR( 12 ) NOT NULL ,
'faxNum' VARCHAR( 12 ) NOT NULL ,
'cellNum' VARCHAR( 12 ) NOT NULL ,
'notes' VARCHAR( 400 ) NOT NULL
) ENGINE = innodb;
INSERT INTO 'contact' ( 'username' , 'password' , 'firstName' , 'lastName' , 'addr1' , 
'addr2' , 'city' , 'zip' , 'state' , 'homeNum' , 'faxNum' , 'cellNum' , 'contactId' , 
'company' , 'workNum' , 'notes' , 'prefix' ) 
VALUES (
'stonyyakovac', 'foo123', 'Stony', 'Yakovac', '1223 NW Rd.', '', 'PDX', '97117', 
'OR', '503-475-1411', '', '', '12345', 'Yakovac Enterprises', '', 'Home: Anytime', 'Mr.'
);

Những lệnh trên sẽ tạo ra một cơ sở dữ liệu và bảng đã yêu cầu rồi chèn vào một bản ghi để sử dụng như là một tài khoản kiểm tra.

Giao diện MySQL trong PHP

PHP mã hóa cho việc đăng nhập vào cơ sở dữ liệu MySQL, chọn cơ sở dữ liệu, xây dựng truy vấn, thực hiện truy vấn và đánh giá những kết quả được trình bày trong Ví dụ 8. Quá trình này khá đơn giản và có thể được thực hiện theo các cách khác nhau nhưng trọng tâm của nhiệm vụ là truy vấn cơ sở dữ liệu.

Ví dụ 8. Truy vấn cơ sở dữ liệu MySQL cho ủy nhiệm đăng nhập
   $sqldb = mysql_connect('localhost', 'root');
   if (!$sqldb) 
     die('Could not connect server at localhost because: ' . mysql_error());

   $sqlseldb = mysql_select_db('acct1', $sqldb);
   if (!$sqlseldb) 
      die ('Can\'t select the acct1 database localhost because: ' . mysql_error());

   $sqlQuery = sprintf("SELECT 1 FROM contact WHERE username='%s' and " . 
      "password='%s'", mysql_real_escape_string($uname), 
      mysql_real_escape_string($pass));
   $queryData = mysql_query($sqlQuery, $sqldb);
   if (!$queryData) 
      die ('Could not insert token into tokentable on because:  ' . mysql_error());

   $numRows = mysql_num_rows($queryData);

Thông tin tốt nhất phải được trả về trong trường hợp thử đăng nhập không thành công là giấy ủy nhiệm đã không hợp lệ. Mặc dù nó có thể thử đưa ra cho người sử dụng mật khẩu không chính xác nhưng việc phản ứng lại đề nghị thử bẻ khóa mật khẩu một cách có phương pháp trong đó điều đầu tiên hacker thử những username cho đến khi PHP nói cho anh ta biết mật khẩu là sai, sau đó cố gắng thử các mật khẩu để biết rằng tài khoản là hợp lệ. Chú ý rằng dữ liệu được trả về từ truy vấn SQL không phải là dữ liệu vô hướng và phải sử dụng một hàm để đánh giá kết quả.

Chú ý: Mặc dù nằm ngoài phạm vi của bài hướng dẫn này nhưng bạn cũng nên kiểm tra Các tài nguyên để có thông tin về việc ngăn chặn các tấn công nội tại của SQL, thường những ứng dụng mục tiêu nào giống như thế này.

Ở điểm này, mặc dù mã PHP trông hợp lý và thậm chí các hàm chính xác thì một vấn đề vẫn tồn tại. Những câu lệnh "die" trả về chuỗi văn bản. Từ khi tập lệnh login.php sử dụng các thuộc tính "instance/replace" trên bản đăng ký, XForms giả sử rằng tất cả dữ liệu được trả về từ tập lệnh PHP là ở trong biểu mẫu XML. Do đó, nếu một trong số những trường hợp "die" thực hiện thì kết quả là những gì mà Firefox sẽ trình bày giống như trong Hình 3.

Hình 3. Lỗi XForms của Firefox
Lỗi XForms của Firefox

Điều bí mật nằm ở góc dưới phải. Lỗi mầu đỏ có thể được đưa ra để cho biết vấn đề thực sự, như được biểu diễn trong Hình 4.

Hình 4. Lỗi XForms của Firefox đã mở rộng
Lỗi XForms của Firefox đã mở rộng

Bài học sẽ được học từ lỗi nhận thức không rõ ràng một cách khó tin này đó là chỉ những dữ liệu XML đã định dạng một cách chính xác mới có thể được dùng bởi XForms. Không có các thuộc tính "replace/instance", lỗi sẽ xuất hiện trên cửa sổ trình duyệt như là một văn bản trong tập lệnh PHP.

Dữ liệu trả về cho những đăng nhập không hợp lệ

Khi một người dùng nhập vào một credentials không chính xác, hoặc username hoặc password, thì hành động thích hợp là nói cho người dùng biết rằng credentials của anh ta là không hợp lệ. Trừ khi có một manh mối nào để người dùng biết họ gõ vào thứ gì không chính xác, thì anh ta có thể nhấn "Login" vài lần với tâm trạng thất vọng, sau đó anh ta gõ lại password và/hoặc username bởi lẽ anh ta đã cho rằng nút không hoạt động. Bằng việc hiển thị một thông điệp như trong Hình 5, người dùng được thông báo rằng dữ liệu đăng nhập không chính xác và có thể khắc phục vấn đề này trước khi nhấn lại "Login".

Hình 5. Những bản ủy quyền đăng nhập không hợp lệ
Những bản ủy quyền đăng nhập không hợp lệ

Để trả về dữ liệu đó, điền vào nút mà bị để trắng trên bản gốc, nút thông điệp. Ví dụ 9 và 10 biểu diễn những dòng thích hợp của XHTML và CSS để hiển thị thông điệp đã trình bày trong Hình 5. Phần tử "output" của XForms hiển thị dữ liệu nhưng không có dữ liệu dùng như một số biểu mẫu của điều khiển đầu vào.

Ví dụ 9. Mã XForm của một thông điệp lỗi
<xforms:output class="errormessage" ref="instance('acctToolLoginInst')/message" />

Ví dụ 10 chỉ ra những dòng thích hợp của CSS.

Ví dụ 10. CSS để định dạng thông điệp lỗi
*.errormessage { font-weight: bold; color: red; }

Điều tiếp theo cần chú ý về biểu mẫu sau khi thử đăng nhập không hợp lệ đó là thiếu mật khẩu. Tên người sử dụng đúng nhưng để đảm bảo rằng người dùng gõ lại mật khẩu thực sự thì dữ liệu phải được gỡ bỏ khỏi dữ liệu thể hiện. Từ khi giao dịch sử dụng "replace/instance", việc cài đặt nút mật khẩu với một xâu rỗng nhằm hoàn thành nhiệm vụ. Ví dụ mã PHP được trình bày trong Ví dụ 11. Chỉ khác với PHP mới ở phương thức "saveXML". Không có tham số nào được kích hoạt, phương thức "saveXML" trả về XML được định dạng một cách chính xác đại diện cho cấu trúc hiện tại của nó, điều này rất thuận tiện vì XForms thực sự cần điều đó.

Ví dụ 11. Mệnh đề đăng nhập không hợp lệ PHP
   if($numRows <= 0)
   {
      mysql_close($sqldb);
      $doc->getElementsByTagName("password")->item(0)->nodeValue = '';
      $doc->getElementsByTagName("message")->item(0)->nodeValue = 'Invalid login 
credentials!';
      echo $doc->saveXML();
      exit;
   }

Dữ liệu trả về cho những đăng nhập hợp lệ

Khi người dùng cung cấp một username và password thì kết quả trong truy vấn trả về nhiều hơn một bản ghi rỗng, người dùng đáp ứng một tiêu chuẩn đăng nhập. Để thỏa mãn tiêu chuẩn này, PHP cần cung cấp vài dịch vụ (xem Ví dụ 12).

  • Ghi nhớ đăng nhập
  • Cho phép người dùng truy cập tới các công cụ
Ví dụ 12. Mệnh đề đăng nhập hợp lệ PHP
   else
   {
      $_SESSION['username'] = $uname;
      $loginToken = rand();
      $_SESSION['loginToken'] = $loginToken;
      $now = localtime();
      $datetime = sprintf("%4d-%2d-%2d 
%2d:%2d:%2d",$now[5]+1900,$now[4],$now[3],$now[2],$now[1],$now[0]);
      $sqlQuery = sprintf("INSERT INTO 'logintokens' ('logintoken', 'username', 
'creation') VALUES ( 
'%d', '%s', '%s');", 
         $_SESSION['loginToken'],
         mysql_real_escape_string($username),
         $datetime);
      $queryData = mysql_query($sqlQuery, $sqldb);
      if (!$queryData) die ('Could not insert token into tokentable on MySQL server 
because:  ' . 
mysql_error());
      mysql_close($sqldb);

      //$host= $_SERVER['HTTP_HOST'];
      //$reldir= rtrim(dirname($_SERVER['PHP_SELF']), '/\\');
      //header("Location: http://$host$reldir/manageAcct.xhtml");
      $notLoggedIn = $doc->getElementsByTagName('notLoggedIn')->item(0);
      $doc->getElementsByTagName('loginForm')->item(0)->removeChild($notLoggedIn);
      $menu = $doc->getElementsByTagName("menu")->item(0);
      $menu->setAttribute('title',
                          "Great! You're logged in! Here are your".
                          " available links:");
      $links = $doc->createElement('links');
      $menu->appendChild($links);
      $link = $doc->createElement('link');
      $link->setAttribute('name', 'Account management');
      $link->setAttribute('value', "manageAcct.xhtml");
      $links->appendChild($link);
      $link = $doc->createElement('link');
      $link->setAttribute('name', 'Invoices');
      $link->setAttribute('value', "invoice.xhtml");
      $links->appendChild($link);
      
      //echo str_replace('<', '<', str_replace('>', '>', $doc->saveXML()));
      echo $doc->saveXML();
      exit;
   }

Trước tiên Đoạn mã PHP này liên quan đến biến _SESSION. Việc thực thi của đặc trưng này đảm bảo rằng dữ liệu đã lưu trữ trong biến _SESSION sẽ luôn sẵn có khi thể hiện của khách hàng tương tự trả về. Một đăng nhập được ghi nhớ như thế nào khi có điều này xảy ra. Thứ hai một người dùng đã hoàn thành việc đăng nhập thì sinh ra một thẻ duy nhất, đưa ra một bản sao cho người dùng sử dụng biến _SESSION và lưu bản sao vào cơ sở dữ liệu. Thẻ này cho phép PHP đảm bảo người dùng đăng nhập một cách chính xác trong những giao dịch tương lai, khi PHP có thể so sánh thẻ với những báo cáo của người dùng có chứa thẻ trong cơ sở dữ liệu cho người dùng đó. Việc lưu trữ một timestamp (nhãn thời gian) cho phép dịch vụ dựa trên máy chủ chọn thời gian có thể làm sạch cơ sở dữ liệu của những đăng nhập cũ yêu cầu người dùng đăng nhập lại sau khoảng thời gian thích hợp.

Trước khi hai phần cuối cùng của tập lệnh PHP được thảo luận, những dòng chú thích đáng được lưu ý. Nhìn chung, hầu hết những biểu mẫu đăng nhập, khi đã thỏa mãn sẽ tự động lấy những người dùng khỏi các trang được bảo vệ. Điều này được hoàn thành với một trang chuyển hướng, như được trình bày trong mã chú thích. Giống như những câu lệnh "die", việc chuyển hướng không hoạt động đúng cách. XForms yêu cầu PHP trả về hoặc chỉ dữ liệu XML hoặc chỉ dữ liệu HTML, nhưng không thể nào phù hợp với PHP ở thời điểm đó. Có những máy trong đặc tả của XForms cung cấp cùng một nhóm chuyển hướng động, nhưng như bài hướng dẫn trong hướng dẫn này, việc thực thi không xuất hiện với chức năng chính xác cho hoạt động đó. Với tư cách một thay thế, một thực đơn được tạo ra và những đặc trưng XForms khác tạo ra ảo giáo của việc chuyển hướng.

Sử dụng những phương thức appendChild, setAttribute, và createElement, những nút XML được thêm vào với dữ liệu đủ để cung cấp một thực thi của nút lệnh, như với nút lệnh "Create Account" đã trình bày trước đó. Sử dụng những phương thức tương tự, nút "notLoggedIn" được loại bỏ.

Hiển thị dữ liệu cho những đăng nhập hợp lệ

Mã XForms được trình bày trong Ví dụ 13 tạo ra một thực đơn giống như đã trình bày ở Hình 6. Những phần thêm mới để giải thích cấu trúc của XForms là "repeat" và cả những biểu thức XPath dùng trong "repeat".

Ví dụ 13. Tạo một thực đơn cho một đăng nhập hợp lệ
       <xforms:label ref="instance('acctToolLoginInst')/menu/@title" />
       <xforms:repeat nodeset="instance('acctToolLoginInst')//link">
           <xforms:trigger>
             <xforms:label ref="@name" />
             <xforms:load ev:event="DOMActivate" ref="@value"/>
           </xforms:trigger>
       </xforms:repeat>
Hình 6. Thực đơn hợp lệ của đăng nhập XForms
XForms login valid menu

Cấu trúc "repeat" của XForms đưa ra động lực để tạo ra nhiều cấu trúc động khác nhau. Những hướng dẫn tiếp theo trong loạt bài này sẽ thảo luận thêm về "repeat", nhưng ví dụ này là điểm bắt đầu có giá trị. Cấu trúc "repeat" xử lý tất cả những nút trong một cấu trúc dữ liệu XML được đại diện bởi thuộc tính "nodeset" đính kèm với nó. Trong trường hợp này, nodeset là tất cả những nút có tên "link". Những nút đó được định nghĩa trong tập lệnh PHP ở Ví dụ 11.

Hai phần tử cú pháp mới làm cho ví dụ này hoạt động là hai đoạn XPath in đậm ở Ví dụ 13. Biểu tượng "@" cho bộ xử lý XPath biết tìm tiếm thuộc tính bằng tên đặt sau "@" thay vì cố gắng tìm một phần tử. Điều đó làm cho cảm giác khi PHP được tham chiếu tại nơi mà dữ liệu được chèn vào giống như là những thuộc tính. Cuối cùng là dấu "//", dùng để chỉ ra "nút này và tất cả các nút con của nó". Nếu không có cặp dấu gạch chéo này thì những liên kết sẽ không hiển thị.

Không hiển thị dữ liệu trước khi những đăng nhập hợp lệ

Hiểu biết về mã cho một thực đơn hoạt động tồn tại, người đọc có thể hỏi tại sao thực đơn không hiển thị ở nơi đầu tiên. Câu trả lời cho câu hỏi đó là ít quan trọng; dữ liệu không tồn tại trước khi đăng nhập hợp lệ. Tuy nhiên, câu hỏi hợp lệ cần được trả lời một cách tuyệt đối. Tại sao những điều khiển biểu mẫu đăng nhập không xuất hiện? Câu trả lời nằm ở phần cuối ở mã XForms, được trình bày trong Ví dụ 14. Ví dụ 14 giới thiệu về thành phần bind của ngôn ngữ XForms. Câu lệnh bind tồn tại trong phần định nghĩa của mô hình XForm. Mục đích của nó là cung cấp một phương thức của biến đổi động các thuộc tính của những điều khiển XForms và kiểm soát hành vi XForms. Ví dụ này sử dụng thuộc tính relevant.

Ví dụ 14. XForms giấu thực đơn đăng nhập
      <xforms:bind nodeset="instance('acctToolLoginInst')/newAcct"
                   relevant="instance('acctToolLoginInst')/notLoggedIn"/>

      <xforms:bind nodeset="instance('acctToolLoginInst')/submitLogin"
                   relevant="instance('acctToolLoginInst')/notLoggedIn"/>

      <xforms:bind nodeset="instance('acctToolLoginInst')/username"
                   relevant="instance('acctToolLoginInst')/notLoggedIn"/>

      <xforms:bind nodeset="instance('acctToolLoginInst')/password"
                   relevant="instance('acctToolLoginInst')/notLoggedIn"/>

      <xforms:bind nodeset="instance('acctToolLoginInst')/message"
                   relevant="instance('acctToolLoginInst')/notLoggedIn"/>

Mỗi nối kết chỉ rõ một nodeset từ dữ liệu thể hiện và tham chiếu nút notLoggedIn của dữ liệu thể hiện cho thuộct tính có liên quan. Nút notLoggedIn được khai báo ở phần dữ liệu thể hiện; cho nên nó tồn tại khi biểu mẫu này được tải lần đầu. Vì nó tồn tại, nút tham chiếu bởi thuộc tính nodeset trở thành "relevant". Khi một đăng nhập hợp lệ xảy ra, tập lệnh PHP gỡ bỏ nút notLoggedIn, thực hiện tất cả những nút không có liên quan kia. Khi một nút được kết nối với một điều khiển XForms là không liên quan, máy XForms sẽ không đáp ứng lại điều khiển đó. Sử dụng phương thức này, biểu mẫu đăng nhập được ẩn đi khi một đăng nhập hợp lệ được hoàn thành.


Đăng ký tài khoản

Trong đoạn này, bạn sẽ thấy một biểu mẫu mới, người dùng sẽ đăng ký trên biểu mẫu. Nó có chứa một điều khiển mới là thực đơn đổ xuống, và những điều khiển nối kết mới.

Tạo một tài khoản

Việc đăng nhập yêu cầu một tài khoản. Việc tạo một tài khoản yêu cầu một biểu mẫu đăng ký. Hình 7 biểu diễn một biểu mẫu đăng ký cho hướng dẫn này, nó có chứa những thông tin rất đơn giản. Tuy nhiên, một số đặc trưng XForms đáng quan tâm được sử dụng để giúp cho việc tạo biểu mẫu này.

Hình 7. Biểu mẫu đăng ký cơ bản
Biểu mẫu đăng ký cơ bản

Những lựa chọn mở

Một lựa chọn mở được dùng cho những lựa chọn drop-down trên biểu mẫu này. Tuy nhiên, hai hộp này thực hiện khác nhau. Hộp Name Prefix chứa tập những lựa chọn cố định. Phần của lựa chọn "mở" cho phép người dùng nhập vào hộp bất cứ thứ gì như nó là một hộp nhập văn bản. Hành vi này được biểu diễn trong Hình 8.

Hình 8. Lựa chọn mở
Lựa chọn mở

Mã XHTML để tạo một lựa chọn mở như được biểu diễn trong Ví dụ 15. Điều khiển biểu mẫu "select1" làm cho người dùng chọn lựa một cách chính xác một danh mục từ danh sách. Danh sách được thành lập từ một số bất kì những "danh mục", như trong Ví dụ 14. Một mặc định cho lựa chọn "select1" là "closed", điều này không cho phép người dùng nhập vào một lựa chọn nằm ngoài danh sách. Thuộc tính selection cho phép người thiết kế biểu mẫu XForms tạo ra một lựa chọn mở.

Ví dụ 15. XForms Open Select1
        <xforms:select1 ref="instance('acctToolRegInst')/prefix" selection="open">
           <xforms:label>Name Prefix:  </xforms:label>
           <xforms:item>
              <xforms:label>Mr.</xforms:label>
              <xforms:value>Mr.</xforms:value>
           </xforms:item>
           <xforms:item>
              <xforms:label>Mrs.</xforms:label>
              <xforms:value>Mrs.</xforms:value>
           </xforms:item>
           <xforms:item>
              <xforms:label>Ms.</xforms:label>
              <xforms:value>Ms.</xforms:value>
           </xforms:item>
           <xforms:item>
              <xforms:label>Jr.</xforms:label>
              <xforms:value>Jr</xforms:value>
           </xforms:item>
        </xforms:select1><br/>

Những lựa chọn động

Biểu mẫu này có chứa một ví dụ về lựa chọn động. Khi người dùng gõ vào, hộp lựa chọn tên người dùng mở ra. Đặc trưng mới của XForms tạo ra hiệu ứng này. Ví dụ 16 biểu diễn những phần của mã XForms để tạo ra hiệu ứng này. Những phần tử khóa là những danh mục có chứa các nhãn và các giá trị của chúng từ những nút dữ liệu thông qua thuộc tính ref và những nút dữ liệu có giá trị của chúng thông qua đặc tính calculate của phần tử bind. Ba sự lựa chọn này là ba "câu thần chú" phổ biến của những tên người dùng. Những "câu thần chú" điển hình trong câu hỏi là sự ghép nối của tên và họ, họ và chữ đầu tiên của tên, tên và chữ đầu tiên của họ.

Ví dụ 16. XForms Open Select1 và Calculate
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
"http://www.w3.org/TR/xhtml1/D/tdxhtml1-strict.dtd">
<html
   xmlns="http://www.w3.org/1999/xhtml"
   xmlns:xforms="http://www.w3.org/2002/xforms" 
   xmlns:ev="http://www.w3.org/2001/xml-events"
>
  <head>
    <title>XForms Accounting Tool New User Registration</title>
    <link rel="stylesheet" href="style.css" type="text/css"/>
    <xforms:model id="acctToolRegModel" >
      <xforms:instance id="acctToolRegInst" >
         <registerForm xmlns="">
            <password/>
            <username/>
            <unameopt1/>
            <unameopt2/>
            <unameopt3/>
            <prefix/>
            <firstName/>
            <lastName/>
            <submitRegistration/>
         </registerForm>
      </xforms:instance>
...
      <xforms:bind nodeset="instance('acctToolRegInst')/unameopt1" 
         calculate="translate(concat(substring(../firstName,1,1), 
../lastName),'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') "/>
      <xforms:bind nodeset="instance('acctToolRegInst')/unameopt2" 
         calculate="translate(concat(substring(../lastName,1,1), 
../firstName),'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') "/>
      <xforms:bind nodeset="instance('acctToolRegInst')/unameopt3" 
         calculate="translate(concat(../firstName, ../lastName),
'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') "/>
...
        <xforms:select1 class="required" bind="usernamebind" >
           <xforms:label>Prefered Username: </xforms:label>
            <xforms:item>
               <xforms:label ref="instance('acctToolRegInst')/unameopt1"/>
               <xforms:value  ref="instance('acctToolRegInst')/unameopt1"/>
            </xforms:item>
            <xforms:item>
               <xforms:label ref="instance('acctToolRegInst')/unameopt2"/>
               <xforms:value  ref="instance('acctToolRegInst')/unameopt2"/>
            </xforms:item>
            <xforms:item>
               <xforms:label ref="instance('acctToolRegInst')/unameopt3"/>
               <xforms:value  ref="instance('acctToolRegInst')/unameopt3"/>
            </xforms:item>
        </xforms:select1><br/>

Chú ý những giới thiệu thêm về những hàm XPath, hàm concat, substring, và translate. Hàm translate biến đổi tất cả những ký tự hoa sang ký tự thường bằng việc thay thế mỗi ký tự từ đối số thứ hai với ký tự tương ứng trong đối số thứ ba. Kết quả được trình bày trong Hình 9. Hàm concat trả về một chuỗi ký tự đơn dựa vào những đối số là N chuỗi ký tự cho trước, và hàm substring trả về một số cụ thể những ký tự được chỉ số hóa bởi vị trí cụ thể trên chuỗi ký tự nguồn. Ghi chú cũng giới thiệu về vị trí XPath của firstNamelastName được bắt đầu với "../". Đó là bởi vì, khi hàm calculate được tính toán, việc tính toán liên quan đến nút bị ràng buộc. Nhìn vào định nghĩa thể hiện, dễ thấy rằng unameopt1lastName là anh chị em và do đó, đường dẫn lên là ("..") và xuống ("lastName").

Hình 9. Lựa chọn động
Lựa chọn động

Hình 10 biểu diễn một biểu mẫu đăng ký đã điền đầy đủ thông tin. Khi nhấn nút lệnh Register, thay vì thấy hành vi trong biểu mẫu đăng nhập, biểu mẫu này nhanh đưa người dùng đến URL khác, biểu mẫu đăng nhập. Hai phần của nhiệm vụ thiết kế cho hành vi này là địng nghĩa XForms có "submission" thấy trong Ví dụ 17, và mã PHP đã trình bày một cách ngắn gọn ở Ví dụ 18.

Ví dụ 17. Đưa bản đăng ký XForms
<xforms:submission id="submit_registration" action="register.php" method="post"/>

Ví dụ 18 hiển thị mã PHP cho việc đăng ký.

Ví dụ 18. Đăng ký với PHP
<?php
   if (!isset($HTTP_RAW_POST_DATA)) 
      $HTTP_RAW_POST_DATA = file_get_contents("php://input");
   $xml = $HTTP_RAW_POST_DATA;
   $doc = new DomDocument('1.0');
   $doc->loadXML($xml);

   $sqldb = mysql_connect('localhost', 'root');
   if (!$sqldb) 
      die('Could not connect to MySQL server at localhost because: ' .
         mysql_error());

   $sqlseldb = mysql_select_db('acct1', $sqldb);
   if (!$sqlseldb) 
      die ('Can\'t select the acct1 database on MySQL server @ localhost because: '
          . mysql_error());

   // first check to see if that username is already taken
   $uname = $doc->getElementsByTagName("username")->item(0)->nodeValue;
   $sqlQuery = sprintf('SELECT * FROM `contact` WHERE username=\'%s\'',
       mysql_real_escape_string($uname));
   $queryData = mysql_query($sqlQuery, $sqldb);
   if (!$queryData) 
      die ('Could not query the contact table in the acct db because:  ' . 
         mysql_error());

   if(mysql_num_rows($queryData) > 0)
   {
      mysql_close($sqldb);
      $doc->getElementsByTagName("message")->item(0)->nodeValue = 
        'The username ' . $uname . ' is already taken.  Choose another.';
      echo $doc->saveXML();
      exit;
   }
   else
   {
      $pass = $doc->getElementsByTagName("password")->item(0)->nodeValue;
      $fname = $doc->getElementsByTagName("firstName")->item(0)->nodeValue;
      $prefix = $doc->getElementsByTagName("prefix")->item(0)->nodeValue;
      $lname = $doc->getElementsByTagName("lastName")->item(0)->nodeValue;
      $sqlQuery = "INSERT INTO `contact` ( `username`, `password`, `firstName`,".
         " `lastName`, `prefix`) VALUES ( ".
         sprintf("'%s', '%s', '%s', '%s', '%s' );", 
            $uname, $pass, $fname, $lname, $prefix);
      $queryData = mysql_query($sqlQuery, $sqldb);
      if (!$queryData) 
         die ('Could not insert token into contact table on MySQL server because:' 
            . mysql_error());
      mysql_close($sqldb);
      $host= $_SERVER['HTTP_HOST'];
      $reldir= rtrim(dirname($_SERVER['PHP_SELF']), '/\\');
      header("Location: http://$host$reldir/login.xhtml");
      exit;
   }
?>

Hầu hết PHP có vẻ quen thuộc. Hai sự khác biệt đáng kể được in đậm. Thứ nhất là một thay đổi đơn giản để chuỗi ký tự truy vấn sử dụng được trong tập lệnh đăng nhập. Lần này, thay vì yêu cầu nếu có một mục vào với username và password thỏa mãn, mục tiêu là để tìm ra nếu một username bị lấy mất hay không. Dấu "*" ở tất cả mật khẩu mà dùng chung cho username cụ thể, sẽ trả về tất cả những mục vào trong cơ sở dữ liệu. Người dùng được chỉ dẫn để chọn một username khác nếu có những kết quả khác được trả lại.

PHP tiếp theo lưu ý về câu truy vấn chèn dữ liệu vào bảng. Cú pháp đơn giản và những phần sau của loạt bài này sẽ giữ riêng tính đơn giản và tính quy tắc của cú pháp.

Đoạn được in đậm cuối cùng của đoạn mã thực thi việc "đưa nhanh" người dùng về trang đăng nhập. Chú ý kể cả "exit" trong đoạn mã được in đậm. "Exit" không yêu cầu chuyển hướng lại nên có thể không có thêm văn bản hiển thị. Nếu PHP lặp lại bất cứ thứ gì trước khi gọi "header", thì việc gọi tới "header" sẽ trả kết quả vào một thông báo lỗi.

Hình 10. Biểu mẫu đăng ký hoàn chỉnh
Biểu mẫu đăng ký hoàn chỉnh

Tổng kết

Biểu mẫu XForms đăng nhập đã giới thiệu là cơ sở làm việc của tập con những khái niệm XForms. Giữa những khái niệm đã giới thiệu là vài điều khiển biểu mẫu cơ bản "input," "secret," "submit," và "trigger". Điều khiển XForms "output" được sử dụng để hiển thị dữ liệu mà người dùng không thể thay đổi trực tiếp. Khái niệm về "submission" được trình bày với dữ liệu thường thay thế cho dữ liệu thể hiện đằng sau sự thực thi của XForms. Hành động đó kích hoạt sử dụng có liên quan đến việc ẩn biểu mẫu và sự có mặt của dữ liệu mới cho phép thể hiện của "repeat" trên một nodeset để tạo ra một thực đơn.

Những thực thi tương lai của loạt bài này cải tiến cả những thực thi của XForms cần thiết và những kỹ năng được chứa trong thực thi của XForms. Tiếp theo, Phần 3 sẽ sử dụng khái niệm về quản lý tài sản để biểu thị sâu hơn nữa tác dụng của những đơn hàng lặp lại và sự biến đổi của những hành động nhập vào khác nhau.


Tải về

Mô tảTênKích thước
Sample code for this tutorialaccttool_part2_code.zip8KB

Tài nguyên

Học tập

Lấy sản phẩm và công nghệ

  • XForms Recommendation được duy trì bởi W3C.
  • MozzIE, một điều khiển nguồn mở cho phép bạn tạo XForms trên Internet Explorer.

Thảo luận

Bình luận

developerWorks: Đăng nhập

Các trường được đánh dấu hoa thị là bắt buộc (*).


Bạn cần một ID của IBM?
Bạn quên định danh?


Bạn quên mật khẩu?
Đổi mật khẩu

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Ở lần bạn đăng nhập đầu tiên vào trang developerWorks, một hồ sơ cá nhân của bạn được tạo ra. Thông tin trong bản hồ sơ này (tên bạn, nước/vùng lãnh thổ, và tên cơ quan) sẽ được trưng ra cho mọi người và sẽ đi cùng các nội dung mà bạn đăng, trừ khi bạn chọn việc ẩn tên cơ quan của bạn. Bạn có thể cập nhật tài khoản trên trang IBM bất cứ khi nào.

Thông tin gửi đi được đảm bảo an toàn.

Chọn tên hiển thị của bạn



Lần đầu tiên bạn đăng nhập vào trang developerWorks, một bản trích ngang được tạo ra cho bạn, bạn cần phải chọn một tên để hiển thị. Tên hiển thị của bạn sẽ đi kèm theo các nội dung mà bạn đăng tải trên developerWorks.

Tên hiển thị cần có từ 3 đến 30 ký tự. Tên xuất hiện của bạn phải là duy nhất trên trang Cộng đồng developerWorks và vì lí do an ninh nó không phải là địa chỉ email của bạn.

Các trường được đánh dấu hoa thị là bắt buộc (*).

(Tên hiển thị cần có từ 3 đến 30 ký tự)

Bằng việc nhấn Gửi, bạn đã đồng ý với các điều khoản sử dụng developerWorks Điều khoản sử dụng.

 


Thông tin gửi đi được đảm bảo an toàn.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=70
Zone=Nguồn mở
ArticleID=407190
ArticleTitle=Sử dụng XForms để tạo công cụ kế toán, Phần 2: Đăng nhập và các tài khoản
publish-date=07072009