403错误后如何将匿名用户重定向到登录表单?


13

如果匿名用户遇到403错误,我想将其重定向到登录表单。

我已经创建了事件订阅者,这是我的代码,但是最后在当前页面上循环了。

/**
   * Redirect anonymous user to login page if he encounters 404 or 403
   * response.
   *
   * @param \Symfony\Component\HttpKernel\Event\GetResponseEvent $response
   *   The created response object that will be returned.
   * @param string $event
   *   The string representation of the event.
   * @param \Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher $event_dispatcher
   *   Event dispatcher that lazily loads listeners and subscribers from the dependency injection
   *   container.
   */
  public function checkLoginNeeded(GetResponseEvent $response, $event, ContainerAwareEventDispatcher $event_dispatcher) {
    $routeMatch = RouteMatch::createFromRequest($response->getRequest());
    $route_name = $routeMatch->getRouteName();
    $is_anonymous = \Drupal::currentUser()->isAnonymous();
    $is_not_login = $route_name != 'user.login';

    if ($is_anonymous && $route_name == 'system.403' && $is_not_login) {
      $query = $response->getRequest()->query->all();
//      $query['destination'] = $routeMatch->getRouteObject()->getPath();
      $query['destination'] = \Drupal::url('<current>');
      $login_uri = \Drupal::url('user.login', [], ['query' => $query]);
      $returnResponse = new RedirectResponse($login_uri, Response::HTTP_FOUND);
      $response->setResponse($returnResponse);
    }
  }

我认为这与以下事实有关:响应已经包含目的地(当前uri),并且system.404和system.403具有较高的优先级,导致我无法覆盖此优先级。


您可以添加整个类而不是仅添加方法吗?
googletorp

只有$ events [KernelEvents :: REQUEST] ='checkLoginNeeded'; 在getSubscribedEvents()方法中。

Answers:


14

我已经看到,如何以编程方式完成此问题从未得到解答。将代码放在Exception Subscriber中时,该代码实际上可以正常工作:

/src/EventSubscriber/RedirectOn403Subscriber.php:

<?php

namespace Drupal\mymodule\EventSubscriber;

use Drupal\Core\EventSubscriber\HttpExceptionSubscriberBase;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;

class RedirectOn403Subscriber extends HttpExceptionSubscriberBase {

  protected $currentUser;

  public function __construct(AccountInterface $current_user) {
    $this->currentUser = $current_user;
  }

  protected function getHandledFormats() {
    return ['html'];
  }

  public function on403(GetResponseForExceptionEvent $event) {
    $request = $event->getRequest();
    $is_anonymous = $this->currentUser->isAnonymous();
    $route_name = $request->attributes->get('_route');
    $is_not_login = $route_name != 'user.login';
    if ($is_anonymous && $is_not_login) {
      $query = $request->query->all();
      $query['destination'] = Url::fromRoute('<current>')->toString();
      $login_uri = Url::fromRoute('user.login', [], ['query' => $query])->toString();
      $returnResponse = new RedirectResponse($login_uri);
      $event->setResponse($returnResponse);
    }
  }

}

mymodule.services.yml:

services:
  mymodule.exception403.subscriber:
    class: Drupal\mymodule\EventSubscriber\RedirectOn403Subscriber
    tags:
      - { name: event_subscriber }
    arguments: ['@current_user']

4
在相关模块(包括规则)发布稳定之前,此方法可能是最好的答案。我必须在$ query ['destination'] = Url :: fromRoute('<current>')中添加-> toString()才能使其正常工作
Colin Shipton

2
这个答案值得出现!
pbonnefoi

13

最简单的方法是浏览到/admin/config/system/site-information并填写读取现场Default 403 (access denied) pageuser/login


7
这是一个很好的解决方案,但是没有考虑到我在描述中提到的用户可能已经登录的事实。

9

仅查看此问题的标题(= 如何将用户从403重定向到登录表单?),有2个选项可以这样做,而无需涉及任何自定义代码,如下所述。

选项1:使用CustomError模块

CustomError模块允许网站管理员创建HTTP自定义错误页的状态代码403(拒绝访问)和404(未找到),无需为他们每个人创建节点。有关其功能的更多详细信息(来自其项目页面):

  • 可配置的页面标题和描述。
  • 没有普通节点那样的作者和日期/时间标题。
  • 可以将任何HTML格式的文本放在页面正文中。
  • 错误页面是可修复的。
  • 未登录并尝试访问需要登录的区域的用户将被重定向到他们登录后尝试访问的页面。
  • 允许404的自定义重定向。

您可能会对以下部分最感兴趣:“ 未登录并尝试访问需要登录的区域的用户将被重定向到他们登录后尝试访问的页面。 ”。

对于D8 ,该模块也有一个8.x-1.x-dev版本,有关它的更多详细信息,请参见发行号2219227

选项2:使用“规则”模块

假定“默认403”页面的路径设置为no_access(通过admin)。然后使用“ 规则”模块创建一个规则,作为事件类似“访问节点之后no_access”。这样整个规则看起来像这样:

  • 事件:访问节点后no_access
  • 条件:

    1. 用户具有的角色 -Parameter: User: [site:current-user], Roles: anonymous user
    2. 非文字比较 -Parameter: Text: [site:current-page:url], Matching text: user/login
  • 操作: 页面重定向 -Parameter: URL: user/login

如果您想这样做,您甚至可以添加另一个Action,以在Drupal消息区域中显示一些(信息性)消息,例如“您试图访问需要登录的页面...”。

是的,它可能需要您启用额外的贡献模块(Rules)。但是,正如它的日益流行所表明的那样,该模块可能已在几乎所有站点中启用(类似于Views模块),因为该模块有数十个用例。

对于D8 ,该模块也有一个8.x-3.x-alfa1版本,有关D8版本的更多详细信息,请参见发行号2574691,其中包括指向“ 规则8.x路线图 ”的链接。

如果上述方法无济于事,那么您可能想要检查是否可以通过类似于问题“ 如何指定 ”的答案来防止/解释循环的原因(或问题中的“高优先级”)规则事件,例如“内容将要被查看”? ”。


4

我想解决您的问题的方法很简单。您可以轻松地为此创建一个自定义页面404403然后在该页面内将匿名用户重定向到该/user页面。

您可以使用此代码

function YOURTHEME_preprocess_page(&$vars) {
   $header = drupal_get_http_header('status'); 
   if ($header == '404 Not Found') {     
       $vars['theme_hook_suggestions'][] = 'page__404';
   }
}

每当404出现时,您page--404.tpl.php都会被使用。在此页面中使用此代码

if(user_is_logged_in() == false){
       /// You can do anything here.
}

Drupal中How to make custom 403 and 404页面介绍了另一种为403和创建页面的方法404


5
嗨,老兄,您应该检查标签和代码。这家伙显然是使用Drupal的8
alexej_d

1
嗨,我给了他算法,他可以轻松地将其更改为8格式
M ama D

3

最简单的方法是使用“ 将403重定向到用户登录”模块(D8中存在其开发版本)。这是有关它的报价(从其项目页面):

使用以下可选消息将HTTP 403错误页面重定向到Drupal / user / login页面:

“访问被拒绝!您必须登录才能查看此页面。”

同样,所需的页面将附加到url查询字符串中,以便成功登录后,将用户直接带到他们最初尝试去的地方。


1
为什么这个答案不好?
米洛什Kroulík

@ milos.kroulik我猜是因为问题是关于Drupal 8的,但是该模块是针对76
M ama D

1
该模块没有开发中的Drupal 8版本
Colin Shipton 2015年

1
可以肯定的是,降低投票率是因为答案是“仅链接”答案(降低投票率甚至删除答案的典型原因……)。这样的答案通常还会显示在“低质量答案”复查队列中。...现在,请参阅我对该答案的编辑版本,以获取增强的版本(不再有被视为仅链接答案的风险)。
Pierre.Vriens,2015年

如果用户已经登录这个答案不考虑或者如果网站使用fast404和403

0

(1)创建一个别名为“ /my403.html”的页面节点

(2)转到/ admin / config / system / site-information并将“ /my403.html”设置为403-Errorpage

(3)转到/ admin / structure / block并将“用户登录”块(“表单”)添加到主要内容区域。将块的外观限制为页面“ my403.html”和角色“ guest”。

而已。

如果需要更多控制,请为403页面创建一个控制器,然后手动添加UserLoginForm。

此致,Rainer

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.