Php Laravel 5重定向()->;back()不';I don’我没有按预期工作

Php Laravel 5重定向()->;back()不';I don’我没有按预期工作,php,redirect,url-routing,laravel-5,blade,Php,Redirect,Url Routing,Laravel 5,Blade,当没有HTTP\u REFERER设置时,我遇到了redirect()->back()问题 通常,当我以ID作为参数打开URL以显示特定数据行时: http://my-domain/module/ID 如果指定的ID不存在,或者当前loggedin用户没有打开它的权限,我将 if (!$this->checkPermission($id)) { return redirect()->back()->withError('message'); } // do my stu

当没有
HTTP\u REFERER
设置时,我遇到了
redirect()->back()
问题

通常,当我以ID作为参数打开URL以显示特定数据行时:
http://my-domain/module/ID

如果指定的
ID
不存在,或者当前loggedin用户没有打开它的权限,我将

if (!$this->checkPermission($id)) {
    return redirect()->back()->withError('message');
}
// do my stuff to show the datarow
但是,当我更改浏览器地址字段并加载不允许的
ID
时,就没有
HTTP\u REFERER
设置,并且
redirect()->back()
将我重定向到上次加载的JavaScript
,以便查看此视图。js
(并显示)添加到视图中,如下所示:

app.blade.php

<!DOCTYPE html>
<html lang="de">
<head>
    @section('head')
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    {!! HTML::style('assets/jquery-ui/jquery-ui.min.css?ver=1.11.4') !!}
    <!-- some more scripts -->
    @show
</head>

<body>
    @yield('content')
</body>
</html>
@extends('app')

@section('head')
    @parent
    {!! HTML::script('for_this_view.js') !!}
@stop

@section('content')
    <!-- display datarow -->
@stop

我目前的工作是扩展
BaseController
,如下所示:

<?php namespace App\Http\Controllers;

use Illuminate\Foundation\Bus\DispatchesCommands;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Foundation\Validation\ValidatesRequests;

abstract class Controller extends BaseController
{
    use DispatchesCommands, ValidatesRequests;

    /**
     * The fallback url for redirects...
     * Prevent faulty redirect if 'HTTP_REFERER' not set.
     *
     * @var string
     */
    private static $back_url = '';

    /**
     * @param string $back_url The fallback url for redirects...
     */
    public static function setBackUrl($back_url)
    {
        self::$back_url = $back_url;
    }

    /**
     * @return string
     */
    protected static function getBackUrl()
    {
        return self::$back_url;
    }

    /**
     * @return \Illuminate\Http\RedirectResponse
     */
    public static function redirect_back()
    {
        $back = self::getBackUrl();
        if (!empty($_SERVER['HTTP_REFERER']))
        {
            return redirect()->back();

        } else if (!empty($back)) {
            return redirect()->to($back);

        } else {
            return redirect()->to('/');
        }
    }
}
<?php namespace App\Http\Controllers;

use App\Http\Requests;
use App\Http\Controllers\Controller;

/**
 * Class MyController
 *
 * @package App\Http\Controllers
 */
class MyController extends Controller
{
    /**
     * Check permission for specified '$id'.
     *
     * @param int|string $id The datarow id
     * @return boolean
     */
    public function checkPermission($id)
    {...}

    /**
     * Display a listing of the resource.
     *
     * @param int|string $id The datarow id
     * @return Response
     */
    public function index($id)
    {
        if (!$this->checkPermission($id)) {
            self::setBackUrl(\URL::route('my_prefered_fallback_route'));
            return self::redirect_back()
                ->withErrors(["message"]);
        }

        return 'Hello, API';
    }
}

如果未设置
HTTP\u REFERER
,Laravel将尝试从会话获取最后一个请求。此URL存储在
illumb\Session\Middleware\StartSession
中:

protected function storeCurrentUrl(Request $request, $session)
{
    if ($request->method() === 'GET' && $request->route() && ! $request->ajax())
    {
        $session->setPreviousUrl($request->fullUrl());
    }
}
正如您所看到的,不幸的是,JS请求满足以下几个条件:

  • 获取方法
  • 按路线处理
  • 不是ajax请求
  • 解决方案 在我看来,你有两个选择

    禁用中间件 警告:我还没有测试过,可能会有副作用

    转到
    app/Http/Kernel.php
    并从
    $Middleware
    中删除
    'illumb\Session\Middleware\StartSession',
    。现在,如果没有设置
    HTTP\u REFERER
    ,Laravel将直接重定向到应用程序的根目录(
    /

    扩展中间件并添加其他约束 您可以扩展中间件并添加一些附加检查:

    class CustomStartSession extends \Illuminate\Session\Middleware\StartSession {
        public function storeCurrentUrl(Request $request, $session){
            if(!ends_with($request->url(), '.js')){
                parent::storeCurrentUrl($request, $session);
            }
        }
    }
    
    然后将
    app/Http/Kernel.php
    中的原始
    StartSession
    替换为您的,以
    .js
    结尾的URL的任何请求都不会保存为“上一个URL”,从而启用它

    更新 显然,中间件需要注册为单例才能完全发挥功能。您可以通过将其添加到其中一个服务提供商(例如,
    AppServiceProvider
    )的
    register
    方法中来实现这一点


    我知道这很难看,但您可以通过将请求方法更改为在控制器中发布来避免storeCurrentUrl()

    $request->setMethod('POST');
    

    调用
    Session::previousUrl()
    它返回什么?@lukasgeiter它显示了直接在
    之前加载的JavaScript的url,用于\u this\u view.js
    ,但这次它是在
    app.blade.php
    中指定的……这个请求是否由laravel处理?(不仅仅是像javascript文件这样的Web服务器通常都会加载)好的,我忘记了我问题中的一个重要信息。请参阅更新部分。那可能是我的问题。但是我如何改进代码,用Blade加载我的JS文件并防止重定向时出现错误?工作非常完美!谢谢很好的解决方案!我刚刚将您的
    if
    子句更改为
    if(!ends_with($request->url(),'.js')){…}
    在覆盖StartSession后,登录中断,出现“TokenMismatch”-错误,注销不做任何操作。Hrmpf,谢谢你,你确定吗?因为仅仅通过覆盖
    storeCurrentUrl
    你不应该破坏某些东西。。。如果你把它改回Laravels
    StartSession
    一切正常?是的,我自己也不明白。我对登录/注销错误的修复是使用原始的StartSession-Class.Ah。这可能就是问题所在。。。显然,你不能改变拉维尔斯的核心。将其还原,并尝试使用
    $this->app->singleton('app\Http\Middleware\CustomStartSession')在其中一个服务提供商中注册自定义类
    
    $this->app->singleton('App\Http\Middleware\CustomStartSession');
    
    $request->setMethod('POST');