通过Scout(RAP)中的登录对话框进行身份验证

时间:2015-12-04 08:48:06

标签: eclipse-rap eclipse-scout

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

失败的原因:

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

摘要

我只能看到,用UI线程解决问题将是推动这一问题的首选方式。

我也会接受替代解决方案,在我的eclipse-scout-RAP环境中拥有自定义登录对话框。

1 个答案:

答案 0 :(得分:1)

问题描述:

如果我已正确理解您的用例,您希望引入类似基于表单的身份验证。我想这是你想要通过在RAP UI-Thread中显示登录对话框来实现的。

解决方案提案:

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

在[1]中,方法是利用Tomcat webcontainer的工具来实现基于表单的身份验证。 可以在文件夹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],它以更通用的方式总结了必要的步骤。