【问题标题】:Allowing only a specific user to view a page只允许特定用户查看页面
【发布时间】:2013-07-26 15:15:28
【问题描述】:

所以我正在构建一个身份验证系统,允许客户查看我们为他们创建的工作。每个客户只有一个帐户。我正在尝试找出一种方法来检查每个页面上是否允许登录的人查看所述内容。

基本上文件结构是这样的:Client/Year/Project/,然后在项目文件夹中有特定类别的文件夹(flash、登录页面等)。在每个文件夹中都有一个 index.php 文件,用于处理显示目录或项目。我需要在每个索引页面上检查登录的用户是否有权查看该页面。

目前,我有几个会话变量:

$_Session['loggedin'] - 只是登录时设置为 true 的布尔值

$_Session['client'] - 这个值是在他们登录时从数据库中获取的。它只是一个客户全名的字符串(它也用于显示目的)。

到目前为止,在每个页面上,我都会检查 login 是否设置为 true,并且我在每个页面上都进行了硬编码:

if(!isset($_SESSION['loggedin']) || $_SESSION['client'] != 'Clientname'){
   unset($_SESSION);
   session_destroy();
   header("Location: http://www.homepage.com");
}

虽然我对这个解决方案不是很满意,因为我正在努力使其尽可能自动化 - 新客户将继续添加,人们应该可以在没有太多大惊小怪的情况下添加客户(所有在这一点上工作正常,除了这个)

我必须检查以确保客户端正确,否则可能会发生以下情况:客户端 A 登录并且已登录会话设置为 true...但是,如果他们导航到客户端 B 的文件夹结构并且它仅检查是否有人登录,他们将能够访问它。

是否有处理此类事情的好习惯?我想实现一些可以在所有用户之间使用的东西,并且每次添加新客户端时都不需要有人进入代码并更改客户端名称字符串。

任何合乎逻辑的帮助都会很棒!

【问题讨论】:

    标签: php security session authorization


    【解决方案1】:

    您可以将客户端数据存储在公共可见目录结构之外的目录中,并使用 mod_rewrite(如果您使用 Apache)将所有请求重定向到将启动 FrontController 的单个 index.php。该控制器根据请求字符串和会话 cookie 初始化身份验证和授权过程。

    如果您的文档根目录是/some/folder/public_html,则客户端数据将存储在/some/folder/data/Client/... 中,PHP 将发布特定文件夹的内容。您还可以将项目及其数据库密钥存储为文件夹。那么你不需要Client/Year/Project/的目录结构而是some/folder/data/{project_key}/...。有了这个解决方案,目录导航就更简单了。

    这里是这个想法的一些简短摘录:

    .htaccess

    使用 mod_rewrite 重定向请求

    RewriteEngine On
    RewriteBase /path/to/client/data
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ index.php?request=$1 [QSA, L]
    

    index.php

    此脚本将初始化数据库连接、控制器和会话并处理请求。

    // initialization of database connection    
    $connection = ...
    
    // controller initialziation
    $controller = new FrontController($connection, ...);
    
    // you could encapsulate the session in its own class to make
    // easy requests to the session.
    $session = new Session(...);
    
    // select the requested resource by its path
    $resource = $controller->selectResourceByPath($_GET['request']);
    
    // resouce was not found
    if (!$resource) {
        $controller->showNotFound($_GET['request']);
        exit(0);
    }
    
    // validate if the session is started. If not, redirect to the login page.
    if (!$session->isStarted()) {
      $controller->redirect('login');
      exit(0);
    }
    
    $user = $session->getUser();
    
    // user is not logged in
    if (!$user) {
       $controller->redirect('login');
       exit(0);
    }
    
    // this is a very simple solution. You could build up separate
    // authentication/authorization layer.
    if ($resource->hasAccess($user))
      $controller->showResource($resource);
    else
      $controller->showAccessDenied($user, $resource);
    

    通常您会使用路由器、防火墙类和 ACL 来保护实体的访问。此外,请求处理将在路由器->解析器->控制器链中构建。这只是想法的摘录。

    【讨论】:

      【解决方案2】:

      您似乎已经有一个身份验证系统,因为您正在设置 $current_client = $_SESSION['client']。

      另外你说你在每个客户端目录下都有一个 index.php 文件。

      您的文件夹在根目录下与客户端一起布局。我假设路径是:

      /root/path/to/files/$$CLIENT$$/....

      您需要做的就是将当前路径/到/客户端与 $current_client 进行比较。

      // returns true if $str begins with $sub
      function beginsWith( $str, $sub ) {
          return ( substr( $str, 0, strlen( $sub ) ) == $sub );
      }
      
      $authorized = beginsWith(__FILE__, '/root/path/to/files/' . $current_client) ;
      

      将其添加到您的授权中,而不是对客户端名称进行硬编码。

      if(!isset($_SESSION['loggedin']) || !$authorized){
         unset($_SESSION);
         session_destroy();
         header("Location: http://www.homepage.com");
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-06-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-05-31
        • 1970-01-01
        相关资源
        最近更新 更多