摘要
我有一些复杂的数据库结构,我想只向授权成员提供数据 - 他们的角色也取决于存储在数据库中的数据。它一直在工作,但现在我想扩展服务,它变得非常复杂。必须有一种优雅的方式。
注意:我没有使用ASP.NET,所以请不要建议那些与之紧密相关的补救措施,尽管我对有关授权过程建模的想法持开放态度。
背景
好吧,我之前也曾问过这个问题,但令我惊讶的是,它没有收到任何好的回应,所以我在这里用不同的词再次发布。我正在开发一个Web应用程序,并且在如何以优雅的方式为授权过程建模方面存在问题。
假设我有一个提供以下服务的应用程序。有“项目”/工作区,您可以在其中发布内容并对这些帖子发表评论。被视为“开放”的项目也可以“跟随” - 因此内容可供追随者访问。为了使这种情况更接近我的实际服务,项目“成员”可以决定关注者可以访问的内容。这可能(或可能不是!)看起来很复杂,但实际的应用程序更复杂。我所做的是在sql查询本身内填写过滤代码。这是一个代码示例:
public function getProjectById($id) {
$auth = new Auth();
$userid = $auth->getCurrentUserId();
$sql = "
SELECT P.id, P.userId, P.name, P.description,
P.creationTime, P.startTime, P.endTime, P.isOpen
FROM projects P
INNER JOIN project_members PM
ON PM.projectid = P.id
AND P.id = '{id}'
AND (PM.userId = '{userid}' OR P.isOpen = 1)
";
return $this->result($sql, array( "userid" => $userid, "id" => $id ));
}
这看起来很糟糕,因为我还必须将这些数据提供给项目关注者(此处未显示)。并且评论和帖子的复杂性也在增加 - 处理代码。现在,有没有更好的方法来做到这一点 - 必须有。我应该将授权逻辑分离到其他类吗?或者/我应该在数据库中使用“视图”(完全没必要,但我还是想指出它们不是MVC视图)?或者还有一种更好,更笨拙的方法来解决这个问题吗?
欢迎所有建议 - 即使是那些旨在改变数据库结构的建议 - 尽管我想知道为什么要这样做。
提前致谢!
答案 0 :(得分:1)
我认为你在视频的正确轨道上,但由于每次调用都需要传递用户ID,听起来你真正需要的是表值函数。我最熟悉Microsoft SQL,它看起来像这样:
SELECT P.*
FROM Projects AS P
INNER JOIN dbo.AuthProjects(@UserID) AS AP ON P.ProjectID = AP.ProjectID
请注意,TVF会逐字地返回一个表,您将加入该表以查看哪些项目可用。 TVF定义可能如下所示:
CREATE FUNCTION dbo.AuthProjects(@UserID INT)
RETURNS @Results TABLE (ProjectID INT NOT NULL, WriteAccess BIT NOT NULL)
AS BEGIN
INSERT INTO @Results (ProjectID, WriteAccess)
SELECT
ProjectID, WriteAccess
FROM
Authorizations
WHERE
UserID = @UserID
-- Additional logic for more ways a project may be authorized
RETURN
END