将GWT与Spring Security框架集成

时间:2013-06-03 12:17:50

标签: spring gwt spring-security

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

1 个答案:

答案 0 :(得分:3)

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

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

您需要首先创建GWT ServiceLayerDecorator,它将请求工厂的世界与Spring世界连接起来。覆盖createServiceInstance方法,从ServiceName注释值调用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 s.c - 例如安全异常会导致未经授权的状态代码。因此,您需要做的是以下列方式覆盖异常处理机制:

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);
  }
}

不是扩展类,而是尝试使用一些'around'方面 - 在这种情况下它是更清晰的解决方案。

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

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