Angular 应用仅在 chrome 中出现 CORS 错误

Angular app gets CORS error only in chrome

在我的 Angular 应用程序(带有远程服务器的本地主机应用程序)上,我仅在 chrome 中收到 CORS 错误,在 Firefox 中,它运行良好。 一旦它在两者上都起作用,但突然停止在 Chrome 上起作用,我猜这与某种更新有关(我猜是 chrome??) 当然,将应用程序上传到生产服务器在两种浏览器上都有效。

我的服务器端代码在 Java (Servlets) 中,我的 CORSFilter 如下所示:

public class CORSFilter implements Filter {
 
    /**
     * Default constructor.
     */
    public CORSFilter() {
        
    }
 
    /**
     * @see Filter#destroy()
     */
    public void destroy() {
        
    }
 
    private final List<String> allowedOrigins = Arrays.asList("http://localhost:4200");
    
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        // Lets make sure that we are working with HTTP (that is, against HttpServletRequest and HttpServletResponse objects)
        if (req instanceof HttpServletRequest && res instanceof HttpServletResponse) {
            HttpServletRequest request = (HttpServletRequest) req;
            HttpServletResponse response = (HttpServletResponse) res;

            // Access-Control-Allow-Origin
            String origin = request.getHeader("Origin");
            LoggingService.writeToLog("call from origin: "+origin+", will be accepted? "+(allowedOrigins.contains(origin)||origin!=null), LogModule.WebAPI, LogLevel.Debug);
            
            response.setHeader("Access-Control-Allow-Origin", allowedOrigins.contains(origin) ? origin : "");
            response.setHeader("Vary", "Origin");
            
            
            // Access-Control-Allow-Credentials
            response.setHeader("Access-Control-Allow-Credentials", "true");

            // Access-Control-Allow-Methods
            response.setHeader("Access-Control-Allow-Methods", "POST,HEAD, PUT, GET, OPTIONS, DELETE");
                       
            // Access-Control-Allow-Headers
            response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization, X-CSRF-TOKEN");
            if (request.getMethod().equals("OPTIONS")) {
                response.setStatus(HttpServletResponse.SC_ACCEPTED);
                return;
            }
     
        }

        chain.doFilter(req, res);
        
    }
}
    

关于如何让它在 Chrome 中工作的任何想法?

该问题与 SameSite cookie 的 Chrome 浏览器 CORS 策略的最后更改有关。 对我来说,因为我想启用 CORS,所以我必须添加 SameSite=None 参数。 这是更新的代码。 这是帮助我验证需要做什么的 post:

请注意,如果您确实需要启用 CORS 选项,此代码非常有用。这是一个重大的决定。

public class CORSFilter implements Filter {
 

 
    private final List<String> allowedOrigins = Arrays.asList("http://localhost:4200");
    
    private final String SESSION_COOKIE_NAME = "JSESSIONID";
    private final String SESSION_PATH_ATTRIBUTE = ";Path=";
    private final String ROOT_CONTEXT = "/";
    private final String SAME_SITE_ATTRIBUTE_VALUES = ";HttpOnly;SameSite=None;Secure";
 
    
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        // Lets make sure that we are working with HTTP (that is, against HttpServletRequest and HttpServletResponse objects)
        if (req instanceof HttpServletRequest && res instanceof HttpServletResponse) {
            HttpServletRequest request = (HttpServletRequest) req;
            HttpServletResponse response = (HttpServletResponse) res;

            // Access-Control-Allow-Origin
            String origin = request.getHeader("Origin");
            LoggingService.writeToLog("call from origin: "+origin+", will be accepted? "+(allowedOrigins.contains(origin)||origin!=null), LogModule.WebAPI, LogLevel.Debug);
            
            response.setHeader("Access-Control-Allow-Origin", allowedOrigins.contains(origin) ? origin : "");
            response.setHeader("Vary", "Origin");
            String requestUrl = request.getRequestURL().toString();
            
            // Access-Control-Max-Age
            //response.setHeader("Access-Control-Max-Age", "3600");

            // Access-Control-Allow-Credentials
            response.setHeader("Access-Control-Allow-Credentials", "true");

            // Access-Control-Allow-Methods
            response.setHeader("Access-Control-Allow-Methods", "POST,HEAD, PUT, GET, OPTIONS, DELETE");
            
            /*
            This the code that i added to the code to use SameSite=None Cookie
            */
            boolean isResourceRequest = requestUrl != null ? StringUtils.isNoneBlank(allowedOrigins.stream().filter(s -> requestUrl.contains(s)).findFirst().orElse(null)) : null;
            if (!isResourceRequest) {
                Cookie[] cookies = ((HttpServletRequest) request).getCookies();
                if (cookies != null && cookies.length > 0) {
                    List<Cookie> cookieList = Arrays.asList(cookies);
                    Cookie sessionCookie = cookieList.stream().filter(cookie -> SESSION_COOKIE_NAME.equals(cookie.getName())).findFirst().orElse(null);
                    if (sessionCookie != null) {
                        String contextPath = request.getServletContext() != null && StringUtils.isNotBlank(request.getServletContext().getContextPath()) ? request.getServletContext().getContextPath() : ROOT_CONTEXT;
                        response.setHeader("Set-Cookie", sessionCookie.getName() + "=" + sessionCookie.getValue() + SESSION_PATH_ATTRIBUTE + contextPath + SAME_SITE_ATTRIBUTE_VALUES);
                    }
                }
            }
            
           /*
            End of new code
           */
            
            // Access-Control-Allow-Headers
            response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization, X-CSRF-TOKEN");
            if (request.getMethod().equals("OPTIONS")) {
                response.setStatus(HttpServletResponse.SC_ACCEPTED);
                return;
            }
     
        }

        chain.doFilter(req, res);
        
    }
    
 
 
}

允许您的来源来源,在 API 调用中

app.get('/rout',(req,res)=>{
    res.set('Access-Control-Allow-Origin', 'http://localhost:8000');
    res.json(res)
})

http://localhost:8000 将其替换为您的来源 URL