本书未发布

56. 访问限制

未匹配的标注

简介

在本节里,我们将限制只有登录用户才可以修改个人信息。

需求

在本节里我们将限制只有登录用户才可以修改个人信息,这功能也是 产品分解 里用户和游客的一个不同之处。按照 产品分解 里的用例说明,在接下来几章里还有很多用例是只允许登录用户操作,所以我们在本节结束之前完成此功能也可以避免以后返工。

对于实现限制只有登录用户才可以访问这个功能,很多人第一反应是在控制器的 initialize 方法或在控制( action )方法 (action)逻辑代码之前判断登录用户是否存在。如果不存在就跳转到登录页面,否则继续执行方法。这也是之前 ThinkPHP 项目里经常使用的实现方式。

不过在本项目里,我们打算用 前置中间件 来实现这种访问限制。因为前置中间件是在控制器之前执行,这样消耗的系统资源也少。

另外,我们的后台模块也是使用 前置中间件 限制只有登录管理员可以访问后台。请对照 官方文档application/admin/config/middleware.phproute/admin.php 一起查看。

中间件

首先,我们用命令行工具创建限制登录用户访问的中间件- Auth 。需要注意的是, 创建中件间时不要指定模块名 ,这一点和创建数据模型或控制器不同,即使你指定了模块名生成的中间件也是存储在 `application/http/middleware' 目录。

$ php think make:middleware Auth

新建中间件代码如下:

application/http/middleware/Auth.php

<?php

namespace app\http\middleware;

use app\common\model\User;

class Auth
{
    public function handle($request, \Closure $next)
    {
        if(empty(User::currentUser())){
            if($request->isAjax()){
                $result = [
                    'code' => 0,
                    'msg'  => '请先登录系统',
                    'data' => [],
                    'url'  => url('[page.login]'),
                ];
                return json($result);
            }else{
                return redirect('[page.login]');
            }
        }

        return $next($request);
    }
}

代码解读

  • '$this->error' 和 '$this->redirect' 方法是 think\Conroller 声明的方法,因为我们定义的所有控制器都直接或间接的继承于它,所以在控制器里可以调用这两个方法,而中间件类不是继承于 think\Conroller ,所以在中间件里返回错误信息或跳转页面时不能使用这两个方法。

其次,在前台模块创建中间件配置文件,并完成注册。

index/config/middleware.php

<?php

return [
    'auth' => [
        \app\http\middleware\Auth::class,
    ],
];

控制器

最后,我们在控制器里使用中间件对控制( action )方法添加访问限制。

application/index/controller/User.php

<?php
.
.
.
class User extends Controller
{
    protected $middleware = [
        'auth' => ['except' => ['read']],
    ];

    .
    .
    .
}

代码解读

  • 在控制器里注册中间件时可以使用 exceptonly , 即也就是我们常说的 白名单黑名单 ,在这里我建议大家在控制器里尽量用 except 来注册中间件,这样可以确保我们新添加的控制( action )方法默认都是受中间件保护的。

如果有人看过 route/admin.php 文件的话,可能会好奇为什么我们在前台模块不同相同的方法在声明路由时 使用闭包定义中间件 ,而是在控制器里注册中间件。这样当项目控制器很多时,我们可能需要在每个控制器里重复注册中间件? 其实笔者最初也是想在声明路由时注册中间件,但因为把路由配置修改成以下内容时,中间件并没有起作用才选择在控制器里注册。
对于这是不是笔者所使用的 ThinkPHP 版本中的一个 bug ,笔者没有仔细研究,大家如果对这有兴趣的话可以探索一下。

效果展示

提交代码

下面把代码纳入到版本管理。

$ git add -A
$ git commit '使用中间件实现登录用户访问限制'

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~