2016-08-17 73 views
19

我正在开发一个Angular2应用程序。看起来,当我的访问令牌过期时,401 HTTP状态代码在Response对象中被更改为值0。我正在接收401 Unauthorized,但ERROR Response对象的状态为0.这阻止了我捕获401错误并尝试刷新令牌。什么导致401 HTTP状态码变为HTTP状态码0?Angular2 REST请求HTTP状态代码401更改为0

下面是截图来自Firefox的控制台:

enter image description here

这里是我的代码:

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...'); 
     }); 
} 

此代码驻留在扩展Angular2的HTTP这样我就可以在一个单一的拦截失误自定义HTTP服务位置。

在谷歌浏览器,我收到此错误信息:

的XMLHttpRequest无法加载https://api.cloudcms.com/repositories/XXXXXXXXXXXXXXXX/branches/XXXXXXXXXXXXXXXX/nodesXXXXXXXXXXXXXXXX。请求的资源上没有“Access-Control-Allow-Origin”标题。因此'Origin'http://screwtopmedia.local.solutiaconsulting.com'不允许访问。该响应具有HTTP状态代码401.

这很混乱,因为我在请求中包含'Access-Control-Allow-Origin'标头。

下面是谷歌浏览器接收到的结果的画面:

enter image description here

我试图访问“WWW验证”响应头作为一种手段来捕获401但是,下面的代码返回NULL:

err.headers.get("WWW-Authenticate") 

它令人费解的是,我得到一个CORS问题,因为我提供了一种有效的访问令牌时我没有得到任何CORS错误。

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

感谢您的帮助。

+1

如果cloudcms.com在401响应中没有设置Access-Control-Allow-Origin,那么您无能为力。您必须打开支持凭单才能确认这是否是正常行为。 JavaScript在浏览器(FF,Chrome和Safari)我测试的将不会收到任何信息,如果发生CORS错误,除状态0. Angular2无法控制它。 –

+0

你解决了这个问题吗?我的意思是在服务器不发送更正代码的情况下,但在Chrome控制台上,您看到401,但角度不断给0状态? – stackdave

回答

5

我为Cloud CMS工作。我可以确认我们在API调用中正确设置了CORS头文件。但是,对于401响应,标题设置不正确。这个问题已经得到解决,修复程序将在本周末的公共API上提供。

顺便说一句,如果您使用我们的JavaScript驱动https://github.com/gitana/gitana-javascript-driver而不是直接写入API,那么重认证流程会自动处理,您根本不需要捕获401错误。

2

根据W3C,如果状态属性设置为0,则意味着:

  • 状态是UNSENT或打开。

  • 错误标志被置位。

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

+0

有趣。你如何解决这个问题? –

+0

该请求正在发送到REST URL,因为我收到了401状态码。结果中我可以看到401未经授权。但是,当我得到所提供的响应时,状态码是0.因此,UNSENT状态看起来不正确。 –

1

我有同样的问题,并且是由于服务器没有发送正确的响应(即使控制台日志声明401角度错误的状态为0)。我的服务器是使用Spring MVC和Spring Security的Java应用程序的Tomcat。

它现在正在使用如下因素设置:

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> 

控制器为h andle的/错误/ ...以前定义

@RestController 
@RequestMapping("/errors") 
public class SecurityExceptionController { 

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

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

    } 
} 
+0

感谢您的回复。我正在使用的服务是第三方服务。所以,我无法控制/访问他们的服务器。任何想法为什么我可以在控制台中看到401状态码,但Angular中的错误对象的状态码为0?这说明问题是Angular,而不是服务器。 –

2

你应该使用第三方http协议监视器(如CharlesProxy),而不是Chrome浏览器开发工具,以确认其头实际上是被发送到API服务,如果它返回一个401

+0

感谢您的回复。我也使用Postman,并且在提交过期的令牌时可以看到从第三方API调用返回的401未授权状态。所以,我不认为这个问题与第三方服务有关。看起来,错误响应对象的错误状态在Angular2内部的某个地方从401变为了0。 –

16

的问题与CORS请求,看到this github issue

否“访问控制允许来源”标头出现在请求 资源

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

角没有得到任何状态代码,这就是为什么它给你这是不允许​​浏览器解析response由于无效headers引起了0

您需要将正确的CORS标头添加到您的error response以及success

+1

因此,来自第三方源的响应也需要头部中的'Access-Control-Allow-Origin'?我已经将其添加到我的请求中。 –

+0

这个状态代码仍然很古怪,为什么Google会说这是一个CORS请求问题,而不是Firefox? –

+0

它不是Firefox,因为我在Google Chrome中遇到同样的问题 –

5

如果cloudcms.com在401响应中没有设置Access-Control-Allow-Origin,那么您无能为力。您必须打开支持凭单才能确认这是否是正常行为。

浏览器中的javascript(FF,Chrome & Safari)如果发生CORS错误(除状态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); } 
     ); 
} 

多的谷歌搜索后,我发现了以下(https://github.com/angular/angular.js/issues/3336):

lucassp于8月19日评论,2013

我发现了一段时间的问题,但我忘了这里的帖子回复。每个响应,即使是错误500,都必须附加CORS头。如果服务器没有将CORS头连接到Error 500响应,那么XHR对象不会解析它,因此XHR对象内部不会有任何响应主体,状态或任何其他响应数据。

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

JavaScript请求将收到空响应。 javascript request

平原URL请求(复制粘贴&在地址栏中的链接)会得到响应主体 Plain url request

JavaScript中使用XHRHttpRequest用于HTTP通讯。

当XHR回复到达时,浏览器将处理标题,这就是为什么你会看到这些401网络消息。但是,如果XHR回复来自不同的主机,那么javascript和回应头不包含CORS头(例如Access-Control-Allow-Origin: *),浏览器不会将任何信息传递回XHR层。因此,答复主体将完全是空的,没有状态(0)。

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

使用浏览器网络监视器检查这些401 Unauthorized条目的响应标头,很可能没有Access-Control-Allow-Origin标题并导致您遇到的问题。这可能是一个错误,也可能是服务提供商方面的设计。

Access-Control-Allow-Origin是仅响应http头。欲了解更多的信息https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#The_HTTP_response_headers