仅通过Auth Middleware和基于令牌的身份验证访问存储文件夹中的文件

时间:2016-05-22 08:51:39

标签: php laravel laravel-5 laravel-5.1 laravel-5.2

我的Laravel网站上有以下文件夹。

  

/存储/资产/媒体

此文件夹可以包含以下信息

/storage/Asset/Media/1/abc.png

/storage/Asset/Media/2/abc.png

此处1或2是文件夹名称。

我有以下代码来保护文件夹,以便没有人可以在没有身份验证的情况下访问该文件夹

Route::group(['middleware' => ['web', 'auth']], function () {
    Route::get('/storage/Asset/Media/{ID}/{eded}', array(
        'as' => 'Files',
        'uses' => 'User\Account\Media\MediaController@DownloadMedia',
    ));
});

因此,在用户的会话未在浏览器中过期之前,没有人可以访问这些文件。

问题出现在Android中,所以现在没有人可以访问由于Auth Middleware而导致的文件。

有人可以建议这样的方法,可以通过基于令牌的身份验证(通过Android)和使用Auth Controller(通过网站)下载文件吗?

5 个答案:

答案 0 :(得分:6)

您不需要在routes.php中使用任何其他配置,如果您遵循本指南,一切都会正常工作:

最简单的解决方案是创建名为api_token的列为users表。然后,当尝试从Android设备访问资源时,只需将?api_token=<token>添加到您的网址,其中<token>api_token表格中的users列。

例如: domain.com/storage/Asset/Media/1/2?api_token=123hello4secret

系统会尝试使用api_token == 123hello4secret搜索用户记录,因此只需将123hello4secret放入您的用户api_token字段。

如果你想知道为什么你应该api_token作为列名,答案就在这里:https://github.com/laravel/framework/blob/2a38acf7ee2882d831a3b9a1361a710e70ffa31e/src/Illuminate/Auth/TokenGuard.php#L45如果在请求字段中找到,{Laravel将尝试使用api_token授权你。

此外,您可以使用HTTP标头来使用令牌进行授权:
标题示例:

Authorization: Bearer 123hello4secret

答案 1 :(得分:2)

请注意,默认情况下&#39;存储&#39;无论如何都无法访问文件夹 - 只有&#39; public&#39;文件夹可公开访问。因此,您可以使用任何URL作为文件下载控制器。

您需要两条路线 - 一条用于基于cookie的身份验证(网络用户),另一条用于无状态(令牌)会话:

// URL can be anything you want
Route::get('downloads/{ID}/{eded}', [
        'middleware' => ['web', 'auth'],
        'as' => 'Files',
        'uses' => 'MediaController@DownloadMedia',
]); 

// For API tokens, use 'api' guard of Auth middleware
// URL has to be different, too
Route::get('api/downloads/{ID}/{eded}', [
        'middleware' => ['auth:api'],
        'as' => 'Files',
        'uses' => 'MediaController@DownloadMedia',
]); 

您还需要在users表中添加一个令牌字段。在您的用户表迁移中添加一行:

$table->string('api_token', 60)->unique();

然后,您需要生成此令牌。如果要使用相同的令牌(无过期或刷新),则可以在创建新用户时生成它。您可以在User类中使用它:

/**
 * @return void
 */
public function boot()
{
    User::creating(function ($user) {
        $user->api_token = str_random(60);
    });
}

否则,您可以强制在每次登录尝试时刷新令牌(在AuthController中使用postLogin),也可以使用单独的控制器方法来交换令牌的电子邮件和密码。

答案 2 :(得分:0)

您需要在auth:api中间件

中包装新路由

使用Laravel的API身份验证非常简单。

答案 3 :(得分:0)

您可以将.htaccess文件放在/ storage / Asset / Media

代码:

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews
    </IfModule>

    RewriteEngine On

    # Redirect Trailing Slashes If Not A Folder...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)/$ /$1 [L,R=301]

    # Handle Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]

    # Handle Authorization Header
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
</IfModule>

您可以在php中访问文件,但直接链接到文件将无法正常工作。

答案 4 :(得分:0)

在您的用户表中,设置一个可以为空的列api_token

现在每次用户通过Api登录时,在db中设置此api_token并将其发送给Api消费者。

现在,在进一步请求时,Api消费者将在请求标头中发回令牌。所以只需配置Authenticate Middleware:

    public function handle($request, Closure $next)
    {   
      if(!empty($request->header('Auth-Token'))) {
        $api_token = $request->header('Auth-Token');
        $user = User::where('api_token', $api_token)->first();
        if(is_null($user)) //Unauthorize: write response to return 
      } elseif ($this->auth->guest()) {
        if ($request->ajax()) {
            return response('Unauthorized.', 401);
        } else {
            return redirect()->guest('/');
        }
     }

      return $next($request);
    }