2014-01-28 10 views
1

다음 JavaScript/jQuery 함수를 사용하여 JSON을 통해 원격 프로 시저를 호출합니다.Spring Security와 함께 Struts2에서 JSON RPC를 사용하면 요청이 금지됩니다. (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; 
    } 
} 

이 방법은 JSON 응답으로서 jQuery를 함수에 위임 리턴이 메소드 파라미터로서 JQuery와 기능에 의해 공급되는 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 

My Spring Security 구성은 this 질문에서 언급 한 것과 완전히 동일합니다.

스프링 시큐리티는 어디서 볼 수 있습니까?

답변

0

발견 된 항목. 이는 AJAX 요청과 함께 보내야하는 CSRF 토큰 (spring-security.xml 파일에 <csrf/>으로 구성됨)을 사용하기 때문입니다. 그것은 내가 <meta> 태그와 함께 jQuery 함수를 사용할 때 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); 
    }); 
});