我正在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并未包含在请求的标头中,因此服务器将其视为新的未经身份验证的会话。我不知道问题出在服务器端还是客户端。有谁知道我是否错过了什么?
答案 0 :(得分:0)
登录请求也必须包含withCredentials=true
标志。如果不是,似乎JSESSIONID cookie被浏览器关闭了。现在一切正常。