You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Lumen后端与AngularJS前端限制视频URL直接浏览器访问

How to Prevent Direct Access to Video URLs in AngularJS + Lumen Stack

Alright, let's break down how to stop users from grabbing your video URL via browser dev tools and accessing it directly outside your app. The key here is that front-end restrictions alone won't cut it—we need to pair them with back-end validation using your Lumen API. Here's a step-by-step solution:


1. Back-End: Generate Signed, Expiring Video URLs (Lumen)

The core fix lives in Lumen. Instead of exposing your raw video URL, we'll create an API endpoint that generates a temporary, signed URL only for authenticated/authorized users. This URL will expire after a short time, and any tampering will invalidate it.

Step 1: Add Routes

First, define two routes in your Lumen routes file:

// routes/api.php
$router->get('/api/video/{videoId}', 'VideoController@getSignedUrl');
$router->get('/video/stream', 'VideoController@streamVideo')->name('video.stream');

Step 2: Implement the Controller

Create a VideoController to handle URL signing and video streaming:

// app/Http/Controllers/VideoController.php
namespace App\Http\Controllers;

use Illuminate\Http\Request;

class VideoController extends Controller
{
    public function getSignedUrl(Request $request, $videoId)
    {
        // 1. Validate user authentication (adjust based on your auth system: JWT, session, etc.)
        if (!$request->user()) {
            return response()->json(['error' => 'Unauthorized'], 401);
        }

        // 2. Define expiration time (e.g., 10 minutes—short enough to prevent reuse)
        $expiresAt = now()->addMinutes(10);
        // Generate a unique signature using your app key and video details
        $signature = hash_hmac('sha256', $videoId . $expiresAt->timestamp, env('APP_KEY'));

        // 3. Return the signed stream URL
        return response()->json([
            'signedUrl' => route('video.stream', [
                'videoId' => $videoId,
                'expires' => $expiresAt->timestamp,
                'signature' => $signature
            ])
        ]);
    }

    public function streamVideo(Request $request)
    {
        $videoId = $request->input('videoId');
        $expires = $request->input('expires');
        $signature = $request->input('signature');

        // Validate the signature and expiration time
        $expectedSignature = hash_hmac('sha256', $videoId . $expires, env('APP_KEY'));
        if ($signature !== $expectedSignature || now()->timestamp > $expires) {
            return response()->json(['error' => 'Invalid or expired URL'], 403);
        }

        // Optional: Add additional permission checks (e.g., user owns the video, has subscription)
        if (!$this->userHasAccess($request->user(), $videoId)) {
            return response()->json(['error' => 'Access denied'], 403);
        }

        // Stream the video file (adjust path based on your storage: local, S3, etc.)
        $videoPath = storage_path("app/videos/{$videoId}.mp4");
        return response()->file($videoPath, [
            'Content-Type' => 'video/mp4',
            'Content-Disposition' => 'inline' // Force browser to play inline instead of downloading
        ]);
    }

    // Helper method to check user permissions (customize to your needs)
    private function userHasAccess($user, $videoId)
    {
        // Example: Check if user has a record in a video_access table
        return true; // Replace with your actual logic
    }
}

2. Front-End: Dynamically Load the Signed URL (AngularJS)

Instead of hardcoding the video URL in your HTML, fetch the signed URL from your Lumen API and bind it to the video element dynamically.

Controller Code

angular.module('yourAppName').controller('VideoPlayerController', function($scope, $http) {
    // Get your video ID from route params, scope, or wherever it's stored
    const videoId = 'your-video-identifier';

    // Fetch the signed URL from the backend
    $http.get(`/api/video/${videoId}`)
        .then(response => {
            $scope.videoUrl = response.data.signedUrl;
        })
        .catch(error => {
            console.error('Failed to load video:', error);
            // Handle error (e.g., show "Access Denied" message)
            $scope.videoError = true;
        });

    // Optional: Prevent right-click on video to make URL harder to grab (not foolproof!)
    $scope.blockContextMenu = function(event) {
        event.preventDefault();
    };
});

HTML Template

<div ng-controller="VideoPlayerController">
    <video ng-src="{{ videoUrl }}" 
           type="video/mp4" 
           controls
           ng-contextmenu="blockContextMenu($event)">
        <track src="http://www.videogular.com/assets/subs/pale-blue-dot.vtt" 
               kind="subtitles" 
               srclang="en" 
               label="English">
    </video>

    <div ng-if="videoError" class="error-message">
        You don't have permission to view this video.
    </div>
</div>

Key Notes

  • Front-end restrictions are just a deterrent: Savvy users can still find workarounds (e.g., network tab in dev tools). The back-end signature and validation are the only reliable way to block unauthorized access.
  • Adjust storage logic: If you're using cloud storage like S3 or Cloudinary, use their SDKs to generate signed URLs instead of the local file method shown above—most cloud providers have built-in support for this.
  • Short expiration times: Keep the URL expiration window small (5-15 minutes) to minimize the risk of leaked URLs being reused.

内容的提问来源于stack exchange,提问作者viralchampanery

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:47:36