使用@Service构造型创建XsrfProtectedServiceServlet会抛出NullPointerException

时间:2017-04-03 20:45:56

标签: java spring gwt csrf

我正在尝试根据指南中的指南为我们的GWT RPC层添加CSRF保护 GWT文档。

我在创建扩展XsrfProtectedServiceServlet的RPC服务实现bean时遇到问题,因为它似乎是上下文 配置仅在创建bean之后创建。尝试运行时,我得到以下NullPointerException 申请:

ERROR [ContextLoader] : Context initialization failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myServiceImpl' defined in file
[/path/to/project/exploded/WEB-INF/classes/za/co/example/server/MyServiceImpl.class]:
Invocation of init method failed; nested exception is java.lang.NullPointerException
.
.
.
Caused by: java.lang.NullPointerException
  at com.google.gwt.user.server.rpc.XsrfProtectedServiceServlet.init(XsrfProtectedServiceServlet.java:84)
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:498)
  at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeCustomInitMethod(AbstractAutowireCapableBeanFactory.java:1713)
  at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1650)
  at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1579)

以下是RPC服务的服务器端实现:

import com.google.gwt.user.server.rpc.XsrfProtectedServiceServlet;

@Service
public class MyServiceImpl extends XsrfProtectedServiceServlet implements MyService {
    // interface overriding methods
}

这是客户端界面:

import com.google.gwt.user.client.rpc.XsrfProtectedService;

public interface MyService extends XsrfProtectedService {
    // interface methods
}

注意:我省略MyServiceAsync,因为在RPC调用中不必进行代码更改以实现反CSRF令牌。

XsrfProtectedServiceServlet尝试通过getServletConfig()访问servlet配置时,抛出空指针,如下所示,即getServletConfig()的返回值为null:

@Override
public void init() throws ServletException {
    super.init();
    // do not overwrite if value is supplied in constructor
    if (sessionCookieName == null) {
        // servlet configuration precedes context configuration
        sessionCookieName = getServletConfig().getInitParameter(
                XsrfTokenServiceServlet.COOKIE_NAME_PARAM);
        if (sessionCookieName == null) {
            sessionCookieName = getServletContext().getInitParameter(
                    XsrfTokenServiceServlet.COOKIE_NAME_PARAM);
        }
        if (sessionCookieName == null) {
            throw new IllegalStateException(
                    XsrfTokenServiceServlet.COOKIE_NAME_NOT_SET_ERROR_MSG);
        }
    }
}

为了让Spring使用@Service构造型正确地注入我的RPC服务实现,我是否需要执行其他配置?

1 个答案:

答案 0 :(得分:0)

查看抛出nullpointer的类的代码,这似乎是有问题的方法:

@Override
  public void init() throws ServletException {
    super.init();
    // do not overwrite if value is supplied in constructor
    if (sessionCookieName == null) {
      // servlet configuration precedes context configuration
      sessionCookieName = getServletConfig().getInitParameter(
          XsrfTokenServiceServlet.COOKIE_NAME_PARAM);
      if (sessionCookieName == null) {
        sessionCookieName = getServletContext().getInitParameter(
            XsrfTokenServiceServlet.COOKIE_NAME_PARAM);
      }
      if (sessionCookieName == null) {
        throw new IllegalStateException(
            XsrfTokenServiceServlet.COOKIE_NAME_NOT_SET_ERROR_MSG);
      }
    }
  }

抛出异常的行是:

sessionCookieName = getServletConfig().getInitParameter(
          XsrfTokenServiceServlet.COOKIE_NAME_PARAM);

因此getServletConfig()方法必须在加载应用程序上下文时返回null。在servlet配置存在之前,您可以确保bean没有“连接”,但是,在您的情况下,有一个简单的解决方案。由于servlet配置和上下文只需要访问cookie名称(如果它为null),您可以通过在构造函数中指定cookie名称来绕过它,即:

public XsrfProtectedServiceServlet(String sessionCookieName) {
    this.sessionCookieName = sessionCookieName;
}

所以在你的MyServiceImpl案例中你要添加:

public MyServiceImpl() {
   super("NAME_OF_THE_COOKIE_YOU_ARE_SPECIFYING_IN_WEB_XML_PROBABLY_JSESSIONID");
}