1

我想根据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

在客户端,我添加InternalNetAuthenticatorplugin.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 标头中找不到用户和密码,或者用户和密码无效)。
    • InternalNetAuthenticator.showModalDialog(status, display)不可能在 RAP 级别打开对话框(请参阅参考资料),因为 Display.getDefault() 或 Display.getCurrent() 总是返回null
      • 这是因为所有 UI 操作(例如打开对话框)都必须出现在 UIThread 中(参见参考资料中的 java-doc Display.getDefault())。
      • InternalNetAuthenticator是在 UIThread中实例化的(请参阅 参考资料Activator.start()),但它不在UIThread 中调用为什么???
    • 返回一个PasswordAuthentication对象将 HTTP 标头中的凭据提供给下一次BasicSecurityFilter.negotiate()调用。
  • BasicSecurityFilter.negotiate()使用给定的凭据再次调用。

什么失败:

因此,由于InternalNetAuthenticator.showModalDialog(status, display)没有在 UI 线程中调用,它会导致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
    • Activator.start()在方法中实例化 Authenticator 时,我已经尝试通过创建自己的 Authenticator 并向构造函数添加参数来 存储 UI 线程,例如:
      • MyAuthenticator my_authenticator = new MyAuthenticator(Thread.currentThread());
      • 但这会导致IllegelStateException类似的事情。因此,无法通过这种方式访问​​ UI 线程。
    • 使用BasicSecurityFilterRAP 级别(在plugin.xmlRAP 捆绑包中)可以使用系统默认登录对话框。
      • 但我想有一个自定义的 SecurityFilter 可以访问其他服务器端系统,所以它必须出现在服务器端,RAP/客户端 SecurityFilter 不是选项!

概括

我所能看到的是,用 UI 线程解决问题将是推动这个问题的首选方法。

我还将接受在我的 eclipse-scout-RAP 环境中使用自定义登录对话框的替代解决方案。

4

1 回答 1

1

问题描述:

如果我正确理解了您的用例,您想介绍一些类似于基于表单的身份验证的东西。我想这就是您想要通过在 RAP UI 线程中显示登录对话框来实现的。

解决方案:

采取了一些步骤来向 Scout 演示应用程序 BahBah 聊天引入基于表单的身份验证,该应用程序可在 [1] 中找到。请注意,此示例基于较旧的 Scout 版本 (3.10)。在下面的解释中,将参考[1]中的实现:

在 [1] 中,该方法是利用 Tomcat Web 容器的功能来实现基于表单的身份验证。可以在文件夹 web-resources 下的 RAP UI 包中找到示例 HTML 登录页面 [2]。因此,在 RAP 应用程序的 plugin.xml [3] 中,删除了 servlet 过滤器 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 确保只允许经过身份验证的主体访问 UI 服务器上的受保护资源。在 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 类。

在 Tomcat context.xml 文件中配置了领域。

<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 实现了实际的身份验证过程。在 [6] 中可以找到在 Tomcat 中设置 JAAS 身份验证的一个很好的示例

还请查看 Eclipse Scout 论坛帖子 [7],它以更通用的方式总结了必要的步骤。

于 2016-01-18T11:13:14.990 回答