Аутентификация через диалоговое окно входа в Scout (RAP)

Я хотел бы иметь аутентификацию, основанную на концепции безопасности скаутов по умолчанию, найденной в https://wiki.eclipse.org/Scout/Concepts/Security.

Что я сделал:

Я добавил BasicSecurityFilter к серверам plugin.xml:

<extension name="" point="org.eclipse.scout.rt.server.commons.filters">
      <filter aliases="/ /process /remotefiles /updatesite" class="org.eclipse.scout.http.servletfilter.security.BasicSecurityFilter" ranking="30"></filter>
</extension>

И активировал его в config.ini:

org.eclipse.scout.http.servletfilter.security.BasicSecurityFilter#active=true
org.eclipse.scout.http.servletfilter.security.BasicSecurityFilter#realm=Development
org.eclipse.scout.http.servletfilter.security.BasicSecurityFilter#users=TEST\=admin

На стороне клиента я добавил InternalNetAuthenticator в plugin.xml:

<extension point="org.eclipse.core.net.authenticator">
    <authenticator class="org.eclipse.scout.rt.ui.rap.login.internal.InternalNetAuthenticator"</authenticator>
</extension>

И установите его как аутентификатор по умолчанию в клиенте Activator:

@Override
public void start(BundleContext context) throws Exception {
  super.start(context);
  plugin = this;
  InternalNetAuthenticator authenticator = new InternalNetAuthenticator();
  InternalNetAuthenticator.setDefault(authenticator);
}

Что просходит:

  • BasicSecurityFilter.negotiate() вызывается при доступе к приложению (первая загрузка, например, http://localhost:8015/web)
  • InternalNetAuthenticator.getPasswordAuthentication() называется, когда переговоры в BasicSecurityFilter происходит сбой (это когда пользователь и пароль не найдены в заголовке HTTP или пользователь и пароль недействительны).
    • Открытие диалога на уровне RAP (см. InternalNetAuthenticator.showModalDialog(status, display)) невозможно, потому что Display.getDefault() или Display.getCurrent() всегда возвращает null,
      • Это связано с тем, что все операции пользовательского интерфейса (например, открытие диалогового окна) ДОЛЖНЫ появляться в UIThread (см. Java-doc в Display.getDefault()).
      • InternalNetAuthenticator создается в UIThread (см. Activator.start()), но это не называется в UIThread! Зачем???
    • Возвращение PasswordAuthentication Объект предоставляет учетные данные в заголовке HTTP для следующего BasicSecurityFilter.negotiate() вызов.
  • BasicSecurityFilter.negotiate() вызывается снова с заданными учетными данными.

Что не получается:

Так из-за того, что InternalNetAuthenticator.showModalDialog(status, display) не вызывается в потоке пользовательского интерфейса, это вызывает NullPointerException:

java.lang.NullPointerException
    at org.eclipse.scout.rt.ui.rap.login.internal.InternalNetAuthenticator.showModalDialog(InternalNetAuthenticator.java:102)
...

Что я уже рассмотрел:

  • Основная информация
    • https://wiki.eclipse.org/Scout/HowTo/3.9/Extending_the_login_dialog
    • https://wiki.eclipse.org/Scout/Concepts/Securit
  • Проблема UI-потока
    • https://www.eclipse.org/forums/index.php/t/440290/
    • https://www.eclipse.org/rap/developers-guide/devguide.php?topic=threads.html
    • Я уже пытался сохранить UI-поток при создании экземпляра Authenticator в Activator.start() метод путем создания собственного Authenticator и добавления параметра в конструктор, например:
      • MyAuthenticator my_authenticator = new MyAuthenticator(Thread.currentThread());
      • Но это вызывает IllegelStateException или что-то типа того. Таким образом, UI-поток не доступен на этом пути.
    • С использованием BasicSecurityFilter на уровне RAP (в plugin.xml пакета RAP) позволяет использовать системный диалог входа по умолчанию.
      • Но я хотел бы иметь собственный SecurityFilter, который имеет доступ к другим системам на стороне сервера, поэтому он должен отображаться на стороне сервера, а SecurityFilter на стороне RAP/client не подходит!

Резюме

Все, что я могу видеть, это то, что решение проблемы с UI-потоком будет предпочтительным способом продвинуть эту проблему вперед.

Я также приму альтернативные решения для создания собственного диалогового окна входа в мою среду eclipse-scout-RAP.

1 ответ

Описание проблемы:

Если я правильно понял ваш вариант использования, вы бы хотели ввести что-то вроде аутентификации на основе форм. Я предполагаю, что это то, чего вы хотели достичь, отображая диалог входа в RAP UI-Thread.

Предложение по решению:

Были предприняты некоторые шаги по внедрению аутентификации на основе форм в демонстрационном приложении BahBah Scout, которое можно найти в [1]. Обратите внимание, что этот пример основан на более старой версии Scout (3.10). В следующем объяснении будет упомянуто выполнение в [1]:

В [1] подход состоял в том, чтобы использовать средство веб-контейнера Tomcat для достижения аутентификации на основе форм. Пример страницы входа в HTML [2] можно найти в комплекте RAP UI в папке web-ресурсов. Поэтому в файле plugin.xml [3] приложения RAP фильтр сервлетов BasicForwardSecurityFilter был удален. Убедитесь, что веб-ресурсы доступны, например, в / res.

<extension point="org.eclipse.equinox.http.registry.resources">
  <resource alias="/res" base-name="/web-resources"/>
</extension>

В файле приложения RAP web.xml были сделаны следующие записи.

<!-- Activate form-based authentication -->
<login-config>
  <auth-method>FORM</auth-method>
  <realm-name>BahBahJAASLogin</realm-name>
  <form-login-config>
    <form-login-page>/res/index.html</form-login-page>
    <form-error-page>/res/index.html</form-error-page>
  </form-login-config>
</login-config>

<!-- Define security role to access the application -->
<security-role>
  <role-name>BahBahRolePrincipal</role-name>
</security-role>

<!-- static resources under /res/* should be accessible without requiring authentication --> 
<security-constraint>
  <web-resource-collection>
    <web-resource-name>All Access</web-resource-name>
    <url-pattern>/res/*</url-pattern>
    <http-method>DELETE</http-method>
    <http-method>PUT</http-method>
    <http-method>HEAD</http-method>
    <http-method>OPTIONS</http-method>
    <http-method>TRACE</http-method>
    <http-method>GET</http-method>
    <http-method>POST</http-method>
  </web-resource-collection>
  <user-data-constraint>
    <transport-guarantee>NONE</transport-guarantee>
  </user-data-constraint>
</security-constraint>

<!-- Protect all other URLs of the application -->
<security-constraint>
  <web-resource-collection>
    <web-resource-name>Protected Resources</web-resource-name
    <url-pattern>/web/*</url-pattern>
    <url-pattern>/tablet/*</url-pattern>
    <url-pattern>/mobile/*</url-pattern>
    <http-method>GET</http-method>
    <http-method>POST</http-method>
  </web-resource-collection>
  <auth-constraint>
    <role-name>BahBahRolePrincipal</role-name>
  </auth-constraint>
  <user-data-constraint>
    <transport-guarantee>NONE</transport-guarantee>
  </user-data-constraint>
</security-constraint>

<!-- Define security filter and mapping --> 
<filter>
  <filter-name>BahbahSecurityFilter</filter-name>
  <filter-class>com.bsiag.securityfilter.BahbahSecurityFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>BahbahSecurityFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

BahbahSecurityFilter гарантирует, что только проверенные участники могут получить доступ к защищенным ресурсам на сервере пользовательского интерфейса. В методе doFilter проверка выполняется путем вызова метода, подобного следующему:

// Taken from org.eclipse.scout.rt.server.commons.authentication.ServletFilterHelper#isRunningWithValidSubject(HttpServletRequest) see [4]
public boolean isRunningWithValidSubject(HttpServletRequest req) {
  String username = req.getRemoteUser();
  if (username == null || username.isEmpty()) {
    return false;
  }

  Subject subject = Subject.getSubject(AccessController.getContext());
  if (subject == null || subject.getPrincipals().isEmpty()) {
    return false;
  }

  for (Principal principal : subject.getPrincipals()) {
    if (username.equalsIgnoreCase(principal.getName())) {
      return true;
    }
  }
  return false;
}

В BahBahChat Realm [5] и модуль входа в систему настроены для аутентификации пользователей. В частности, определены UserPrincipal и RolePrincipal, а также создан класс LoginModule.

В файле contextcat.xml Tomcat настроена область.

<Realm className="org.apache.catalina.realm.JAASRealm"
       appName="BahBahJAASLogin"
       userClassNames="com.bsiag.securityfilter.BahBahUserPrincipal"
       roleClassNames="com.bsiag.securityfilter.BahBahRolePrincipal"/>

Наконец, файл jaas.config определен:

BahBahJAASLogin  {
  com.bsiag.securityfilter.BahBahJAASLoginModule required debug=true;
};

BahBahJAASLoginModule реализует для фактического процесса аутентификации. Хороший пример настройки аутентификации JAAS в Tomcat можно найти по адресу [6].

Пожалуйста, ознакомьтесь с сообщением на форуме Eclipse Scout [7], в котором кратко изложены необходимые шаги.

Другие вопросы по тегам