From ecc
인증/권한 부여, 유효성 검사, CSRF, 대량 할당(mass assignment), 파일 업로드, 비밀 정보(secrets), 속도 제한 및 보안 배포를 위한 Laravel 보안 모범 사례입니다.
npx claudepluginhub sam42-lab/everything-claude-code-krThis skill uses the workspace's default tool permissions.
일반적인 취약점으로부터 보호하기 위한 Laravel 애플리케이션용 종합 보안 가이드입니다.
Mandates invoking relevant skills via tools before any response in coding sessions. Covers access, priorities, and adaptations for Claude Code, Copilot CLI, Gemini CLI.
Share bugs, ideas, or general feedback.
일반적인 취약점으로부터 보호하기 위한 Laravel 애플리케이션용 종합 보안 가이드입니다.
VerifyCsrfToken을 통한 CSRF 보호, SecurityHeaders를 통한 보안 헤더).auth:sanctum, $this->authorize, 정책 미들웨어).UploadInvoiceRequest).RateLimiter::for('login')).URL::temporarySignedRoute + signed 미들웨어)를 통해 보장됩니다.APP_DEBUG=false로 설정APP_KEY가 반드시 설정되어야 하며, 유출 시 교체해야 함SESSION_SECURE_COOKIE=true 및 SESSION_SAME_SITE=lax (민감한 앱의 경우 strict) 설정SESSION_HTTP_ONLY=true 설정SESSION_SAME_SITE=strict 사용라우트 보호 예시:
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
Route::middleware('auth:sanctum')->get('/me', function (Request $request) {
return $request->user();
});
Hash::make()를 사용하여 비밀번호를 해싱하고 절대 평문으로 저장하지 않음use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\Rules\Password;
$validated = $request->validate([
'password' => ['required', 'string', Password::min(12)->letters()->mixedCase()->numbers()->symbols()],
]);
$user->update(['password' => Hash::make($validated['password'])]);
$this->authorize('update', $project);
라우트 수준의 강제를 위해 정책 미들웨어 사용:
use Illuminate\Support\Facades\Route;
Route::put('/projects/{project}', [ProjectController::class, 'update'])
->middleware(['auth:sanctum', 'can:update,project']);
$fillable 또는 $guarded를 사용하고 Model::unguard() 지양DB::select('select * from users where email = ?', [$email]);
{{ }}){!! !!} 사용VerifyCsrfToken 미들웨어를 활성화 상태로 유지@csrf를 포함하고 SPA 요청의 경우 XSRF 토큰 전송Sanctum을 사용한 SPA 인증의 경우 stateful 요청이 구성되었는지 확인:
// config/sanctum.php
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', 'localhost')),
final class UploadInvoiceRequest extends FormRequest
{
public function authorize(): bool
{
return (bool) $this->user()?->can('upload-invoice');
}
public function rules(): array
{
return [
'invoice' => ['required', 'file', 'mimes:pdf', 'max:5120'],
];
}
}
$path = $request->file('invoice')->store(
'invoices',
config('filesystems.private_disk', 'local') // 비공개 디스크로 설정
);
throttle 미들웨어 적용use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\RateLimiter;
RateLimiter::for('login', function (Request $request) {
return [
Limit::perMinute(5)->by($request->ip()),
Limit::perMinute(5)->by(strtolower((string) $request->input('email'))),
];
});
저장된 민감한 컬럼에 대해 암호화된 캐스트(encrypted casts) 사용.
protected $casts = [
'api_token' => 'encrypted',
];
헤더 설정을 위한 미들웨어 예시:
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
final class SecurityHeaders
{
public function handle(Request $request, \Closure $next): Response
{
$response = $next($request);
$response->headers->add([
'Content-Security-Policy' => "default-src 'self'",
'Strict-Transport-Security' => 'max-age=31536000', // 모든 서브도메인이 HTTPS인 경우에만 includeSubDomains/preload 추가
'X-Frame-Options' => 'DENY',
'X-Content-Type-Options' => 'nosniff',
'Referrer-Policy' => 'no-referrer',
]);
return $response;
}
}
config/cors.php에서 허용 오리진 제한// config/cors.php
return [
'paths' => ['api/*', 'sanctum/csrf-cookie'],
'allowed_methods' => ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
'allowed_origins' => ['https://app.example.com'],
'allowed_headers' => [
'Content-Type',
'Authorization',
'X-Requested-With',
'X-XSRF-TOKEN',
'X-CSRF-TOKEN',
],
'supports_credentials' => true,
];
use Illuminate\Support\Facades\Log;
Log::info('User updated profile', [
'user_id' => $user->id,
'email' => '[REDACTED]',
'token' => '[REDACTED]',
]);
composer audit을 실행하여 취약한 패키지 체크