如何在SpringMVC中为错误响应启用CORS?

如何在SpringMVC中为错误响应启用CORS?,spring,angular,spring-mvc,oauth-2.0,cors,Spring,Angular,Spring Mvc,Oauth 2.0,Cors,我正在开发一个应用程序,其中后端使用SpringMVC,前端使用Angular5。我一直致力于Auth2安全层的实现,包括跨源资源共享。我的CORS筛选器实现如下所示: @Component @Order(Ordered.HIGHEST_PRECEDENCE) @WebFilter("/*") public class WebSecurityCorsFilter implements Filter { @Override public void init(FilterConfi

我正在开发一个应用程序,其中后端使用SpringMVC,前端使用Angular5。我一直致力于Auth2安全层的实现,包括跨源资源共享。我的CORS筛选器实现如下所示:

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
@WebFilter("/*")
public class WebSecurityCorsFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse res = (HttpServletResponse) response;
        res.setHeader("Access-Control-Allow-Origin", "*");
        res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
        res.setHeader("Access-Control-Max-Age", "3600");
        res.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, Accept, x-requested-with, Cache-Control");


        if ("OPTIONS".equalsIgnoreCase(((HttpServletRequest) request).getMethod())) {
            res.setStatus(HttpServletResponse.SC_OK);
        } else {
            chain.doFilter(request, res);
        }

    }
    @Override
    public void destroy() {
    }
}
我的工作几乎正常,我能够获得access_令牌并使用它从ResourcesServer获取受保护的数据:

{“访问令牌”:“4fcef1f8-4306-4047-9d4d-1c3cf74ecc44”,“令牌类型”:“承载”、“刷新令牌”:“397016eb-dfb0-4944-a2e0-50c3bd07c250”,“到期时间”:29,“范围”:“读取” 写入信任“}

当我尝试使用过期令牌处理请求时,问题就开始了。在这种情况下,我无法通过角度捕捉正确的ErrorResponeCode。HttpClient得到的不是401,而是状态为0的“未知错误”

问题似乎出在CORS策略上,其中ErrorResponse不包括必要的头文件,如Access Control Allow Origin(…)

未能加载:否 “Access Control Allow Origin”标头出现在请求的服务器上 资源。因此,不允许使用源“” 通道响应的HTTP状态代码为401

我搜索了如何在SpringMVC中为ErorrResponse(InvalidTokenException等)启用CORS。我尝试了各种方法:accessDeniedHandler和setExceptionTranslator,但没有成功。我自己真的很努力地想找到解决办法,但我在春天是个初学者。我不确定这是否可能

角度(更新)

@hrdkisback,这不是角度问题,无论如何,这是我的代码:

@Injectable()

export class HttpInterceptorService implements HttpInterceptor {


    addToken(req: HttpRequest<any>, oauthService: AuthenticationService): HttpRequest<any> {

        if(oauthService.isTokenExist()){

            return req.clone({ setHeaders: { Authorization: 'Bearer ' + oauthService.getAccessToken() }})
        }

        return req;
    }


    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> {

        let oauthService = this.inj.get(AuthenticationService);

        return next.handle(this.addToken(req,oauthService))

        .do((event: HttpEvent<any>) => {

            if (event instanceof HttpResponse) {

                // process successful responses here

            }
        }, (error: any) => { 

            if (error instanceof HttpErrorResponse) {

                // Error 

                console.log(error);
            }
        });

    }
}
@Injectable()
导出类HttpInterceptorService实现HttpInterceptor{
addToken(请求:HttpRequest,oauthService:AuthenticationService):HttpRequest{
if(oauthService.isTokenExist()){
返回req.clone({setHeaders:{Authorization:'Bearer'+oauthService.getAccessToken()}})
}
返回请求;
}
截取(req:HttpRequest,next:HttpHandler):可观察{
让oauthService=this.inj.get(AuthenticationService);
返回next.handle(this.addToken(req,oauthService))
.do((事件:HttpEvent)=>{
if(HttpResponse的事件实例){
//在此处理成功的响应
}
},(错误:any)=>{
if(HttpErrorResponse的错误实例){
//错误
console.log(错误);
}
});
}
}

在我在ResourcesServer配置级别上添加CORS筛选器后,问题得到解决,如下所示:

适合我的正确配置

@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {


    @Override
        public void configure(HttpSecurity http) throws Exception {

            http
            .addFilterAfter(new WebSecurityCorsFilter(), CsrfFilter.class)
            ...
        }
   ....
}
在我以前的配置中,我以相同的方式添加了过滤器,但它位于MVC安全配置的顶层,这是我问题的根源:

导致我的问题的先前配置

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {



    @Override
            public void configure(HttpSecurity http) throws Exception {

                http
                .addFilterAfter(new WebSecurityCorsFilter(), CsrfFilter.class)
                ...
            }
       ....
    }

我也遇到了同样的问题。我试着用Angular 5编写Basic Auth。 问题是您没有在错误响应中添加CORS头。 这就是我所做的

@Component
public class AuthEntryPoint extends BasicAuthenticationEntryPoint {

@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authEx)
  throws IOException, ServletException {
    response.addHeader("WWW-Authenticate", "Basic realm=" +getRealmName());
    response.addHeader("Access-Control-Allow-Origin", "http://localhost:4200");
    response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    PrintWriter writer = response.getWriter();
    writer.println("HTTP Status 401 - " + authEx.getMessage());
    }
}
那就行了