2016-08-17 169 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