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

Laravel 5.4:public目录用户视频未登录可访问的权限控制问题咨询

这个问题的核心原因很明确:public目录是Web服务器(Nginx/Apache)直接对外开放的,所有请求都会被服务器直接处理,完全绕过了Laravel的权限中间件。所以要解决这个问题,我们需要把用户的视频文件移出public目录,通过Laravel来接管文件的访问请求,从而实现权限校验。

下面是具体的实现步骤:

1. 迁移用户视频文件夹到非公开目录

首先,把原来放在public/{userId}的用户视频文件夹,移动到storage/app/users_videos/{userId}目录下。这个目录默认是Web服务器无法直接访问的,完美避开了无权限访问的问题。

如果管理员是通过FTP上传文件,你需要调整FTP的根目录指向storage/app/users_videos,或者让管理员上传后手动/自动将文件移动到这个目录。

2. 创建受权限保护的路由

在routes/web.php中添加一个路由,用auth中间件保护,确保只有登录用户才能访问:

Route::get('/user-videos/{userId}/{filename}', 'UserVideoController@show')
    ->middleware('auth')
    ->name('user.videos.show');

3. 编写控制器处理文件访问与权限校验

创建UserVideoController,在里面实现权限判断和文件返回逻辑:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Http\Response;

class UserVideoController extends Controller
{
    public function show($userId, $filename)
    {
        // 权限校验逻辑:两种情况允许访问
        // 1. 当前登录用户是管理员(假设你的User模型有isAdmin()方法)
        // 2. 当前登录用户就是文件所属的用户
        $currentUser = auth()->user();
        if (!$currentUser->isAdmin() && $currentUser->id != $userId) {
            abort(403, '你没有权限访问该文件');
        }

        // 拼接文件路径
        $filePath = "users_videos/{$userId}/{$filename}";

        // 检查文件是否存在
        if (!Storage::exists($filePath)) {
            abort(404, '文件不存在');
        }

        // 获取文件的绝对路径
        $absolutePath = storage_path("app/{$filePath}");

        // 返回文件,Laravel会自动识别MIME类型并设置响应头
        return response()->file($absolutePath);

        // 如果需要让浏览器下载而不是在线播放,可以用download方法:
        // return Storage::download($filePath, $filename);
    }
}

注意:如果你的User模型没有isAdmin()方法,需要根据你的权限体系调整校验逻辑,比如检查用户的role字段是否为管理员。

4. 调整前端/管理员的访问链接

原来直接访问public/123/video.mp4的链接,现在要改成路由对应的地址,比如/user-videos/123/video.mp4。这样所有的视频请求都会经过Laravel的权限校验。

可选:优化Web服务器配置(如果不想移动文件)

如果因为某些原因无法移动文件到storage目录,你可以通过Web服务器配置,把用户视频的请求转发到Laravel处理。以Nginx为例,在站点配置中添加:

location ~ ^/[0-9]+/.*\.(mp4|avi|mov)$ {
    rewrite ^/(.*)$ /user-videos/$1 last;
}

这个规则会把所有类似/123/video.mp4的请求转发到/user-videos/123/video.mp4,然后由Laravel的路由处理权限校验。不过这种方法不如移动文件到storage目录安全,因为如果服务器配置出错,可能会导致文件直接暴露。

额外注意事项

  • 确保storage/app/users_videos目录有正确的读写权限,Laravel需要能读取这个目录下的文件。
  • 如果使用云存储(比如AWS S3),可以直接用Laravel的Storage门面处理,权限逻辑完全一致,只需要调整文件路径的前缀。
  • 可以添加缓存头优化视频加载速度,比如在返回文件时添加Cache-Control响应头:
    return response()->file($absolutePath)->header('Cache-Control', 'public, max-age=31536000');
    

这样处理后,只有登录且有权限的用户才能访问对应的视频文件,完美解决了原问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:36:17