CORS服务器上的客户端Ajax调用不包含凭据

时间:2018-10-25 10:33:13

标签: java ajax tomcat cors shiro

我正在Web应用程序中使用Shiro来实现REST API的安全性。当客户端在同一台服务器上运行时,它可以正常工作,但是我无法使其与CORS请求一起使用。经过研究,该应用程序如下所示:

web.xml

<filter>
    <filter-name>CORS</filter-name>
    <filter-class>com.company.project.cors.CORSFilter</filter-class>
    <!--<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>-->
</filter>
<filter-mapping>
    <filter-name>CORS</filter-name>
    <url-pattern>/v2/*</url-pattern>
</filter-mapping>

我尝试了tomcat的CorsFilter实现,但由于无法正常工作,我实现了自己的自定义过滤器:

public class CORSFilter implements Filter {

    public CORSFilter() {}

    public void destroy() {}

    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
            throws IOException, ServletException {

        HttpServletRequest request = (HttpServletRequest) servletRequest;
        System.out.println("CORSFilter HTTP Request: " + request.getMethod());

        HttpServletResponse resp = (HttpServletResponse) servletResponse;

        String origin = request.getHeader("Origin");
        resp.setHeader("Access-Control-Allow-Origin", origin);
        resp.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        resp.setHeader("Vary", "Origin");
        resp.setHeader("Access-Control-Allow-Credentials", "true");
        resp.setHeader("Access-Control-Max-Age", "6000");
        resp.setHeader("Access-Control-Expose-Headers","Access-Control-Allow-Origin, Access-Control-Allow-Headers, Access-Control-Allow-Credentials, Access-Control-Allow-Methods");

    if (request.getMethod().equals("OPTIONS")) {
        resp.setStatus(HttpServletResponse.SC_ACCEPTED);
        resp.setHeader("Access-Control-Allow-Methods", "PUT, GET, OPTIONS, POST, DELETE");
        return;
    }

        // pass the request along the filter chain
        chain.doFilter(request, servletResponse);
    }

    public void init(FilterConfig fConfig) throws ServletException {}
}

我修改了一项服务,以检查服务器在CORS请求中收到的内容:

    @POST
    @Compress
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Response getElementsSearch(SearchRequestObject sro, @Context HttpServletRequest hsr) {
        Subject currentUser = SecurityUtils.getSubject();
        System.out.println("Current User: " + currentUser);
        System.out.println("Session: " + currentUser.getSession(false));
        System.out.println("Current User: " + currentUser.getPrincipal());
        System.out.println("Origin: " + hsr.getHeader("Origin"));
        System.out.println("Headers: ");
        Enumeration<String> e1 = hsr.getHeaderNames();
        while(e1.hasMoreElements()) {
            String param = e1.nextElement();
            System.out.print(param + "; ");
        }
        System.out.println("Cookie: " + hsr.getHeader("cookie"));   

        if(!currentUser.isAuthenticated())  
            return Response.status(Response.Status.UNAUTHORIZED).build();
         .
         .
         .
}

使用jQuery的ajax调用看起来像这样:

$.ajax({
    url:  ServerUrl+'search',
    type: 'POST',
    data: JSON.stringify(objSearch),
    headers: {'Content-Type':'application/json'},
    xhrFields: {
        withCredentials: true
    },
    success: function (result) {
        //Format result

    }, //success
    error: ajaxErrorCallback
});

此调用返回unauthorized,因为尽管将JSESSIONID设置为true,但带有xhrFields.withCredentials的cookie并未包含在请求的标头中,因此服务器将其视为新的未经身份验证的会话。我不知道问题出在服务器端还是客户端。有谁知道我是否错过了什么?

1 个答案:

答案 0 :(得分:0)

登录请求也必须包含withCredentials=true标志。如果不是,似乎JSESSIONID cookie被浏览器关闭了。现在一切正常。