Я использую 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();
.
.
.
}
Вызов ajax с использованием jQuery выглядит следующим образом:
$.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
, поскольку файл cookie с JSESSIONID
не включается в заголовки запроса, несмотря на то, что для xhrFields.withCredentials
установлено значение true, поэтому сервер рассматривает его как новый, не прошедший проверку подлинности.сессия.Я не знаю, является ли проблема на стороне сервера или клиента.Кто-нибудь знает, если я что-то пропустил?