2014-01-28 40 views
1

我使用以下JavaScript/jQuery函數通過JSON進行遠程過程調用。在Struts2中使用JSON RPC和Spring Security會導致請求被禁止(403)

<s:url var="testJsonUrl" action="testJsonAction"/> 
<script src="../js/jquery-1.8.0.min.js" type="text/javascript"></script> 

var timeout; 
var request; 

$(document).ready(function(){ 
    $("#countryComboBox").change(function(){ 
     if(!request) 
     { 
      request = $.ajax({ 
       datatype:"json", 
       type: "POST", 
       data: JSON.stringify({jsonrpc:'2.0', method:'getStateTables', id:'jsonrpc', params:[$("#countryComboBox").val()]}), 
       contentType: "application/json-rpc; charset=utf-8", 
       url: "<s:property value='#testJsonUrl'/>", 
       success: function(response) 
       { 
        alert(JSON.stringify(response.result)); 
       }, 
       complete: function() 
       { 
        timeout = request = null; 
       }, 
       error: function(request, status, error) 
       { 
        if(status!=="timeout"&&status!=="abort") 
        { 
         alert(status+" : "+error); 
        } 
       } 
      }); 
      timeout = setTimeout(function() { 
       if(request) 
       { 
        request.abort(); 
        alert("The request has been timed out."); 
       } 
      }, 30000); 
     } 
    }); 
}); 

該函數調用在動作類,這是如下的方法getStateTables()

@Namespace("/admin_side") 
@ResultPath("/WEB-INF/content") 
@ParentPackage(value = "json-default") 
public final class TestAction extends ActionSupport 
{ 
    @Autowired 
    private final transient SharableService sharableService = null; 
    private static final long serialVersionUID = 1L; 
    List<StateTable> stateTables; 

    public TestAction() {} 

    @SMDMethod 
    public List<StateTable> getStateTables(@SMDMethodParameter(name="countryId")Long countryId) { 
     stateTables = sharableService.findStatesByCountryId(countryId); 
     return stateTables; 
    } 

    @Action(value = "testJsonAction", 
    results = { 
     @Result(name = ActionSupport.SUCCESS, type = "json", params = {"enableSMD", "true"})}, 
    interceptorRefs = { 
     @InterceptorRef(value = "json", params = {"enableSMD", "true", "includeProperties", "result\\[\\d+\\]\\.stateId, result\\[\\d+\\]\\.stateName", "excludeNullProperties", "true"})}) 
    public String executeAction() throws Exception { 
     return SUCCESS; 
    } 

    @Action(value = "Test", 
    results = { 
     @Result(name = ActionSupport.SUCCESS, location = "Test.jsp"), 
     @Result(name = ActionSupport.INPUT, location = "Test.jsp")}, 
    interceptorRefs = { 
     @InterceptorRef(value = "defaultStack", params = {"params.acceptParamNames", "", "params.excludeMethods", "load", "validation.validateAnnotatedMethodOnly", "true"})}) 
    public String load() throws Exception { 
     //This method is just used to return an initial view on page load. 
     return ActionSupport.SUCCESS; 
    } 
} 

此方法會導致對應於由jQuery函數作爲參數提供給此方法要返回其被委派給jQuery函數作爲JSON響應countryId狀態的列表。

這工作正常,除非春安來進入圖片。在使用Spring Security時,請求被禁止。

標題信息可以查看如下。

Request URL:http://localhost:8080/TestStruts/admin_side/testJsonAction.action 
Request Method:POST 
Status Code:403 Forbidden 
Request Headers 
    Accept:*/* 
    Accept-Encoding:gzip,deflate,sdch 
    Accept-Language:en-US,en;q=0.8 
    Cache-Control:max-age=0 
    Connection:keep-alive 
    Content-Length:73 
    Content-Type:application/json-rpc; charset=UTF-8 
    Cookie:JSESSIONID=0C4D7DFD269F1D5F7315A39971A75961; sbOverlayID=42887237 
    Host:localhost:8080 
    Origin:http://localhost:8080 
    Referer:http://localhost:8080/TestStruts/admin_side/Test.action 
    User-Agent:Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.76 Safari/537.36 
    X-Requested-With:XMLHttpRequest 
Request Payload 
    {jsonrpc:2.0, method:getStateTables, id:jsonrpc, params:[2]} 
    id: "jsonrpc" 
    jsonrpc: "2.0" 
    method: "getStateTables" 
    params: [2] 
Response Headers 
    Content-Length:1149 
    Content-Type:text/html;charset=utf-8 
    Date:Tue, 28 Jan 2014 22:12:55 GMT 
    Server:Apache-Coyote/1.1 
    X-Content-Type-Options:nosniff 
    X-Frame-Options:DENY 
    X-XSS-Protection:1; mode=block 

我的Spring Security配置與this問題中提到的完全相同。

在哪裏查看Spring Security?

回答

0

找到了東西。這是因爲我正在使用CSRF令牌(在spring-security.xml文件中配置爲<csrf/>),該CSRF令牌需要隨AJAX請求一起發送。它工作,當我使用一個jQuery函數<meta>標籤如here所述。

如果您使用JSON,則無法在HTTP參數中提交CSRF令牌 。相反,您可以在 HTTP標頭中提交令牌。一個典型的模式是在您的元標籤中包含CSRF令牌 。下面顯示了一個JSP示例:

<html> 
    <head> 
    <meta name="_csrf" content="${_csrf.token}"/> 
    <!-- default header name is X-CSRF-TOKEN --> 
    <meta name="_csrf_header" content="${_csrf.headerName}"/> 
    <!-- ... --> 
    </head> 
    <!-- ... --> 

然後,您可以在所有Ajax請求中包含令牌。如果 正在使用jQuery,則可以使用以下方法完成:

$(function() { 
    var token = $("meta[name='_csrf']").attr("content"); 
    var header = $("meta[name='_csrf_header']").attr("content"); 
    $(document).ajaxSend(function(e, xhr, options) { 
    xhr.setRequestHeader(header, token); 
    }); 
}); 
相關問題