Thứ Năm, 29 tháng 10, 2009

7 khả năng phát sinh lỗi bảo mật khi code PHP

PHP đem đến sự linh động, tiện dụng và đôi khi là tùy tiện. Điều đó dẫn đến một số các quy tắc bảo mật căn bản sau có thể bị bỏ qua

Kiểm tra dữ liệu đầu vào

Đây là vấn đề cơ bản của căn bản, tránh việc chèn mã độc và giảm tải kha khá cho server khi không phải xử lý dữ liệu không mong muốn.

Hạn chế truy cập

Đối với các trang cho phép những thao tác can thiệp vào website ở các khía cạnh giao diện, hệ thống, db hay bất cứ cấu hình nào thì luôn phải được đảm bảo mức độ an toàn cao nhất. Cơ bản của căn bản nữa là phải kiểm tra bất cứ request nào của người dùng, thay vì chỉ phân quyền đơn giản.

Hạn chế sử dụng session ID đối với các dữ liệu nhạy cảm

Ví dụ như số thẻ tín dụng hay các thông tin cá nhân, đổi mật khẩu ... việc chỉ kiểm tra sessionID mới là xác thực vòng ngoài thôi. Không nên đặt niềm tin quá vào nó.

SQL injections

Sự tiện lợi của PHP đem đến cho người phát triển khả năng tương tác database nhanh chóng, dễ dàng. Do đó, sự cẩu thả của người viết code khi để lạc các ký tự 'không sạch' vào câu query sẽ dẫn đến hậu quả khôn lường. Các framework hầu hết loại bỏ khả năng này, và nó cũng không còn phổ biến, nhưng vẫn xuất hiện nhiều nếu không cẩn thận.

Thông báo lỗi hệ thống

Nếu vì lý do gì đó mà website của bạn dừng hoạt động, hãy đảm bảo là các thông báo cho người dùng sẽ không thể hiện những thông tin nhạy cảm như connection error, db, webserver hay nặng nhất là câu query db. Hãy chắc chắn có một câu thông báo chuẩn cho toàn bộ website khi đi vào vận hành.

Xử lý dữ liệu nhận từ phía người dùng

Hãy đảm bảo đó là những dữ liệu 'sạch' và có ý nghĩa, nếu không sẽ dẫn đến nhiều vấn đề ở trên.

Cấu hình

Nếu có quyền truy cập, hãy xác lập các thông số của PHP & webserver đảm bảo an toàn, hiệu quả & tối ưu.

nguồn: http://articles.sitepoint.com/article/php-security-blunders/2    (nhớ vào đọc cho có cả vd rõ ràng)

Thứ Tư, 28 tháng 10, 2009

Sử dụng plugin chat trong cakephp 1.2

Xin chào các bạn!

Đây là môt plugin do tôi tự viết dựa trên các tính năng chat của livechat. Chương trình livechat tôi tham khảo được viết bằng php, để có thể quản trị được các chức năng tôi thấy có nhiều cái thừa  không cần thiết trong trường hợp của tôi. Tôi đã dựa vào livechat để viết plugin với tính năng tương tự. Plugin này có sử dụng jquery.

Các chức năng chính:

1)  Hiển thị danh sách người chat và danh sách người quản trị đang chat. Tôi tạm gọi là guests và operators.

2) Guest chỉ việc nhập tên và email, sau đó sẽ hiển thị màn hình chat. Operators sẽ thấy trạng thái chát của guest và bắt đầu chat. Một guest có thể do nhiều operators chat.

3) Operators sử dụng luôn bảng users.

3) Các chức năng hoặc động trong cửa sổ window riêng biệt (popup window).

Để sử dụng các bạn download plugin tại đây. (Để hểu rõ hơn về plugin bạn có thể tham khảo tại đây)

Cài đặt:

1) Đưa toàn bộ nội dung của plugin chat vào trong app/plugin

2) Bạn chạy file sqlChat trong thu mục app/plugins/chat/config/sql .

3) Copy file chat.ctp trong thu muc app/plugins/chat/views/layout vào trong thu mục app/views/layout.

Sử dụng:

Do các chức năng chat đểu hiển thị ra các cửa sổ riêng biệt. Do vậy ta chỉ việc tạo ra link gọi đến là ok.

Ví dụ:
<?php
//Hiển thị link để guest mở cửa sổ chat với admin
echo $html->link('Chat with Amdmin', '/chat/chats/form_guest', array('onclick' => "window.open('{$html->url('/chat/chats/form_guest')}','mywin','left=20,top=20,width=460,height=440,toolbar=0,resizable=0'); return false;"));
echo '<br />';
//Hiển thị link quản trị chat
echo $html->link('Manager chatting', '/chat/chats/chat_users', array('onclick' => "window.open('{$html->url('/chat/chats/chat_users')}','mywin','left=20,top=20,width=460,height=440,toolbar=0,resizable=0'); return false;"));
?>

Vậy là xong, chúc các bạn vui vẻ :D

Chủ Nhật, 18 tháng 10, 2009

Upload ảnh có đóng dấu bản quyền - cakephp 1.2

Đóng dấu cho ảnh thật sự cần thiết khi chúng ta muốn giữ bản quyền cho ảnh đó. Bài viết này sẽ hướng dẫn mọi người làm việc đó một cách dễ dàng. Bắt dầu nào :
Đầu tiên là tạo cơ sở dữ liệu :

CREATE TABLE `images` (
`id` INT( 4 ) NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`images` VARCHAR( 255 ) NOT NULL
)

Vậy là xong bước đầu tiên. Tiếp đến chúng ta sẽ tạo controller / model / views

Đầu tiên là controller : app/controllers/images_controller.php:

<?php
class ImagesController extends AppController
{
var $name = 'Images';
var $components = array('Upload');

function add()
{
if(! empty ($this->data))
{
$this->Image->create ();
if($this->Upload->upload ($this->data['Image']['image'], WWW_ROOT . 'img' . DS))
{
$this->data['Image']['images'] = $this->data['Image']['image']['name'];
}
if($this->Image->save ($this->data))
{
$this->Session->setFlash (__ ('The Image has been saved', true));
$this->redirect ($this->referer());
}else
{
$this->Session->setFlash (__ ('The Image could not be saved. Please, try again.', true));
}
}
}
}
?>

Tiếp đến là model : app/models/image.php

<?php
class Image extends AppModel {
var $name = 'Image';
}
?>

Cuối cùng là views : app/views/images/add.ctp

<div class="images form">
<?php $session->flash();?>
<?php echo $form->create('Image', array('type' => 'file')); ?>
<fieldset>
<legend><?php __('Add image');?></legend>
<div class="group">
<div><?php __('Image');?></div>
<div><?php echo $form->file('image',array('label'=>'',)); ?></div>
</div>
</fieldset>
<?php echo $form->end('add');?>
</div>

Để có thể upload được ảnh ta sẽ sử dụng components. Ở đây ta sẽ tạo 1 file có tên là upload.php trong components

app/controllers/components/upload.php

<?php
class UploadComponent extends Object {
function upload(&$file, $dir) {
$return = false;
// current time in miliseconds
$time = microtime ( 1 ) * 1000;
$file['name']=md5($time).$file['name'];

if(@move_uploaded_file($file['tmp_name'],$dir.$file['name']))
{
//Dòng này là ảnh sẽ được upload
$main_img         = $dir.$file['name']; // main big photo / picture

//Dòng này là ảnh sẽ đóng dấu lên ảnh được upload
$watermark_img    = "watermark.gif"; // use GIF or PNG, JPEG has no tranparency support
$padding         = 3; // distance to border in pixels for watermark image
$opacity        = 100;    // image opacity for transparent watermark

$watermark     = imagecreatefromgif($dir.$watermark_img); // create watermark
$image         = imagecreatefromjpeg($main_img); // create main graphic

if(!$image || !$watermark) die("Error: main image or watermark could not be loaded!");

$watermark_size     = getimagesize($dir.$watermark_img);
$watermark_width     = $watermark_size[0];
$watermark_height     = $watermark_size[1];

$image_size     = getimagesize($main_img);
$dest_x         = $image_size[0] - $watermark_width - $padding;
$dest_y         = $image_size[1] - $watermark_height - $padding;

// copy watermark on main image
imagecopymerge($image, $watermark, $dest_x, $dest_y, 0, 0, $watermark_width, $watermark_height, $opacity);

// print image to screen
header("content-type: image/jpeg");
imagejpeg($image);
imagedestroy($image);
imagedestroy($watermark);
$return = true;
}
return $return;
}
}
?>


file ảnh watemark.gif được đặt trong thư mục : app/webroot/img/watermark.gif.

Muốn cho ảnh watermark.gif mờ đi thì ta chỉ việc chỉnh độ opacity là được.

Bạn có thể download file ảnh watermark.gif tại đây

Thứ Bảy, 17 tháng 10, 2009

Sử dụng plugin Paypal IPN trong CakePHP

Xin chào mọi người!

Plugin paypal IPN này thật sự cần thiết cho những ai muốn sử dụng Paypal IPN trong cakephp. Tôi đã tìm kiếm trên mạng và sử dụng plugin này, thấy thật sự mang lại tiện ích rất lớn. Helper trong plugin sẽ giúp ta dẽ dàng tạo ra các nút Checkout, Add to Cart, Subscribe, và Donate một cách dễ dàng. Chức năng chính của plugin này là tạo ra các nút add to cart, subscribe ... trong paypal để gửi thông tin lên paypal, thực hiện giao dịch và lưu trữ dữ liệu giao dịch trả về vào trong log và CSDL. (Cách sử dụng plugin bạn tham khảo tại đây).

Paypal IPN plugin. (Paypal Instant Payment Notification)
Version 1.4
Tác giả: Nick Baker (nick@webtechnick.com)

Website: http://www.webtechnick.com

Browse, Download, hoặc  Checkout Plugin.
Browse: http://projects.webtechnick.com/paypal_ipn
Download: http://projects.webtechnick.com/paypal_ipn.tar.gz
SVN: https://svn2.xp-dev.com/svn/nurvzy-paypal-ipn

Các bước cài đặt như sau:

1) Copy plugin vào trong project /app/plugins/paypal_ipn.

2) Import file /plugins/paypal_ipn/paypal_ipn.sql vào trong cơ sở dữ liệu.

3) Thêm những dòng dưới đây vào router: /app/config/routes.php fil
<?php
/* Paypal IPN plugin */
Router::connect('/paypal_ipn/process', array('plugin' => 'paypal_ipn', 'controller' => 'instant_payment_notifications', 'action' => 'process'));

/* Optional Routes, but nice for administration */
Router::connect('/paypal_ipn/edit/:id', array('admin' => true, 'plugin' => 'paypal_ipn', 'controller' => 'instant_payment_notifications', 'action' => 'edit'), array('id' => '[a-zA-Z0-9\-]+', 'pass' => array('id')));
Router::connect('/paypal_ipn/view/:id', array('admin' => true, 'plugin' => 'paypal_ipn', 'controller' => 'instant_payment_notifications', 'action' => 'view'), array('id' => '[a-zA-Z0-9\-]+', 'pass' => array('id')));
Router::connect('/paypal_ipn/delete/:id', array('admin' => true, 'plugin' => 'paypal_ipn', 'controller' => 'instant_payment_notifications', 'action' => 'delete'), array('id' => '[a-zA-Z0-9\-]+', 'pass' => array('id')));
Router::connect('/paypal_ipn/add', array('admin' => true, 'plugin' => 'paypal_ipn', 'controller' => 'instant_payment_notifications', 'action' => 'edit'));
Router::connect('/paypal_ipn', array('admin' => true, 'plugin' => 'paypal_ipn', 'controller' => 'instant_payment_notifications', 'action' => 'index'));/*
/* End Paypal IPN plugin */
?>

Router này sẽ chuyển cách gọi các controller và action trong plugin này về cách gọi thông thường. (nhìn code bạn sẽ hiểu ngay !^_^! )

Tạo tài khoản paypal:

Để sự dụng được plugin này bạn phải có một tài khoản paypal (tham khảo cách tạo tài khoản paypal tại đây). Với các lập trình viên, paypal có hỗ trợ cho việc tạo tài khoản ảo để test, địa chỉ https://developer.paypal.com. Khi tạo xong tài khoản, bật (enable) IPN trong tài khoản của bạn.

Sử dụng trong administator (tùy chọn): đây là trường hợp bạn thêm và lưu thông tin thông qua giao diện admin

1) Bạn phải đăng nhập vào trong phần quản trị với tài khoản administrator thông qua component Auth.

2) Sử dụng plugin tại http://www.yoursite.com/paypal_ipn

Sự dụng helper paypal (tùy chọn): Trong trường hợp bạn muốn sử dụng helper hoặc các button trong helper.

1) Cấu hình lại với thông tin của bạn tại /paypal_ipn/config/paypal_ipn_config.php

2) Thêm 'PaypalIpn.Paypal' vào trong danh sách helper của app_controller.php:
<?php
var $helpers = array('Html','Form','PaypalIpn.Paypal');
?>

3) cách sử dụng (tham khảo thêm tại /paypal_ipn/views/helpers/paypal.php)

$paypal->button(String tittle, Options array);

ví dụ:
<?php
//Pay Now Button
echo $paypal->button('Pay Now', array('amount' => '12.00', 'item_name' => 'test item'));
//Pay Now Button with Image
echo $paypal->button('pay_now.jpg', array('amount' => '12.00', 'item_name' => 'test item'));

//Subscribe Button
echo $paypal->button('Subscribe', array('type' => 'subscribe', 'amount' => '60.00', 'term' => 'month', 'period' => '2'));

//Donate Button
echo $paypal->button('Donate', array('type' => 'donate', 'amount' => '60.00'));

//Add To Cart
echo $paypal->button('Add To Cart', array('type' => 'addtocart', 'amount' => '15.00'));
?>

Ta cũng có thể thêm một số thuộc tính Paypal hợp lệ vào trong options của button.

Ví dụ :
<?php echo $paypal->button('Pay Now', array('amount' => '12.00', 'item_name' => 'Stuff', 'return' => 'http://www.yoursite.com/thankyou')); ?>

Ngoài việc sử dụng các helper button đẻ tạo ra các button paypal ta còn có thể tạo ra thông các các thẻ html. Khi sử dụng thẻ form html ta phải sử dụng notify_url để gán tới http://www.yoursite.com/paypal_ipn/process
ví dụ:
<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
...
...
<input type="hidden" name="notify_url" value="http://www.yoursite.com/paypal_ipn/process" />
...
</form>

Khi thông tin giao dịch được trả về từ paypal, dữ liệu sẽ được lưu vào trong cơ sở dữ liệu và hàm afterPaypalNotification sẽ được gọi (nếu nó tồn tại). Đây sẽ là nơi bạn xử lý các thao tác login khác liên quan đến giao dịch sau khi giao dịch thành công.

Tạo ra function trong /app/app_controller.php như sau:
<?php
function afterPaypalNotification($txnId){
//Here is where you can implement code to apply the transaction to your app.
//for example, you could now mark an order as paid, a subscription, or give the user premium access.
//retrieve the transaction using the txnId passed and apply whatever logic your site needs.

$transaction = ClassRegistry::init('PaypalIpn.InstantPaymentNotification')->findById($txnId);
$this->log($transaction['InstantPaymentNotification']['id'], 'paypal');

//Tip: be sure to check the payment_status is complete because failure transactions
// are also saved to your database for review.

if($transaction['InstantPaymentNotification']['payment_status'] == 'Completed'){
//Yay! We have monies!
}
else {
//Oh no, better look at this transaction to determine what to do; like email a decline letter.
}
}
?>

Chú ý:

1) Với các bạn chưa lần nào làm về paypal, các bạn có thể tìm hiểu qua về cách tạo một trang web trực tuyển qua paypal một cách đơn giản tại đây. Sau khi làm xong ví dụ này, tôi nghĩ các bạn sẽ hiểu rõ hơn nguyên tắc hoặt động của plugin này.

2) Plugin này hiện tại (version 2.1) theo tôi được biết thì chỉ có hỗ trợ 2 button chính là Paynow và Subscribe. Còn các nút AddToCart... thì chưa hỗ trợ việc lưu dữ liệu. Hi vọng khi các bạn sử dụng thì đã hỗ trợ đủ.

Chúc các bạn thành công  !^_^!