tritue.edu.vn


Mã hoá tham số trong url bằng SqidUrl

Tự động mã hóa URL bằng Sqids + Chữ ký HMAC mà không cần sửa view, route, controller

Ưu điểm

✔ Không sửa Controller.

✔ Không sửa Route.

✔ Không sửa View.

✔ Không sửa Model.

✔ Tự động encode.

✔ Tự động decode.

✔ Có thể bật tắt.

✔ Có chữ ký chống sửa URL.

✔ Tốc độ gần như không ảnh hưởng.

 

Cấu trúc tổng quan:
 

app

├── Http
│   └── Middleware
│       └── DecodeSqidRouteParameters.php

├── Providers
│   └── SqidUrlServiceProvider.php

└── Support
    └── SqidUrl
        ├── SqidUrl.php
        └── SqidUrlGenerator.php

config
└── sqid_url.php

bootstrap
├── app.php
└── providers.php

.env



Bước 1: Cài Sqids

Copy
         

composer require sqids/sqids


Bước 2: Khai báo .env; nếu muốn tắt chế độ mã thì đặt: SQID_URL_ENABLED=false rồi php artisan optimize:clear

Copy
         

SQID_URL_ENABLED=true
SQID_URL_MIN_LENGTH=8

SQID_URL_SIGNED=true
SQID_URL_SIGNATURE_LENGTH=10


Bước 3. Tạo file config/sqid_url.php

Copy
         

<?php

 

return [

'enabled' => env('SQID_URL_ENABLED', false),

 

'min_length' => env('SQID_URL_MIN_LENGTH', 8),

 

'signed' => env('SQID_URL_SIGNED', true),

 

'signature_length' => env('SQID_URL_SIGNATURE_LENGTH', 10),

 

'separator' => '~',

 

'ignore_parameters' => [

'page',

'q',

'keyword',

'search',

'sort',

'direction',

'date',

'from_date',

'to_date',

'month',

'year',

'slug',

'token',

'locale',

],

];


Bước 4. Tạo app/Support/SqidUrl/SqidUrl.php

Copy
         

<?php

 

namespace App\Support\SqidUrl;

 

use Sqids\Sqids;

 

class SqidUrl

{

protected static ?Sqids $sqids = null;

 

public static function enabled(): bool

{

return (bool) config('sqid_url.enabled', false);

}

 

public static function signed(): bool

{

return (bool) config('sqid_url.signed', true);

}

 

public static function instance(): Sqids

{

if (! static::$sqids) {

static::$sqids = new Sqids(

minLength: (int) config('sqid_url.min_length', 8)

);

}

 

return static::$sqids;

}

 

public static function encode(int|string $id): string

{

$code = static::instance()->encode([(int) $id]);

 

if (! static::signed()) {

return $code;

}

 

return $code . config('sqid_url.separator', '~') . static::signature($code);

}

 

public static function decode(string $value): ?int

{

if (static::signed()) {

$separator = config('sqid_url.separator', '~');

 

if (! str_contains($value, $separator)) {

return null;

}

 

[$code, $signature] = explode($separator, $value, 2);

 

if (! hash_equals(static::signature($code), $signature)) {

return null;

}

 

$decoded = static::instance()->decode($code);

 

return $decoded[0] ?? null;

}

 

$decoded = static::instance()->decode($value);

 

return $decoded[0] ?? null;

}

 

public static function looksSigned(string $value): bool

{

return str_contains($value, config('sqid_url.separator', '~'));

}

 

protected static function signature(string $code): string

{

$key = config('app.key');

 

$hash = hash_hmac('sha256', $code, $key, true);

 

$signature = rtrim(strtr(base64_encode($hash), '+/', '-_'), '=');

 

return substr($signature, 0, (int) config('sqid_url.signature_length', 10));

}

 

public static function shouldHandleParameter(?string $name): bool

{

if (! $name) {

return false;

}

 

return ! in_array(

$name,

config('sqid_url.ignore_parameters', []),

true

);

}

}


Bước 5: Tạo app/Support/SqidUrl/SqidUrlGenerator.php

Copy
         

<?php

 

namespace App\Support\SqidUrl;

 

use Illuminate\Contracts\Routing\UrlRoutable;

use Illuminate\Routing\Route;

use Illuminate\Routing\UrlGenerator;

 

class SqidUrlGenerator extends UrlGenerator

{

public function toRoute($route, $parameters, $absolute)

{

if (SqidUrl::enabled() && $route instanceof Route) {

$parameters = $this->encodeRouteParameters($route, $parameters);

}

 

return parent::toRoute($route, $parameters, $absolute);

}

 

protected function encodeRouteParameters(Route $route, $parameters): array

{

$parameters = is_array($parameters) ? $parameters : [$parameters];

 

$names = $route->parameterNames();

 

foreach ($parameters as $key => $value) {

$paramName = is_string($key)

? $key

: ($names[$key] ?? null);

 

if (! SqidUrl::shouldHandleParameter($paramName)) {

continue;

}

 

if ($value instanceof UrlRoutable) {

$value = $value->getRouteKey();

}

 

if (is_numeric($value) && (int) $value > 0) {

$parameters[$key] = SqidUrl::encode($value);

}

}

 

return $parameters;

}

}


Bước 6: Tạo app/Http/Middleware/DecodeSqidRouteParameters.php

Copy
         

<?php

 

namespace App\Http\Middleware;

 

use App\Support\SqidUrl\SqidUrl;

use Closure;

use Illuminate\Http\Request;

 

class DecodeSqidRouteParameters

{

public function handle(Request $request, Closure $next)

{

if (! SqidUrl::enabled()) {

return $next($request);

}

 

$route = $request->route();

 

if (! $route) {

return $next($request);

}

 

foreach ($route->parameters() as $name => $value) {

if (! SqidUrl::shouldHandleParameter($name)) {

continue;

}

 

if (! is_string($value)) {

continue;

}

 

if (is_numeric($value)) {

continue;

}

 

$decoded = SqidUrl::decode($value);

 

if ($decoded) {

$route->setParameter($name, $decoded);

continue;

}

 

if (SqidUrl::signed() && SqidUrl::looksSigned($value)) {

abort(403, 'Invalid URL signature.');

}

}

 

return $next($request);

}

}


Bước 7: Tạo app/Providers/SqidUrlServiceProvider.php

Copy
         

<?php

 

namespace App\Providers;

 

use App\Support\SqidUrl\SqidUrlGenerator;

use Illuminate\Support\ServiceProvider;

 

class SqidUrlServiceProvider extends ServiceProvider

{

public function register(): void

{

$this->app->singleton('url', function ($app) {

$url = new SqidUrlGenerator(

$app['router']->getRoutes(),

$app['request'],

$app['config']['app.asset_url'] ?? null

);

 

$url->setSessionResolver(function () use ($app) {

return $app->bound('session') ? $app['session'] : null;

});

 

$url->setKeyResolver(function () use ($app) {

return $app['config']['app.key'];

});

 

$app->rebinding('request', function ($app, $request) {

$app['url']->setRequest($request);

});

 

return $url;

});

}

}


Bước 8. Đăng ký Provider: bootstrap/providers.php

Copy
         

return [

......

App\Providers\SqidUrlServiceProvider::class,

];


Bước 9. Đăng ký Middleware: bootstrap/app.php

Copy
         

- thêm ở đẩu file: use App\Http\Middleware\DecodeSqidRouteParameters;

- tìm đến: 

->withMiddleware(function (Middleware $middleware) {
    //thêm đoạn này vào 
    $middleware->web(prepend: [
        DecodeSqidRouteParameters::class,
    ]);

})

 


Bước 10: Xoá cache

Copy
         

php artisan optimize:clear




Link chia sẻ bài viết
Copy
            https://tritue.edu.vn/tuecode/tracnghiem30/site/data/YVdRc01qVXpMRjl5YjNWMFpTeGlZV2wyYVdWMEwzQnZjM1F2ZG1sbGR3PT0%3D         

Bài viết liên quan