2012-07-05 26 views
0

我有一個使用Spring的REST API。我創建了一個攔截器:如何處理JSON並在Spring Interceptor中修改請求?

@Component 
public class CSRFInterceptor extends HandlerInterceptorAdapter { 
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 

     // code here 

     return true; 
    } 
} 

是使用JSON的每個請求具有以下相應的Java類:

public class CSRFTokenContainer<T> { 
    private T data; 
    private String csrf; 

    public T getData() { 
     return data; 
    } 
    public void setData(T data) { 
     this.data = data; 
    } 
    public String getCsrf() { 
     return csrf; 
    } 
    public void setCsrf(String csrf) { 
     this.csrf = csrf; 
    } 
} 

在我的控制器的所有作品,以及使用例如:

@Controller 
@RequestMapping("/persons") 
public class PersonController { 

    @RequestMapping(method=RequestMethod.POST) 
    public @ResponseBody String create(@RequestBody CSRFTokenContainer<Person> account, HttpServletResponse response) { 

     // do something 

     return "test"; 
    } 
} 

現在我想要做以下事情:控制器應該只接收沒有CSRF令牌的Person對象。 CSRF令牌應該在攔截器內進行處理。我怎樣才能做到這一點?我認爲主要的問題是,我不知道如何讓我的CSRFTokenContainer對象在Interceptor中。之後,我想修改請求以僅包含「數據」部分。

一些代碼示例會很好。

謝謝!

+0

請接受一些你以前的問題 – 2012-07-05 15:11:37

+0

@ Sean Patrick Floyd:完成 – 2012-07-05 16:48:00

回答

0

我已經解決了這個問題CSRF這樣:

創建服務器端的令牌,並把它通過JSP的GWT主機頁面內。令牌也被存儲在Session:

myPage.jsp:

<%@taglib prefix="t" uri="myTags" %> 
<!doctype html> 
<html> 
    <head> 
     ... 
     <script> 
      <t:csrfToken /> 
     </script> 
     ... 
    </head> 
    ... 
</html> 

myTags.tld:

<?xml version="1.0" encoding="UTF-8"?> 
<taglib xsi:schemaLocation=" 
    http://java.sun.com/xml/ns/javaee 
    http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd" 
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    version="2.1"> 

    <tlib-version>1.0</tlib-version> 
    <short-name>t</short-name> 
    <uri>myTags</uri> 

    <tag> 
     <name>csrfToken</name> 
     <tag-class>myapp.server.jsp.CSRFTokenTag</tag-class> 
     <body-content>empty</body-content> 
    </tag> 
</taglib> 

CSRFTokenTag:

public class CSRFTokenTag extends TagSupport { 
    private final SecureRandom random = new SecureRandom(); 

    private String generateToken() { 
     final byte[] bytes = new byte[32]; 
     random.nextBytes(bytes); 
     return Base64.encode(bytes); 
    } 

    @Override 
    public int doStartTag() throws JspException { 
     String token = generateToken(); 

     try { 
      pageContext.getOut().write("var " + "myCSRFVarName" + " = \"" + token + "\";"); 
     } catch (IOException e) {} 

     pageContext.getSession().setAttribute("csrfTokenSessionAttributeName", token); 

     return SKIP_BODY; 
    } 

    @Override 
    public int doEndTag() throws JspException { 
     return EVAL_PAGE; 
    } 
} 

GWT通過JSNI讀取令牌:

public class CSRFToken { 
    private native static String get()/*-{ 
     return $wnd["myCSRFVarName"]; 
    }-*/; 
} 

而且每個請求的Web應用程序發送一個定製HTTP頭裏面的道理,比如像這樣:

RequestBuilder rb = new RequestBuilder(RequestBuilder.GET, "/rest/persons"); 
rb.setHeader("myCSRFTokenHeader", CSRFToken.get()); 
rb.setRequestData("someData"); 
rb.setCallback(new RequestCallback() { 
    @Override 
    public void onResponseReceived(Request request, Response response) { 
     // ... 
    } 
    @Override 
    public void onError(Request request, Throwable exception) { 
     // ... 
    } 
}); 
rb.send(); 

在春天我創建了一個攔截器,對於每個請求從提交的讀取令牌並檢查它:

@Component 
public class CSRFInterceptor extends HandlerInterceptorAdapter {  
    @Override 
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 
     String sessionCSRFToken = (String) request.getSession().getAttribute("csrfTokenSessionAttributeName"); 

     if(sessionCSRFToken != null && sessionCSRFToken.equals(request.getHeader("myCSRFTokenHeader"))) { 
      return true; 
     } else { 
      response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authentication required"); 
      return false; 
     } 
    } 
} 

這可能不是完美的,但它似乎工作得很好!