【问题标题】:Laravel 5: when protecting delete route after authentication MethodNotAllowedHttpException in RouteCollection.phpLaravel 5:在 RouteCollection.php 中验证 MethodNotAllowedHttpException 后保护删除路由时
【发布时间】:2016-02-12 13:19:47
【问题描述】:

希望有人能帮忙。

在这个阶段,我的所有其他方法(编辑和新方法)都可以很好地处理受保护的路由。只是删除效果不好。 (尽管我确信我正在做的事情很愚蠢)。我已经通过将删除从路由组中删除并分配了中间件来删除身份验证,它成功地删除了配置(对象),因此操作正常工作。我尝试按照另一篇文章中的建议在萤火虫中检查它,我得到:

405 Method Not Allowed

Allow           DELETE
Cache-Control   no-cache, private
Connection      close
Content-Type    text/html
Date            Wed, 11 Nov 2015 12:36:40 GMT
Host            127.0.0.1:8000
X-Powered-By    PHP/5.5.9-1ubuntu4.14

我想让用户在创建新条目或编辑现有条目之前进行身份验证(同样用于删除)。

当我通过按下按钮尝试删除时,它会引导我进行身份验证/登录(laravel 的开箱即用快速启动身份验证),但是在成功登录后,地址栏中的 url 是:

127.0.0.1:8000/delete/48

显示:

MethodNotAllowedHttpException in RouteCollection.php line 219:

routes.php:

Route::get('/new', [
    'as' => 'create', 
    'middleware' => 'auth',
    'uses' => 'ConfigsController@getCreate'
]);
$router->group(['middleware' => 'auth'], function($router)
    {
    Route::get('{id}/edit', 'ConfigsController@edit');
    Route::delete('/delete/{id}/', 'ConfigsController@getDL');
    });

+--------+----------+-------------------+----------+-------------------------------------------------------+------------+
| Domain | Method   | URI               | Name     | Action                                                | Middleware |
+--------+----------+-------------------+----------+-------------------------------------------------------+------------+
|        | DELETE   | delete/{id}       |          | App\Http\Controllers\ConfigsController@getDL          | auth       |
|        | POST     | new               |          | App\Http\Controllers\ConfigsController@postCreate     |            |
|        | GET|HEAD | new               | create   | App\Http\Controllers\ConfigsController@getCreate      | auth       |
|        | GET|HEAD | {id}/edit         |          | App\Http\Controllers\ConfigsController@edit           | auth       |

ConfigsController.php:

public function getCreate() {
return view('create');
}

public function edit($id)
{
$configs = Config::find($id);
    return view('edit')
    ->with('configs', $configs);
}

public function getDL($id) {
    $configs = Config::find($id)->delete();
    return Redirect::to('/');
}

index.blade.php (edit & delete) & app.blade.php (new):

<ul class="nav navbar-nav">
  <li><a href="{{ URL::route('create') }}">New</a></li>
</ul>

{!! Form::open(array('url' => '/delete/' . $config->id . '/', 'class' => 'pull-right')) !!}
{!! Form::hidden('_method', 'DELETE') !!}
{!! Form::submit('Delete this Config', array('class' => 'btn btn-warning')) !!}
{!! Form::close() !!}

<a class="btn btn-small btn-info" href="{{ URL::to('/' . $config->id . '/edit') }}">Edit this Config</a>

【问题讨论】:

    标签: php laravel authentication


    【解决方案1】:

    这是因为 Laravel authenticate() 开箱即用的函数在重定向时使用“预期”。

    这意味着当用户未登录并在 /whateverpage 发出获取请求时,Laravel 会介入并强制用户登录,成功登录后 Laravel 会将用户重定向到“预期”页面,在我们的示例中为 @987654326 @ 和你的情况是 /delete/48。

    /**
    * Send the response after the user was authenticated.
    *
    * @param  \Illuminate\Http\Request  $request
    * @param  bool  $throttles
    * @return \Illuminate\Http\Response
    */
    protected function handleUserWasAuthenticated(Request $request, $throttles)
    {
        if ($throttles) {
            $this->clearLoginAttempts($request);
        }
    
        if (method_exists($this, 'authenticated')) {
            return $this->authenticated($request, Auth::user());
        }
    
        return redirect()->intended($this->redirectPath());
    }
    

    此代码在 trait 内部,因此您正在寻找 "override-ing" trait 函数。


    解决方案 使用$redirectPath

    从this documentation section你可以看到设置$redirectPath是你所需要的。

    当用户成功通过身份验证后,他们将被重定向到 /home URI,您需要注册一个路由来处理。您可以通过在 AuthController 上定义 redirectPath 属性来自定义身份验证后重定向位置:protected $redirectPath = '/dashboard';


    解决方法及原因

    您会得到MethodNotAllowedHttpException,因为浏览器只能执行 GET 或 POST 请求; here 是来自 Laravel 文档的更多信息(表单方法欺骗)。

    HTML 表单不支持 PUT、PATCH 或 DELETE 操作。因此,在定义从 HTML 表单调用的 PUT、PATCH 或 DELETE 路由时,您需要向表单添加隐藏的 _method 字段。

    由于您没有使用表单来删除“配置”,因此您必须使用 GET 而不是 DELETE

    Route::delete('/delete/{id}/', 'ConfigsController@getDL'); Route::get('/delete/{id}/', 'ConfigsController@getDL');


    工作示例

    $ php artisan route:list

    +--------+----------+--------------------+---------------+--------------------------------------------------+------------+
    | Domain | Method   | URI                | Name          | Action                                           | Middleware |
    +--------+----------+--------------------+---------------+--------------------------------------------------+------------+
    |        | GET|HEAD | config/create      |               | App\Http\Controllers\ConfigController@getCreate  | auth       |
    |        | POST     | config/create      |               | App\Http\Controllers\ConfigController@postCreate | auth       |
    |        | GET|HEAD | config/{id}/delete | config.delete | App\Http\Controllers\ConfigController@destroy    | auth       |
    |        | GET|HEAD | config/{id}/edit   |               | App\Http\Controllers\ConfigController@getEdit    | auth       |
    |        | POST     | config/{id}/edit   |               | App\Http\Controllers\ConfigController@postEdit   | auth       |
    +--------+----------+--------------------+---------------+--------------------------------------------------+------------+
    

    routes.php

    Route::group(['middleware' => 'auth'], function () {
        Route::group(['prefix' => 'config'], function() {
            Route::get('create', 'ConfigController@getCreate');
            Route::post('create', 'ConfigController@postCreate');
    
            Route::get('{id}/edit', 'ConfigController@getEdit'); 
            Route::post('{id}/edit', 'ConfigController@postEdit');
    
            Route::get('{id}/delete', ['as' => 'config.delete', 'uses' => 'ConfigController@destroy']);
        });
    });
    

    和控制器(注意它被重命名为ConfigController.php)

    <?php namespace App\Http\Controllers;
    
    
    use App\Config;
    
    class ConfigController extends Controller {
    
        public function index()
        {
            // just show and sort, paginate... all config(s)
        }
    
        public function getCreate() {
            return view('create');
        }
    
        public function postCreate() {
    
    
        }
    
        public function getEdit($id, Config $config) { //injecting config model
            return view('edit')->with('config', $config->findOrFail($id));
        }
    
        public function postEdit($id, Config $config) {
            //do something with data that user sent us
            //Input::all();
            //$config->create([])
    
    
            //and redirect
            return Redirect::to('/');
        }
    
        public function destroy($id, Config $config) {
            $config->findOrFail($id)->delete();
            return Redirect::to('/');
        }
    
    }
    

    并用按钮生成“删除链接”

    <a class="btn btn-small btn-warning" href="{{ route('config.delete', ['id' => $config->id]); }}">Delete</a>
    

    【讨论】:

    • 感谢您的快速回复@Kyslik。就是这样,$redirectPath 已经设置好了 Auth/AuthController.php: protected $redirectPath = '/'; protected $loginPath = 'auth/login';
    • 试着把它放到你的ConfigsController.php
    • 不幸的是@Kyslik,结果相同。我在萤火虫中注意到的一件事是:当未经过身份验证时 - 进程失败,即成功登录后重定向:萤火虫报告:GET 50,带有标题:允许删除,所以我发送错误的方法?如果我在出现错误后刷新页面并尝试删除身份验证删除,那么萤火虫报告成功:POST 50,然后我可以使用 DELETE 方法看到 Post Params
    • 谢谢,我想我已经把它放在了:{!! Form::hidden('_method', 'DELETE') !!} 我看的越多,我认为它可能与中间件有关......我想我可能需要中间件之后的路线.. 。我会告诉你。感谢您迄今为止的帮助。
    • 您是否尝试过按照我的建议更改路线?您的方法甚至被称为“get”-> @getDL(也删除了那个_method ...)它解决了“预期”部分...
    猜你喜欢
    • 2015-10-29
    • 1970-01-01
    • 2015-09-22
    • 2016-08-30
    • 1970-01-01
    • 1970-01-01
    • 2016-02-22
    • 1970-01-01
    • 2016-10-20
    相关资源
    最近更新 更多