3

我已经搜索过有关此主题的教程,但它们都已过时。任何人都可以向我提供有关将 Spring 安全性集成到 GWT 的任何链接或示例吗?

4

1 回答 1

3

首先,您必须牢记 GWT 应用程序已转换为在客户端运行的 javascript,因此您无法真正保护那里的某些资源。所有敏感信息都应该存储在服务器端(与其他情况一样,不仅仅是 GWT),因此正确的方法是从应用程序服务层的角度考虑 Spring Security 集成,并将该安全性与您的通信协议集成使用 - 在 GWT 的情况下,在大多数情况下它是请求工厂。

解决方案不是很简单,但我无法以更好的方式做到这一点......欢迎任何改进建议。

您需要从创建 GWT 开始ServiceLayerDecorator,它将请求工厂的世界与 Spring 的世界连接起来。从 ServiceName 注释值中覆盖createServiceInstance要调用的 Spring 服务类的名称并返回该服务的实例的方法(您需要从 Spring 获取它ApplicationContext):

final Class<?> serviceClass = requestContext.getAnnotation(ServiceName.class).value();
return appContext.getBean(serviceClass);

此外,您需要重写超类invoke(Method, Object...)方法以捕获所有抛出的运行时异常。如果是 Spring Security 的实例,则应分析捕获的异常原因AccessDeniedException。如果是这样,则应重新抛出异常原因。在这种情况下,GWT 不会将异常序列化为字符串,而是将其重新抛出,因此调度程序 servlet 可以通过设置适当的 HTTP 响应状态码来处理它。所有其他类型的异常都会被 GWT 序列化为 String。

实际上,您只能捕获 GWT ReportableException,但不幸的是它具有包访问修饰符(呵呵...... GWT 不是那么容易扩展的)。捕获所有运行时异常更加安全(虽然不是很优雅,但我们别无选择)——如果 GWT 实现发生变化,这段代码仍然可以正常工作。

现在你需要插入你的装饰器。您可以通过扩展请求工厂 servlet 并定义您的 servlet 构造函数来轻松完成,如下所示:

public MyRequestFactoryServlet() {
  this(new DefaultExceptionHandler(), new SpringServiceLayerDecorator());
}

最后一件事——你需要做一个肮脏的黑客攻击并覆盖请求工厂 servlet doPost 方法来改变它处理异常的方式——默认情况下,异常被序列化为字符串,服务器发送 500 个状态码。并非所有异常都应导致 500 sc - 例如,安全异常应导致未经授权的状态代码。所以你需要做的是通过以下方式覆盖异常处理机制:

catch (RuntimeException e) {
  if (e instanceof AccessDeniedException) {
    response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
  } else {
    response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
     LOG.log(Level.SEVERE, "Unexpected error", e);
  }
}

您可以尝试使用一些“围绕”方面,而不是扩展类 - 在这种情况下,这是更清洁的解决方案。

而已!现在您可以像往常一样使用 Spring Security 注释(@Secured等等)来注释您的应用程序服务层。

我知道 - 这一切都很复杂,但 Google 的请求工厂很难扩展。伙计们在通信协议方面做得很好,但是这个库的设计很糟糕。当然客户端代码有一些限制(它被编译成java脚本),但服务器端代码可以设计得更好......

于 2013-06-04T19:43:36.353 回答