请问如何实现 仅限管理员访问后台?

我希望只有管理员能访问用户列表,并删除用户,所以我建了一个后台管理界面 (Admin Panel),把用户列表入口转移进去了,并在主页下方放了一个按钮来进入该管理界面,然后建了一个中间件(CheckAdmin)来检查用户是否有管理员权限,并分配给后台管理界面的路由,结果访问后台报错:

Symfony \ Component \ Debug \ Exception \ FatalThrowableError (E_ERROR)
Function name must be a string

看了半天各种文档彻底晕了,不知道该怎么办了,而且我不知道这个用路由+中间件的思路是否正确,或者该用userpolicy吗?求大神帮我看看...不胜感激。下面是我的代码:


主页:home.blade.php
(后台管理界面按钮倒是没问题,只有管理员可见,普通用户不可见)

......
 <div class="buttons_wrap">
        <hr/>
        @can('show_admin', Auth::user())
          <a class="btn btn-lg btn-success main_button" href="{{ route('admin') }}" role="button"><font color=red><b>Admin Panel</b></font></a>
        @endcan
    </div>
    ......

中间件:CheckAdmin.php

<?php

namespace App\Http\Middleware;

use Closure;

class CheckAdmin
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function CheckAdmin($request, Closure $next)
    {
        if ($request->is_admin=1){
            return view('users.admin');
        }else{
            return redirect('/');
            session()->flash('info', 'Sorry, only admins can access!');
        }
        return $next($request);
    }
}

路由:

......
Route::resource('users', 'UsersController');
Route::get('admin', 'UsersController@admin')->middleware('CheckAdmin')->name('admin');

UsersController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Requests;
use App\Models\User;

class UsersController extends Controller
{
  .......

    public function admin(User $user)
    {
        return view('users.admin');  //后台管理界面名为admin.balde.php
    }
}
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
yema
最佳答案

报错信息提示你的行为是没有权限的。这种错误是可打断点来精确到哪一句代码出的错。

代码中逻辑存在错误:
file

5年前 评论
讨论数量: 8
yema

你中间件的逻辑有问题。程序执行不到UserController中。但是是可以返回视图的。建议你将中间件的返回视图的代码拿掉。由控制器去操作返回视图。

报错信息截的全一点。

file
这个判断里面的应该是 == 。

5年前 评论

CheckAdmin 方法参数 $request 少了个类型提示吧,应该是:

public function CheckAdmin(Request $request, Closure $next)
{
       //
 }
5年前 评论

@yema
报错是这样的:
file
图中右边黑色部分:

/home/vagrant/code/w2_support/vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php
                    return $pipe($passable, $stack);
                } elseif (! is_object($pipe)) {
                    list($name, $parameters) = $this->parsePipeString($pipe);

                    // If the pipe is a string we will parse the string and resolve the class out
                    // of the dependency injection container. We can then build a callable and
                    // execute the pipe function giving in the parameters that are required.
                    $pipe = $this->getContainer()->make($name);

                    $parameters = array_merge([$passable, $stack], $parameters);
                } else {
                    // If the pipe is already an object we'll just make a callable and pass it to
                    // the pipe as-is. There is no need to do any extra parsing and formatting
                    // since the object we're given was already a fully instantiated object.
                    $parameters = [$passable, $stack];
                }

                return method_exists($pipe, $this->method)
                                ? $pipe->{$this->method}(...$parameters)
                                : $pipe(...$parameters);
            };
        };
    }

    /**
     * Parse full pipe string to get name and parameters.
     *
     * @param  string $pipe
     * @return array
     */
    protected function parsePipeString($pipe)
    {
        list($name, $parameters) = array_pad(explode(':', $pipe, 2), 2, []);

        if (is_string($parameters)) {
            $parameters = explode(',', $parameters);
        }

        return [$name, $parameters];
    }
Arguments
"Function name must be a string"

我把中间件里返回试图那段拿掉了,改成这样了:


 public function CheckAdmin(Request $request, Closure $next)
    {
        if ($request->is_admin==1){
            return $next($request);
        }else{
            return redirect('/');
            session()->flash('info', 'Sorry, only admins can access!');
        }
    }
5年前 评论
yema

中间件里方法名错了。handle。记得使用命令生成

5年前 评论

@yema 谢了,昨天我换了个方法又试了一下,不用中间件,直接用UsersContrlloer 来验证,然后成功了,但是用非管理员账号访问后台只是报错,按照代码应该重定向然后显示一些信息的,不知道是哪又出问题了,能麻烦再帮我看看吗?
这是非管理员账号访问后台的报错界面:
file
下面是代码:
UsersContrlloer .php


<?php namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Requests;
use App\Models\User;

class UsersController extends Controller
{ 
......
 public function admin_panel(User $currentUser)
    {
        $this->authorize('admin_rights', $currentUser);
        if ($currentUser->is_admin!==0){
            return view('users.admin_panel');
        }else{
            return redirect()->route('/');
            session()->flash('danger', 'Sorry, only admins can access!');  //按理说应该会重定向到主页然后显示错误信息的
        }
    }
}

UserPolicy.php


 public function admin_rights(User $currentUser, User $user)
    {
        return $currentUser->is_admin;
    }

路由:


Route::get('admin_panel', 'UsersController@admin_panel')->name('admin');
5年前 评论
yema

报错信息提示你的行为是没有权限的。这种错误是可打断点来精确到哪一句代码出的错。

代码中逻辑存在错误:
file

5年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!