FrontController с RequestFactory в GWT

Я использую RequestFactory с GWT. Все работает нормально. У меня есть интерфейс RequestContext, который указывает на мои методы DAO.

Теперь я хочу реализовать какую-то проверку безопасности перед вызовом DAO. Первое, что приходит мне в голову, это использовать FrontController и централизовать в нем безопасность, но я не знаю, как реализовать это с помощью RequestFactory. Любая мысль?


person Momo    schedule 26.03.2013    source источник
comment
Какую проверку безопасности вы хотите сделать? Проверка подлинности пользователя?   -  person Sam    schedule 26.03.2013
comment
В основном я хочу проверить, есть ли у пользователя активный сеанс.   -  person Momo    schedule 26.03.2013


Ответы (3)


Вот как я реализовал проверку безопасности:

На стороне сервера я проверяю, что каждый запрос RequestFactory связан с пользователем, который ранее вошел в систему. Для этого файл web.xml (в каталоге war/WEB-INF) должен иметь сопоставление для класса сервлета. Вот запись из файла web.xml:

<servlet>
  <servlet-name>requestFactoryServlet</servlet-name>
  <servlet-class>org.greatlogic.rfexample2.server.RFERequestFactoryServlet</servlet-class>
  <init-param>
    <param-name>symbolMapsDirectory</param-name>
    <param-value>WEB-INF/classes/symbolMaps/</param-value>
  </init-param>
</servlet>
<servlet-mapping>
  <servlet-name>requestFactoryServlet</servlet-name>
  <url-pattern>/gwtRequest</url-pattern>
</servlet-mapping>

Класс RFERequestFactoryServlet содержит следующий код:

public class RFERequestFactoryServlet extends RequestFactoryServlet {

@Override
protected void doPost(final HttpServletRequest request, final HttpServletResponse response)
  throws IOException, ServletException {
  if (!userIsLoggedIn(request)) {
    response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
  }
  else {
    super.doPost(request, response);
  }
}

private boolean userIsLoggedIn(final HttpServletRequest request) {
  boolean result = false;
  HttpSession session = request.getSession();
  if (session != null) {
    User user = (User)session.getAttribute("User");
    result = user != null;
  }
  return result;
}

}

На стороне клиента мне нужно было перехватывать каждый ответ RequestFactory, чтобы проверить наличие ошибки SC_UNAUTHORIZED. Вы должны указать объекту RequestFactory использовать конкретный RequestTransport в вызове RequestFactory#initialize, например так:

MyRequestFactory requestFactory = GWT.create(MyRequestFactory.class);
requestFactory.initialize(eventBus, new RFERequestTransport());

Мой класс RFERequestTransport расширяет класс DefaultRequestTransport:

public class RFERequestTransport extends DefaultRequestTransport {

private final class RFERequestCallback implements RequestCallback {

private RequestCallback _requestCallback;

private RFERequestCallback(final RequestCallback requestCallback) {
  _requestCallback = requestCallback;
}

@Override
public void onError(final Request request, final Throwable exception) {
  _requestCallback.onError(request, exception);
}

@Override
public void onResponseReceived(final Request request, final Response response) {
  if (response.getStatusCode() == Response.SC_UNAUTHORIZED) {
    // the login processing goes here
  }
  else {
    _requestCallback.onResponseReceived(request, response);
  }
}

} // end of the RFERequestCallback class

@Override
protected RequestCallback createRequestCallback(final TransportReceiver receiver) {
  return new RFERequestCallback(super.createRequestCallback(receiver));
}

}

Когда RequestFactory создает обратный вызов запроса, он вызывает мой метод, который создает мою собственную версию RequestCallback. Если пользователь вошел в систему (как определено сервлетом), то он просто выполняет обычную RequestFactory обработку; в противном случае я прохожу процесс входа в систему с пользователем. Часть процесса входа в систему включает в себя связь с сервером для проверки входа в систему ... если вход в систему прошел успешно, я создаю объект на сервере и сохраняю ссылку на него в атрибуте «Пользователь» - затем это проверяется в userIsLoggedIn метод в классе сервлета.

person Andy King    schedule 26.03.2013
comment
Как вы обрабатываете первый запрос на вход? потому что сеанс еще не создан - person Momo; 02.04.2013
comment
@Moh В RFERequestFactoryServlet#userIsLoggedIn я выполняю HttpServletRequest#getSession. JavaDoc для этого метода гласит: возвращает текущий сеанс, связанный с этим запросом, или, если запрос не имеет сеанса, создает его. - person Andy King; 03.04.2013
comment
Я понимаю часть для HttpSession. Но когда пользователь извлекается из сеанса, он может быть нулевым, это было бы нормально, если бы ни один пользователь не вошел в систему. Теперь моя проблема заключается в том, что когда я вызываю метод в DAO, который выполняет вход, вызов будет обработан через RFERequestFactoryServlet#userIsLoggedIn и поскольку в сеансе еще нет пользователя, запрос на вход не будет выполнен, и будет отображаться окно входа в систему. Как разрешить запрос на вход в систему, даже если в сеансе нет пользователя? - person Momo; 03.04.2013
comment
@Moh Вы обеспокоены тем, что в процессе есть цикл ... то есть, когда вы обрабатываете ответ пользователя на запрос входа в систему, он просто вызовет еще один ответ SC_UNAUTHORIZED от сервлета? (кстати, пожалуйста, используйте @ в своих комментариях, чтобы я видел их по электронной почте). - person Andy King; 06.04.2013
comment
@Moh Не знаю, поможет ли это, но в моем коде, реализующем процесс входа в систему, я отправляю имя пользователя и пароль пользователя с помощью GWT RPC, а не с помощью RequestFactory, то есть я не использую DAO для входа в систему. У меня есть пример проекта, который реализует эту схему (хотя в этом примере он не включает действия для неудачных входов в систему)... Я описываю проект в своем блоге, здесь. - person Andy King; 06.04.2013
comment
Да, меня беспокоила проблема цикла... В конце концов я выполнил процесс входа в сервлет отдельно. Спасибо - person Momo; 07.04.2013

Если вы хотите проверить, аутентифицирован ли пользователь, вы можете использовать фильтр сервлета на стороне сервера и пользовательский RequestTransport на стороне клиента. См. архетип guice-rf-activity на странице https://github.com/tbroyer/gwt-maven-archetypes для примера.

Вы также можете проверить на уровне метода, используя собственный ServiceLayerDecorator и реализует метод invoke, вызывая report(), когда пользователь не авторизован/аутентифицирован (и обрабатывает onFailure на стороне клиента). Я реализовал такую ​​штуку, что авторизовал пользователя на основе @RolesAllowed аннотации к методу или классу службы: https://gist.github.com/tbroyer/6091533

person Thomas Broyer    schedule 26.03.2013

Настройте фильтр в файле web.xml, чтобы фильтровать каждый запрос RF для проверки сеанса.

<filter>
  <filter-name>AuthFilter</filter-name>
  <filter-class>my.namespace.AuthFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>AuthFilter</filter-name>
  <url-pattern>/gwtRequest</url-pattern>
</filter-mapping>

Здесь у вас есть пример класса, проверяющий, находится ли в сеансе определенный параметр, который может быть установлен в процессе входа в ваше приложение, это всего лишь пример, вы можете использовать свой собственный механизм.

  public class AuthFilter implements Filter {

    public void doFilter(ServletRequest servletRequest,
        ServletResponse servletResponse, FilterChain filterChain)
        throws IOException, ServletException {

      HttpServletRequest req = (HttpServletRequest) servletRequest;
      HttpServletResponse resp = (HttpServletResponse) servletResponse;

      if (req.getSession().getAttribute("VALID_SESSION") == null) {
        resp.sendError(HttpServletResponse.SC_UNAUTHORIZED);
        return;
      }

      if (null != filterChain) {
        filterChain.doFilter(req, resp);
      }

    }
  }
person Manolo Carrasco Moñino    schedule 26.03.2013