Java implements CORS cross-domain requests

problem

When developing projects using front-end and back-end decoupling patterns, you often encounter the problem of not being able to obtain server-side data across domains.

This is due to the browser's homology policy, for security purposes. Today, the front-end and back-end separated development model is very popular. Front-end and back-end projects are often developed in different environments. At this time, there will be cross-domain requests for data. Current solutions mainly include the following:

JSONP, iframe, proxy mode, CORS, etc.

The first few ways are not mentioned here, there are a lot of information on the Internet. Here I mainly share the solution of CORS, which is "cross-domain resource sharing". It allows browsers to issue XMLHttpRequest requests to cross-source servers, thus overcoming the restriction that AJAX can only be used in the same source.

The CORS cross-domain process is the same as the ordinary ajax process, except that the browser automatically handles some things for us when it finds that this is a cross-domain request, so as long as the server provides support, the front end does not need to do additional things.

Realization

The general idea is to use a filter to obtain the request information of the requesting object, such as Origin field (which indicates the source of the request, including protocol, domain name, port), to determine whether the request is legal by the pre-configured parameters, and then set the head information of the response object to achieve cross-domain resource requests. Before we introduce the implementation, let's look at the response header information that will be used.

Response head

  • Access-Control-Allow-Methods
    HTTP methods used to list browser CORS requests that are allowed to use, such as GET, POST, PUT, DELETE, OPTIONS

  • Access-Control-Allow-Credentials
    Indicates whether cross-domain cookies are supported

  • Access-Control-Allow-Headers
    A comma-separated string representing all header information fields supported by the server, such as Content-Type and custom fields

  • Access-Control-Expose-Headers
    Contrary to Access-Control-Allow-Headers, header information fields are not supported

  • Access-Control-Allow-Origin
    Allow cross-domain request source information, including protocols, domain names, ports, to * indicate that all request sources are allowed, and only one request source can be set

Here's how the Java background implements this approach.

Code

Since spring-boot has recently been used, the next step is to implement it on the basis of spring-boot.

First, create a CorsFilter filter, code as follows:

...
@WebFilter(filterName = "corsFilter", urlPatterns = "/*",
        initParams = {@WebInitParam(name = "allowOrigin", value = "*"),
                @WebInitParam(name = "allowMethods", value = "GET,POST,PUT,DELETE,OPTIONS"),
                @WebInitParam(name = "allowCredentials", value = "true"),
                @WebInitParam(name = "allowHeaders", value = "Content-Type,X-Token")})
public class CorsFilter implements Filter {

    private String allowOrigin;
    private String allowMethods;
    private String allowCredentials;
    private String allowHeaders;
    private String exposeHeaders;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        allowOrigin = filterConfig.getInitParameter("allowOrigin");
        allowMethods = filterConfig.getInitParameter("allowMethods");
        allowCredentials = filterConfig.getInitParameter("allowCredentials");
        allowHeaders = filterConfig.getInitParameter("allowHeaders");
        exposeHeaders = filterConfig.getInitParameter("exposeHeaders");
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        HttpServletResponse response = (HttpServletResponse) servletResponse;
        if (!StringUtils.isEmpty(allowOrigin)) {
            if(allowOrigin.equals("*")){
                response.setHeader("Access-Control-Allow-Origin", allowOrigin);
            }else{
                List<String> allowOriginList = Arrays.asList(allowOrigin.split(","));
                if (allowOriginList != null && allowOriginList.size() > 0) {
                    String currentOrigin = request.getHeader("Origin");
                    if (allowOriginList.contains(currentOrigin)) {
                        response.setHeader("Access-Control-Allow-Origin", currentOrigin);
                    }
                }
            }
        }
        if (!StringUtils.isEmpty(allowMethods)) {
            response.setHeader("Access-Control-Allow-Methods", allowMethods);
        }
        if (!StringUtils.isEmpty(allowCredentials)) {
            response.setHeader("Access-Control-Allow-Credentials", allowCredentials);
        }
        if (!StringUtils.isEmpty(allowHeaders)) {
            response.setHeader("Access-Control-Allow-Headers", allowHeaders);
        }
        if (!StringUtils.isEmpty(exposeHeaders)) {
            response.setHeader("Access-Control-Expose-Headers", exposeHeaders);
        }
        filterChain.doFilter(servletRequest, servletResponse);
    }

    @Override
    public void destroy() {

    }
}

With great success, the front-end can obtain background data across domains. It is much easier than other methods. The code is not explained and easy to understand. The same is true with other background development methods. The ultimate goal is to judge requests, set up response heads, and do nothing at the front-end.

Java Learning and Exchange QQ Group: 589809992 No gossip, do not enter unless you like it!

Keywords: Java Spring

Added by adrive on Wed, 22 May 2019 22:58:42 +0300