简易laravel路由权限开关(附黑名单防刷)

编程

首先还是介绍一下存储吧,mysql,由于数据量不会很多,至于需不需要用到no-sql缓存,就看大家具体项目的抉择了。生成简单的一个迁移文件,充当路由权限表,主要通过路由的别名充当唯一键。

代码 :

<?php

use AppModelsV1SystemAppRouterConfig;

use IlluminateSupportFacadesSchema;

use IlluminateDatabaseSchemaBlueprint;

use IlluminateDatabaseMigrationsMigration;

class CreateAppRouterConfigsTable extends Migration

{

/**

* Run the migrations.

*

* @return void

*/

public function up()

{

Schema::create(AppRouterConfig::TABLE, function (Blueprint $table) {

$table->increments("id");

$table->string("name",50)->unique()->comment("");

$table->string("uri",100)->comment("路由");

$table->string("methods",30)->nullable()->comment("方法");

$table->string("black_ips",100)->nullable()->comment("ip黑名");

$table->string("black_users",200)->nullable()->comment("黑名");

$table->string("black_devices",200)->nullable()->comment("设备黑名");

$table->string("tips_message",200)->nullable()->comment("提示");

$table->tinyInteger("status")->default(AppRouterConfig::STATUS_ABLE)->comment("状态");

$table->timestamps();

});

IlluminateSupportFacadesDB::statement("ALTER TABLE ".AppRouterConfig::TABLE." comment "路由限表"");

}

/**

* Reverse the migrations.

*

* @return void

*/

public function down()

{

Schema::dropIfExists(AppRouterConfig::TABLE);

}

}

表结构确定好之后,我们考虑一下数据填充。

这里也是集成到laravel 的 artisan脚本生成工具之中,每次路由有更新需要用到权限的时候,执行一下脚本即可。

php artisan cron:init-router-access

command脚本入口文件,这个就不具体讲了,不同的项目会有不同的规范。

<?php

namespace AppConsoleCommandsCron;

use AppServicesCardCardService;

use AppServicesCronRouterAccessService;

use IlluminateConsoleCommand;

class InitRouterAccess extends Command

{

protected $service;

protected $signature = "cron:init-router-access";

protected $description = "初始化路由";

public function __construct(RouterAccessService $service)

{

parent::__construct();

$this->service = $service;

}

/**

* @throws Throwable

*/

public function handle()

{

//行的任

$this->service->run();

}

}

其次实现方式我们用常规的中间件形式,主要的处理逻辑在Service文件中,这里有三个主要函数,

<?php

/**

* User: Freeze

* Date: 2020/03/31

* Time: 19:58

*/

namespace AppServicesCron;

use AppModelsV1SystemAppRouterConfig;

use IlluminateSupportFacadesDB;

class RouterAccessService

{

public $message;

/**

* @return mixed

*/

public function getMessage()

{

return $this->message;

}

/**

* @param mixed $message

*/

public function setMessage($message): void

{

$this->message = $message;

}

/**

* 验证路由

* @param $name

* @return bool

*/

public function check( $request, $name)

{

$dbRouter = AppRouterConfig::query()->where("name", $name)->first();

if ($dbRouter && $dbRouter->status == AppRouterConfig::STATUS_DIABLE) {

$this->setMessage($dbRouter->tips_message ?: "该请求服已停用");

return false;

}

if ($dbRouter && $dbRouter->black_ips && in_array($request->ip(), explode(",", $dbRouter->black_ips))) {

$this->setMessage("求拒,IP已被识别为非法操作!");

return false;

}

if ($dbRouter && $dbRouter->black_devices) {

$device_no = $request->header("device_no");

if ($device_no && in_array($device_no, explode(",", $dbRouter->black_devices))) {

$this->setMessage("求拒,账号已被识别为非法操作!");

return false;

}

}

return true;

}

/**

* 根据用录态验证路由

* @param $name

* @return bool

*/

public function checkAuth( $request, $name)

{

$dbRouter = AppRouterConfig::query()->where("name", $name)->first();

if ($dbRouter && $dbRouter->black_users && $request->user() && in_array($request->user()->id, explode(",", $dbRouter->black_users))) {

$this->setMessage("求拒,账号已被识别为非法操作!");

return false;

}

return true;

}

//初始化路由,据表

public function run()

{

try {

DB::transaction(function () {

$routers = app("router")->getRoutes()->getRoutesByName();

foreach ($routers as $name => $router) {

AppRouterConfig::query()->updateOrCreate([

"name" => $name,

], [

"uri" => $router->uri,

"methods" => implode(",", $router->methods)

]);

}

});

} catch (Exception $exception) {

logger("RouteAccess:" . $exception->getMessage());

echo $exception->getMessage();

}

}

}

1. run是每次刷新路由表的数据跑的脚本执行的,基础的sql操作,其中路由别名(name)充当唯一键的作用。

简单的打印个例子

2.check方法就是我们的开关和黑名单过滤功能的体现。

代码也是通俗易懂,status决定该路由的开关,black_ips决定ip黑名单的过滤,black_devices决定设备号的过滤,当然还有black_users针对已登录用户的id的过滤(由于这个用户id的值必须要等到jwt登录态校验处理完之后,才能拿到,故单独开了一个中间件放在jwt后面,做这个black_users的过滤处理),大家可以根据自己的需要补充一下其他维度的黑名单处理。

中间件代码:

全局过滤

<?php

namespace AppHttpMiddlewareApiV1Common;

use AppExceptionsCheckSignException;

use AppExceptionsInvalidRequestException;

use AppServicesActivityGashaponService;

use AppServicesCronRouterAccessService;

use CarbonCarbon;

use Closure;

use IlluminateSupportFacadesRedis;

class RouterAccessMiddleware

{

public $accessService;

public function __construct(RouterAccessService $accessService)

{

$this->accessService = $accessService;

}

/**

* 验证签名中

* @param $request

* @param Closure $next

* @return mixed

* @throws CheckSignException

* @throws InvalidRequestException

*/

public function handle($request, Closure $next)

{

$route_name = $request->route()->getName();

if (!$this->accessService->check($request,$route_name)) throw new InvalidRequestException($this->accessService->getMessage());

return $next($request);

}

}

3. 需要登录态获取用户id过滤

<?php

namespace AppHttpMiddlewareApiV1Common;

use AppExceptionsCheckSignException;

use AppExceptionsInvalidRequestException;

use AppServicesActivityGashaponService;

use AppServicesCronRouterAccessService;

use CarbonCarbon;

use Closure;

use IlluminateSupportFacadesRedis;

class RouterAuthAccessMiddleware

{

public $accessService;

public function __construct(RouterAccessService $accessService)

{

$this->accessService = $accessService;

}

/**

* 验证签名中

* @param $request

* @param Closure $next

* @return mixed

* @throws CheckSignException

* @throws InvalidRequestException

*/

public function handle($request, Closure $next)

{

$route_name = $request->route()->getName();

if (!$this->accessService->checkAuth($request,$route_name)) throw new InvalidRequestException($this->accessService->getMessage());

return $next($request);

}

}

 

到这里,一个简易的路由权限控制已经做好了,希望能帮到大家。

最后附上数据表中的一些数据情况作为说明。

 

 

以上是 简易laravel路由权限开关(附黑名单防刷) 的全部内容, 来源链接: utcz.com/z/514953.html

回到顶部