我正在使用Laravel(Lumen)构建REST API.我们的想法是,这个API为多个食品订购网站提供了后端.它们共享相同的后端逻辑(模型,控制器等).这样每个网站只需要它自己的前端应用程序,我打算为此使用Angular.每个网站都有自己的数据(产品,页面等),必须存储在不同的数据库中.
config/databases.php
为了测试目的,我已经定义了多个连接.现在我可以在查询相应的数据库之前动态设置连接,如下所示:
class ProductController extends Controller { /** * Display a listing of the resource. * * @return Response */ public function index() { $products = new Product; $products->setConnection('customer_two'); // <-- $products = $products->get(); return response()->json($products); } }
例如,可以使用缓存来完成相同的操作.
让API知道哪个客户的网站提出请求的最佳方法是什么?我需要指向正确的数据库.此外,这种方法是否会在性能方面造成任何问题?
我将使用双管齐下的方法来解决这个问题,我会使用第一个没有第二个.
第一个将基于您使用api请求的路由.例如,您可以使用前缀来定义路线/api/{site}
.这样,所有api端点都将基于请求的站点变量.如/api/site1/login
将使用的数据库site1
,并/api/site2/login
会使用数据库site2
.
第二部分是使用JWT进行身份验证,如上所述,并且在每个请求中使用中间件来检查经过身份验证的用户是否实际上是该特定站点的用户的一部分.这仅对经过身份验证的路由非常有用,但仍然会使您的未经身份验证的路由被滥用,但是如果您的网站上有合法用户并且您的网站正在从api请求数据,那么您应该site
返回正确的数据并且任何恶意访问只会获取公共数据.
可能还有第三种选择.使用JWT,您可以创建自定义声明.这些自定义声明可用于存储正在使用的站点以及要访问的数据库.我自己没有这样做,但一直在考虑做类似的事情来验证客户端对我的apis以及基于用户的身份验证.这意味着每个端点至少应进行客户端身份验证,其他端点也将进行用户身份验证以及客户端身份验证.
使用中间件在运行时轻松更改数据库连接.
中间件:app/Http/Middleware/DatabaseConnectionChooser.php
getRoutes()->match($request); $connection = $route->getParameter('connection'); app('db')->setDefaultConnection($connection); return $next($request); } }
将此中间件添加到app/Http/Kernel.php类到$ middleware属性.
protected $middleware = [ ... \App\Http\Middleware\DatabaseConnectionChooser::class, ];
创建路由以指定站点,即数据库连接.
应用程序/ HTTP/routes.php文件
app('router')->get('/{connection}/', function () { return app('db')->getDefaultConnection(); });
在配置中设置数据库连接.
配置/ database.php中
'connections' => [ ... 'site1' => [ 'driver' => 'mysql', 'host' => env('DB_HOST', 'localhost'), 'database' => env('DB_DATABASE', 'forge1'), 'username' => env('DB_USERNAME', 'forge1'), 'password' => env('DB_PASSWORD', ''), 'charset' => 'utf8', 'collation' => 'utf8_unicode_ci', 'prefix' => '', 'strict' => false, ], 'site2' => [ 'driver' => 'mysql', 'host' => env('DB_HOST', 'localhost'), 'database' => env('DB_DATABASE', 'forge2'), 'username' => env('DB_USERNAME', 'forge2'), 'password' => env('DB_PASSWORD', ''), 'charset' => 'utf8', 'collation' => 'utf8_unicode_ci', 'prefix' => '', 'strict' => false, ], ... ]