我在我的网络应用程序中使用 Shiro 来确保 REST API 的安全性。当客户端在同一台服务器上运行时它工作正常,但我无法让它与 CORS 请求一起工作。经过一些研究,该应用看起来像这样:
网络.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
,因为尽管设置了 xhrFields.withCredentials
,但带有 JSESSIONID
的 cookie 并未包含在请求的 header 中> 为 true,因此服务器将其视为新的未经身份验证的 session 。不知道问题出在服务端还是客户端。有谁知道我是否错过了什么?
最佳答案
登录请求也必须包含 withCredentials=true
标志。如果不是,则 JSESSIONID cookie 似乎已被浏览器关闭。现在一切正常。
关于java - CORS 服务器上的客户端 Ajax 调用不包含凭据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52987183/