0

ユーザーが会社/組織のサブドメインを作成できるようにするCakePHPを使用してWebアプリを構築しています。例えばcompany-name.domain.com

これを実現するために、次のような Users テーブルと Subsites テーブルがあります。

ユーザー: ID、ユーザー名、電子メール、パスワード、subsite_id サブサイト: ID、名前、ドメイン

ご覧のとおり、ユーザーはサブサイトにリンクされており、サブサイトはこの関係を通じて多くのユーザーを持つことができますが、ユーザーは 1 つのサブサイトにしか所属できません。

AppController で以下を使用して、サブドメインが有効かどうかを確認します。

function checkSubdomain()
{
    if ($_SERVER['HTTP_HOST'] != 'domain.com')
    {
        $domain_parts = explode('.',$_SERVER['HTTP_HOST']);

        if (count($domain_parts) != 3) exit('Invalid url');

        $subdomain = $domain_parts[0];

        $this->loadModel('Subsite');

        $subsites = $this->Subsite->find('all', array('conditions'=>array('domain'=>$subdomain)));

        if(empty($subsites))
        {
            exit('Subsite not found');
        }
    }
}

function beforeFilter()
{
    $this->checkSubdomain();
}

これは基本的に、サブドメインが見つからない場合にエラーが発生することを示しており、これは正常に機能します! 私が抱えている問題は、ホーム、アバウト、価格設定、サインアップフォームなどの特定のページに、明らかな理由でサブドメインからアクセスできないようにしたいということです.

これを行う最良の方法は何ですか?サブドメインかどうか、すべてのコントローラーをチェックインする必要はありませんか?

getballpark.com などの他のアプリでは、サインアップ プロセスにサブドメインが使用されていることに気付きました。特定のサブドメインが特定のページを持つことを許可する特別な方法ですか?

ありがとう

サブドメインが使用されている場合に特定のコントローラーへのアクセスをブロックする、以下の回答に基づく追加の要件:

もう 1 つの問題は、HomeController を使用して、ユーザーがログインしている場合にアプリのスプラッシュ プロモーション ページまたはダッシュボードを表示することです。サブドメイン。または、サム機能を実現するための完全に優れたソリューションです。

サインアップ (これは私の UsersController にあります) を保護するために、ログインとパスワードを忘れた方法もブロックします。Cake の慣習を破ったり、メソッドを個々のコントローラーに移動したりすることなく、これを回避するにはどうすればよいですか? 乾杯

4

2 に答える 2

1

禁止されているコントローラーのリストを作成し、現在のリクエストがサブドメインからのものである場合に備えて、アプリ コントローラーbeforeFilterハンドラーでそれをチェックすることをお勧めします。

protected $_forbiddenSubdomainControllers = array
(
    'about',
    'home',
    'pricing',
    'signup'
);

public function beforeFilter()
{
    parent::beforeFilter();

    if($this->checkSubdomain() &&
       in_array($this->request->params['controller'], $this->_forbiddenSubdomainControllers))
    {
        throw new ForbiddenException('This URL is inaccessible');
    }

}

public function checkSubdomain()
{
    if ($_SERVER['HTTP_HOST'] != 'domain.com')
    {
        $domain_parts = explode('.',$_SERVER['HTTP_HOST']);

        if (count($domain_parts) != 3) exit('Invalid url');

        $subdomain = $domain_parts[0];

        $this->loadModel('Subsite');

        $subsites = $this->Subsite->find('all', array('conditions'=>array('domain'=>$subdomain)));

        if(empty($subsites))
        {
            throw new NotFoundException('Subsite not found');
        }

        return true;
    }

    return false;
}

メソッドを変更して、リクエストが(有効な)サブドメインから送信されたかどうかに応じcheckSubdomainて返されるように変更したことに注意してください。また、呼び出しをエラーをスローするように変更しました。これは、CakePHP でそのような状況を処理するために推奨される方法です.truefalseexit

特定のサブドメインがこれらの「特別な」コントローラーの一部を使用できるようにする場合は、許可されたコントローラーをデータベースに保存し、それらをモデルに関連付けることをお勧めしSubsiteます。その後、これらの名前をチェックに含めることができます。


編集 (05.11.2012)

サブドメインから要求された場合にのみ特定のコントロールの認証を要求することは、たとえば を使用して実現できAuthComponent::allowます。HomeコントローラーのコールバックではbeforeFilter、サブドメインを確認してから、認証されていないアクセスを適切に許可/拒否できます。たとえば、リクエストがサブドメインからのものではない場合にすべてのアクションを許可します。

public function beforeFilter()
{
    parent::beforeFilter();

    if(!$this->checkSubdomain())
    {
        $this->Auth->allow('*');
    }
}

特定のアクションへのアクセスを制限するという新しい要件を念頭に置いて、アプリケーションの複雑さによっては、アクセスの制限/許可がACLの仕事になる可能性があると思います。

代わりに「手動で」行うと、最初の例は次のようにアクションで拡張できます。

protected $_denyAccessMap = array
(
    'about',
    'home',
    'pricing',
    'users' => array
    (
        'signup'
    )
);

public function beforeFilter()
{
    parent::beforeFilter();

    if($this->checkSubdomain())
    {
        $controller = $this->request->params['controller'];
        $action = $this->request->params['action'];

        if(in_array($controller, $this->_denyAccessMap) ||
          (array_key_exists($controller, $this->_denyAccessMap) && in_array($action, $this->_denyAccessMap[$controller])))
        {
            throw new ForbiddenException('This URL is inaccessible');
        }
    }
}

aboutこれにより、 controller 、homeand pricing、およびuserscontrollersignupアクションへのアクセスが拒否されます。

すでに述べたように、これは ACL を使用して行うこともできます。また、特定のサブドメインにより多くのアクセスを許可する必要があると述べたので、これはより良いオプションである可能性があり、アクセス制限を動的に制御できるようになります。シンプルな ACL 制御アプリケーションのチュートリアルを見てください。これは簡単に使用できます。Groupモデルを自分のSubsiteモデルに置き換えるだけで済みます。

そうすれば、特定のサブサイト、つまりそのサブサイトに関連付けられたユーザーに特定のアクションへのアクセスを許可できます。たとえば、コントローラーメソッドを除くすべてのコントローラーへSubsiteのアクセスを許可します。id 1Userssubscribe

$this->Subsite->id = 1;

$this->Acl->allow($this->Subsite, 'controllers');
$this->Acl->deny($this->Subsite, 'controllers/User/subscribe');

またはその逆で、コントローラーへのアクセスをブロックし、特定のおよびアクションUsersを期待します。loginpasswordRecovery

$this->Acl->allow($this->Subsite, 'controllers');
$this->Acl->deny($this->Subsite, 'controllers/User');
$this->Acl->allow($this->Subsite, 'controllers/User/login');
$this->Acl->allow($this->Subsite, 'controllers/User/passwordRecovery');

アクセスが許可されているかどうかの確認は、たとえばアプリ コントローラーのbeforeFilterコールバックで行うことができます。

public function beforeFilter()
{
    parent::beforeFilter();

    $subsite = $this->checkSubdomain();
    if(!empty($subsite))
    {
        $aco = 'controllers/' . $this->name . '/' . $this->request->params['action'];
        if($this->Acl->check($subsite, $aco))
        {
            throw new ForbiddenException('This URL is inaccessible');
        }
    }
}

public function checkSubdomain()
{
    if ($_SERVER['HTTP_HOST'] != 'domain.com')
    {
        $domain_parts = explode('.',$_SERVER['HTTP_HOST']);

        if (count($domain_parts) != 3) exit('Invalid url');

        $subdomain = $domain_parts[0];

        $this->loadModel('Subsite');

        $subsite = $this->Subsite->find('first', array('conditions'=>array('domain'=>$subdomain)));

        if(empty($subsite))
        {
            throw new NotFoundException('Subsite not found');
        }

        return $subsite;
    }

    return false;
}

結果を返すように、またはACL チェックに簡単に使用できるようにcheckSubdomainメソッドを変更したことに注意してください。findfalse

于 2012-11-03T16:52:24.463 に答える
0

主な質問と回答に加えて、開発環境も考慮します...数日前に同様の問題があったので、それに取り組みました。

AppController の内部:

function checkAccess() {
    if (count($domain_parts) != 3 &&
       (count($domain_parts) == 2 && $domain_parts[1] != 'localhost:8080')) {
        throw new NotFoundException();
    }
}

内部 checkSubdomain() メソッド:

checkSubdomain() {

    [...]

    $this->checkAccess();

    [...]

}

localhost でサブドメインの機能をテストしていたので、xxx.localhost と yyy.localhost を使用して、展開する前にすべてが正常であることを確認できました。

于 2014-08-26T22:24:34.373 に答える