65 phút
Validation, Security và Sessions
Validation
Controller validation
public function store()
{
$rules = [
'name' => [
'label' => 'Product Name',
'rules' => 'required|min_length[2]|max_length[200]',
'errors' => [
'required' => 'Vui lòng nhập tên sản phẩm',
'min_length' => 'Tên phải có ít nhất 2 ký tự',
],
],
'email' => 'required|valid_email|is_unique[users.email]',
'price' => 'required|numeric|greater_than[0]',
'image' => [
'rules' => 'uploaded[image]|max_size[image,2048]|is_image[image]|mime_in[image,image/jpg,image/jpeg,image/png]',
],
];
if (!$this->validate($rules)) {
return redirect()->back()->withInput()
->with('errors', $this->validator->getErrors());
}
// Valid data
$data = $this->validator->getValidated();
// ...
}
Custom validation rules
// app/Validation/MyRules.php
namespace App\Validation;
class MyRules
{
public function even(string $value): bool
{
return ((int) $value) % 2 === 0;
}
public function phone(string $value): bool
{
return preg_match('/^[0-9]{10,11}$/', $value) === 1;
}
}
// Sử dụng
$rules = [
'quantity' => 'required|even',
'phone' => 'required|phone',
];
Security
CSRF Protection
// Tự động khi dùng form helper
<?= form_open('products/create') ?>
<?= csrf_field() ?>
<input type="text" name="name">
<button type="submit">Save</button>
<?= form_close() ?>
XSS Protection
// Escape output
<?= esc($data) ?>
<?= esc($data, 'html') ?>
// Trong controller
$data = $this->request->getPost('comment', FILTER_SANITIZE_FULL_SPECIAL_CHARS);
Password Hashing
$hash = password_hash($password, PASSWORD_DEFAULT);
password_verify($input, $hash);
SQL Injection Prevention
// Query Builder (an toàn)
$db->table('users')->where('email', $email)->get();
// Query bindings
$db->query('SELECT * FROM users WHERE email = ?', [$email]);
$db->query('SELECT * FROM users WHERE email = :email:', ['email' => $email]);
Filters
Tạo Filter
php spark make:filter AuthFilter
AuthFilter
<?php
namespace App\Filters;
use CodeIgniter\Filters\FilterInterface;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
class AuthFilter implements FilterInterface
{
public function before(RequestInterface $request, $arguments = null)
{
if (!session()->get('user_id')) {
return redirect()->to('/login');
}
}
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
{
// ...
}
}
Register filter trong Routes
$routes->group('admin', ['filter' => 'auth'], function ($routes) {
$routes->get('dashboard', 'Admin\Dashboard::index');
$routes->get('users', 'Admin\Users::index');
});
Config Filters
// app/Config/Filters.php
public array $aliases = [
'csrf' => \CodeIgniter\Filters\CSRF::class,
'auth' => \App\Filters\AuthFilter::class,
'admin' => \App\Filters\AdminFilter::class,
];
public array $globals = [
'before' => [
'csrf' => ['except' => ['api/*']],
],
];
Sessions
Sử dụng Session
$session = session();
// Set
$session->set('user_id', 123);
$session->set([
'name' => 'John',
'role' => 'admin',
]);
// Get
$userId = $session->get('user_id');
$name = $session->get('name') ?? 'Guest';
// Check
if ($session->has('user_id')) { }
// Remove
$session->remove('user_id');
// Destroy all
$session->destroy();
// Flash data (1 lần)
$session->setFlashdata('success', 'Saved!');
// Trong view
<?php if (session()->has('success')): ?>
<div class="alert"><?= session('success') ?></div>
<?php endif; ?>
Login System
<?php
namespace App\Controllers;
class Auth extends BaseController
{
public function login()
{
return view('auth/login');
}
public function attemptLogin()
{
$rules = [
'email' => 'required|valid_email',
'password' => 'required',
];
if (!$this->validate($rules)) {
return redirect()->back()->withInput()
->with('errors', $this->validator->getErrors());
}
$email = $this->request->getPost('email');
$password = $this->request->getPost('password');
$model = new \App\Models\UserModel();
$user = $model->where('email', $email)->first();
if (!$user || !password_verify($password, $user['password'])) {
return redirect()->back()->withInput()
->with('error', 'Invalid credentials');
}
session()->set([
'user_id' => $user['id'],
'user_name' => $user['name'],
'is_logged_in' => true,
]);
return redirect()->to('/dashboard');
}
public function logout()
{
session()->destroy();
return redirect()->to('/login');
}
}
CORS cho API
<?php
namespace App\Filters;
use CodeIgniter\Filters\FilterInterface;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
class CorsFilter implements FilterInterface
{
public function before(RequestInterface $request, $arguments = null)
{
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: Content-Type, Authorization');
header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS');
if ($request->getMethod() === 'options') {
exit(0);
}
}
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
{
}
}
Bài tập thực hành
Hãy implement login system với session!