我一直试图让XSRF在Web应用程序上工作毫无结果。
我正在看一个典型的登录实现。
我正在关注Google's code。
我将web.xml更改为包括:
<servlet>
<servlet-name>xsrf</servlet-name>
<servlet-class>com.google.gwt.user.server.rpc.XsrfTokenServiceServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>xsrf</servlet-name>
<url-pattern>/gwt/xsrf</url-pattern>
</servlet-mapping>
<context-param>
<param-name>gwt.xsrf.session_cookie_name</param-name>
<param-value>JSESSIONID</param-value>
</context-param>
并在我的登录服务的服务器Impl文件上扩展了
XsrfProtectedServiceServlet
。据我了解,服务器上不需要其他更改。我是否需要添加其他内容,例如在此处(以及正在实现的接口中)返回RpcToken
的方法?在客户端,我使用注释。
@XsrfProtect
@RemoteServiceRelativePath("login")
public interface LoginService extends RemoteService {
String check(String user, String pass) throws IllegalArgumentExceptionhere;
}
这可能是我缺少某些东西的地方。 Google在提示中说:
Tip: To specify which RpcToken implementation GWT should generate serializers for use @RpcTokenImplementation annotation.
不知道这是什么意思,或者我是否需要在这里使用其他方法来返回RpcToken。我的异步接口是这样的:
public interface LoginServiceAsync {
//Returns the Session ID
void check(String user, String pass, AsyncCallback<String> callback);
}
然后,对于实际的RPC调用,我将代码包装在xsrf令牌请求周围。我使用与Google相同的代码:
XsrfTokenServiceAsync xsrf = (XsrfTokenServiceAsync)GWT.create(XsrfTokenService.class);
((ServiceDefTarget)xsrf).setServiceEntryPoint(GWT.getModuleBaseURL() + "xsrf");
xsrf.getNewXsrfToken(new AsyncCallback<XsrfToken>() {
public void onSuccess(XsrfToken token) {
LoginServiceAsync rpc = (LoginServiceAsync)GWT.create(LoginService.class);
((HasRpcToken) rpc).setRpcToken(token);
// make XSRF protected RPC call
rpc.check(user, pass, new AsyncCallback<String>() {
// ...
});
}
public void onFailure(Throwable caught) {
try {
throw caught;
} catch (RpcTokenException e) {
// Can be thrown for several reasons:
// - duplicate session cookie, which may be a sign of a cookie
// overwrite attack
// - XSRF token cannot be generated because session cookie isn't
// present
} catch (Throwable e) {
// unexpected
}
});
我的抱怨是我对getNewXsrfToken的调用失败,因为它不知道以下调用中的xsrf位置:
GWT.getModuleBaseURL() + "xsrf"
。我感到缺少令牌握手,这会导致此错误,但是我不确定。最后,我也尝试实现Nick Siderakis' code,但是他的示例使用了一个JSP页面,该页面询问服务器:
XsrfTokenUtil.getToken(request.getSession().getId())
。我不想使用JSP页面,也没有弄清楚如何在没有jsp页面的情况下执行此操作。他的代码也不同于Google代码示例(即,他没有调用getNewXsrfToken),我不知道这是否是Google处理XSRF的“首选”方式。关于我所缺少的任何想法吗?谢谢。
编辑
解决方案如下...
最佳答案
好的,我知道了问题所在。我不得不在上面的代码中将GWT.getModuleBaseURL()+“ xsrf”更改为“ gwt / xsrf”,因为我怀疑它没有指向正确的位置。另外,服务器找不到JSESSIONID cookie,因此我跟随this并添加了Cookies.setCookie(“ JSESSIONID”,“ JSESSIONID”,null,null,“ /”,false);。在我的onModuleLoad()中。做到了。干杯。