CROS Implementing Cross-Domain Authorization
Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access. The response had HTTP status code 403
Questions raised
If the resources we access do not require authorization, that is, there is no authentication header in the HTTP request header, then this is enough. However, if the resource requires permission authentication, then the pre-detection option request for cross-domain requests is rejected because it does not carry identity information. The browser will report 401 errors. The error message is as follows:
Failed to load resource: the server responded with a status of 401 (Unauthorized) XMLHttpRequest cannot load http://localhost/api/test. Response for preflight has invalid HTTP status code 401
Now that you know the reason for the problem, it's easy to get the answer: for the resource (api) that needs cross-domain requests, when the server detects that it's OPTONS requests, it releases them all, giving the status of HTTP.OK(200) and the necessary response header, even if it doesn't have identity information.
This problem can be achieved either by writing the corresponding back-end code or by setting up the server configuration file. That is how to set the response header and return 200 status codes.
Solution of Spring+Shrio
The following code can be added to shiro's self-implemented authentication filter:
@Override protected boolean preHandle(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; if(request.getMethod().equals(RequestMethod.OPTIONS.name())) { response.setStatus(HttpStatus.OK.value()); return false; } return super.preHandle(request, response); }
AccessControlFilter in shiro provides basic functions of access control, such as whether access is allowed or how to handle when access is denied, and it is also a parent class of our customized permission validation. We determine whether it is an option request by rewriting its onPreHandle method, and if so, set the corresponding state. The response header has been configured by filter in previous articles) Returning false indicates that the interceptor instance has been processed and will be returned directly.
Tomcat configuration
You need to modify tomcat's global web.xml file under CATALINA_HOME/conf to add the following configuration.
<filter> <filter-name>CorsFilter</filter-name> <filter-class>org.apache.catalina.filters.CorsFilter</filter-class> </filter> <filter-mapping> <filter-name>CorsFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
Nginx configuration
add_header 'Access-Control-Allow-Methods' 'GET,OPTIONS,PUT,DELETE' always; add_header 'Access-Control-Allow-Credentials' 'true' always; add_header 'Access-Control-Allow-Origin' '$http_origin' always; add_header 'Access-Control-Allow-Headers' 'Authorization,DNT,User-Agent, Keep-Alive,Content-Type,accept,origin,X-Requested-With' always; if ($request_method = OPTIONS ) { return 200; }
Apache configuration
Header always set Access-Control-Allow-Origin "http://waffle" Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS" Header always set Access-Control-Allow-Credentials "true" Header always set Access-Control-Allow-Headers "Authorization,DNT,User-Agent,Keep-Alive,Content-Type,accept,origin,X-Requested-With" RewriteCond %{REQUEST_METHOD} OPTIONS RewriteRule ^(.*)$ $1 [R=200,L]
js request example
The Authorization and Content-Type headers need to be added to the request.
$http({ method: 'POST', url: scope.webdav.url, withCredentials: true, headers: { Authorization: 'Basic ' + btoa(user + ':' + password), 'Content-Type': 'application/vnd.google-earth.kml+xml; charset=utf-8' }, data: getKml() })
Reference article: http://www.jujens.eu/posts/en/2015/Jun/27/webdav-options/