Angular 2 REST请求HTTP状态代码401更改为0

Angular 2 REST请求HTTP状态代码401更改为0,rest,angular,cors,Rest,Angular,Cors,我正在开发Angular2应用程序。似乎当我的访问令牌过期时,401HTTP状态代码在响应对象中的值变为0。我正在接收401个未经授权的错误,但错误响应对象的状态为0。这会阻止我捕获401错误并尝试刷新令牌。是什么导致401 HTTP状态代码更改为0的HTTP状态代码 以下是Firefox控制台的屏幕截图: 这是我的密码: get(url: string, options?: RequestOptionsArgs): Observable<any> { //console

我正在开发Angular2应用程序。似乎当我的访问令牌过期时,401HTTP状态代码在响应对象中的值变为0。我正在接收401个未经授权的错误,但错误响应对象的状态为0。这会阻止我捕获401错误并尝试刷新令牌。是什么导致401 HTTP状态代码更改为0的HTTP状态代码

以下是Firefox控制台的屏幕截图:

这是我的密码:

get(url: string, options?: RequestOptionsArgs): Observable<any> 
{
    //console.log('GET REQUEST...', url);

    return super.get(url, options)
        .catch((err: Response): any =>
        {
            console.log('************* ERROR Response', err);

            if (err.status === 400 || err.status === 422)
            {
                return Observable.throw(err);
            }
            //NOT AUTHENTICATED
            else if (err.status === 401)
            {                   
                this.authConfig.DeleteToken();
                return Observable.throw(err);
            }               
            else
            {
                // this.errorService.notifyError(err);
                // return Observable.empty();
                return Observable.throw(err);
            }
        })
        // .retryWhen(error => error.delay(500))
        // .timeout(2000, new Error('delay exceeded'))
        .finally(() =>
        {
            //console.log('After the request...');
        });
}
令人费解的是,我得到了一个CORS问题,因为当提供了有效的访问令牌时,我没有得到任何CORS错误

如何捕获401HTTP状态代码?为什么401 HTTP状态代码更改为0

感谢您的帮助。

根据,如果状态属性设置为0,则表示:

  • 状态为未发送或已打开

  • 已设置错误标志

我认为这不是Angular2的问题,似乎您的请求有问题。

我也有同样的问题,原因是服务器没有发送正确的响应(尽管控制台日志说明角度错误状态为0)。我的服务器是Tomcat,Java应用程序使用SpringMVC和SpringSecurity

它现在正在使用以下设置工作:

SecurityConfig.java

...
protected void configure(HttpSecurity http) throws Exception {
....
    http.exceptionHandling()
            .accessDeniedHandler(accessDeniedHandler)
            .authenticationEntryPoint(authenticationEntryPoint);
    // allow CORS option calls
    http.authorizeRequests().antMatchers(HttpMethod.OPTIONS, "/**").permitAll();
 ...
SomeAuthenticationEntryPoint.java

@Component
public class SomeAuthenticationEntryPoint implements AuthenticationEntryPoint {

  @Override
  public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
    HttpStatus responseStatus = HttpStatus.UNAUTHORIZED;
    response.sendError(responseStatus.value(), responseStatus.getReasonPhrase());
    }
}
web.xml

<error-page>
    <error-code>403</error-code>
    <location>/errors/unauthorised</location>
</error-page>
<error-page>
    <error-code>401</error-code>
    <location>/errors/unauthorised</location>
</error-page>

您应该使用第三方http协议监视器(如CharlesProxy)而不是Chrome开发工具来确认哪些标头实际上被发送到API服务,以及它是否返回401。

该问题与CORS请求有关,请参阅

请求的服务器上不存在“Access Control Allow Origin”标头 资源

表示响应头中需要
'Access-Control-Allow-Origin'

Angular没有获得任何状态代码,这就是为什么它会给您一个
0
,这是由于浏览器由于
标题无效而不允许
xml解析器
解析
响应


您需要将正确的CORS头添加到
错误响应中
以及
成功
如果cloudcms.com不在401响应中设置
访问控制允许源站
,那么您就无能为力了。您必须与他们一起打开支持票,以确认这是否是正常行为

如果出现CORS错误,我测试的浏览器(FF、Chrome和Safari)中的javascript将不会收到任何信息,状态0除外。Angular2无法控制它


我创建了一个简单的测试,得到了与您相同的结果:

geturl() {
    console.log('geturl() clicked');
    let headers = new Headers({ 'Content-Type': 'application/xhtml+xml' });
    let options = new RequestOptions({ 'headers': headers });
    this.http.get(this.url)
        .catch((error): any => {
            console.log('************* ERROR Response', error);
            let errMsg = (error.message) ? error.message :
                error.status ? `${error.status} - ${error.statusText}` : 'Web Server error';
            return Observable.throw(error);
        })
        .subscribe(
        (i: Response) => { console.log(i); },
        (e: any) => { console.log(e); }
        );
}
通过谷歌搜索,我发现了以下内容()

lucassp于2013年8月19日发表评论

我发现这个问题有一段时间了,但我忘了在这里发布回复。每个响应,甚至错误500,都必须附加CORS头。如果服务器没有将CORS头附加到错误500响应,那么XHR对象将不会对其进行解析,因此XHR对象内部不会有任何响应主体、状态或任何其他响应数据

Firefox网络监视器的结果似乎支持上述原因

Javascript请求将收到空响应。

普通url请求(复制并粘贴地址栏中的链接)将获得响应正文

Javascript使用XHRHttpRequest进行http通信

当XHR回复到达时,浏览器将处理标题,这就是您将看到401条网络消息的原因。但是,如果XHR回复来自不同的主机,则javascript和响应标头不包含CORS标头(例如
访问控制允许来源:
),浏览器将不会将任何信息传递回XHR层。因此,回复正文将完全为空,没有状态(0)

我使用FF 48.0.1、Chrome 52.0.2743.116和Safari 9.1.2进行了测试,它们都具有相同的行为

使用浏览器网络监视器检查那些
401未经授权的
条目的响应标题,很可能没有
Access Control Allow Origin
标题,导致您面临的问题。这可能是一个bug,也可能是服务提供商设计的


Access Control Allow Origin
是一个仅响应的http头。有关

的更多信息,我在云CMS工作。我可以确认我们在API调用上正确设置了CORS头。但是,401响应的标题设置不正确。这一问题已经解决,修复程序将于本周末在公共API上发布


顺便说一句,如果您使用我们的javascript驱动程序而不是直接写入API,那么重新验证流将自动处理,您根本不需要捕获401个错误。

偶然发现此项:

我的情况是:

  • 我从不同的领域要求休息
  • 资源返回401,但在错误响应中未设置“访问控制允许原点”
  • Chrome(或您的浏览器)收到401并显示在网络选项卡中(请参见下面的计数:401),但从未传递给Angular

  • 由于不允许CORS(缺少“Access Control Allow Origin”标题),Chrome无法将此响应传递给Angular。这样,我可以看到401在铬,但不是在角

  • 解决方案很简单(扩展了TimothyBrake的答案)——将缺少的头添加到错误响应中。在SpringBoot中,我放入:
    response.addHeader(“访问控制允许源代码“,”*”)然后我就被分类了

PS:确保bean被提供到您的WebSecurity配置适配器中的HttpSecurity配置中。如有疑问,请参阅


希望这有帮助。

很有趣。如何修复此问题?请求将被发送到REST URL,因为我获得了401状态代码。我可以在结果中看到。但是当我得到提供的响应时,状态
@RestController
@RequestMapping("/errors")
public class SecurityExceptionController {

    @RequestMapping("forbidden")
    public void resourceNotFound() throws Exception {
        // Intentionally empty
    }

    @RequestMapping("unauthorised")
    public void unAuthorised() throws Exception {
        // Intentionally empty
        }

    }
}
geturl() {
    console.log('geturl() clicked');
    let headers = new Headers({ 'Content-Type': 'application/xhtml+xml' });
    let options = new RequestOptions({ 'headers': headers });
    this.http.get(this.url)
        .catch((error): any => {
            console.log('************* ERROR Response', error);
            let errMsg = (error.message) ? error.message :
                error.status ? `${error.status} - ${error.statusText}` : 'Web Server error';
            return Observable.throw(error);
        })
        .subscribe(
        (i: Response) => { console.log(i); },
        (e: any) => { console.log(e); }
        );
}
@Component
public class JwtUnauthorizedResponseAuthenticationEntryPoint
  implements AuthenticationEntryPoint {
  @Override
  public void commence(HttpServletRequest request, HttpServletResponse response,
          AuthenticationException authException) throws IOException {

      response.addHeader("Access-Control-Allow-Origin", "*"); 
      response.sendError(HttpServletResponse.SC_UNAUTHORIZED,
              "You would need to provide the Jwt Token to Access This resource");
  }
}