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
你不应该破坏某些东西。。。如果你把它改回LaravelsStartSession
一切正常?是的,我自己也不明白。我对登录/注销错误的修复是使用原始的StartSession-Class.Ah。这可能就是问题所在。。。显然,你不能改变拉维尔斯的核心。将其还原,并尝试使用$this->app->singleton('app\Http\Middleware\CustomStartSession')在其中一个服务提供商中注册自定义类代码>
$this->app->singleton('App\Http\Middleware\CustomStartSession');
$request->setMethod('POST');