web-dev-qa-db-ja.com

Angular2 REST HTTPステータスコード401のリクエストが0に変更されます

Angular2アプリケーションを開発しています。私のアクセストークンが期限切れになると、Responseオブジェクトで401 HTTPステータスコードが値0に変更されるようです。 401 Unauthorizedを受け取っていますが、ERROR Responseオブジェクトのステータスは0です。これにより、401エラーをトラップしてトークンの更新を試みることができません。 401 HTTPステータスコードが0のHTTPステータスコードに変更される原因は何ですか?

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サービスに存在するため、1つの場所でエラーをインターセプトできます。

Google Chromeでは、次のエラーメッセージが表示されます。

XMLHttpRequestを読み込むことができません https://api.cloudcms.com/repositories/XXXXXXXXXXXXXXXXXXX/branches/XXXXXXXXXXXXXXXX/nodesXXXXXXXXXXXXXXXX 。要求されたリソースに「Access-Control-Allow-Origin」ヘッダーがありません。 Origin ' http://screwtopmedia.local.solutiaconsulting.com 'はアクセスを許可されていません。応答のHTTPステータスコード401。

要求に「Access-Control-Allow-Origin」ヘッダーが含まれているため、これは混乱を招きます。

Google Chromeで受信した結果の写真は次のとおりです。

enter image description here

401をトラップする手段として「WWW-Authenticate」応答ヘッダーにアクセスしようとしました。ただし、次のコードはNULLを返します。

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

有効なアクセストークンが提供されたときにCORSエラーが表示されないため、CORSの問題が発生しているのは不可解です。

401 HTTPステータスコードをトラップするにはどうすればよいですか? 401 HTTPステータスコードが0に変更されるのはなぜですか?

ご協力いただきありがとうございます。

23
Tom Schreck

私はCloud CMSで働いています。 API呼び出しでCORSヘッダーが適切に設定されていることを確認できます。ただし、401応答の場合、ヘッダーは適切に設定されません。これは解決されており、修正は今週の終わりに公開APIで利用可能になります。

ところで、JavaScriptドライバーを使用する場合 https://github.com/gitana/gitana-javascript-driver APIに直接書き込む代わりに、再認証フローが自動的に処理されるため、不要です401エラーをトラップします。

5
Harry

この問題はCORSリクエストに関連しています。 このgithubの問題 を参照してください

要求されたリソースに「Access-Control-Allow-Origin」ヘッダーがありません

は、'Access-Control-Allow-Origin'が応答ヘッダーに必要であることを意味します。

Angularはステータスコードを取得していないため、ブラウザは0responseを無効にしてheadersを解析できないため、xml parserを取得します。

正しい[CORS headerserror responseおよびsuccessに追加する必要があります。

19
Ankit Singh

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は2013年8月19日にコメントしました

私はしばらくの間この問題を見つけましたが、返信をここに投稿するのを忘れました。エラー500を含むすべての応答には、CORSヘッダーが添付されている必要があります。サーバーがCORSヘッダーをエラー500応答に添付しない場合、XHRオブジェクトはそれを解析しないため、XHRオブジェクトは応答本体、ステータス、またはその他の応答データを内部に持ちません。

Firefoxネットワークモニターの結果は、上記の理由をサポートしているようです。

JavaScriptリクエストは空のレスポンスを受け取ります。 javascript request

プレーンなURLリクエスト(アドレスバーにリンクをコピーして貼り付ける)は、応答本文を取得します Plain url request

Javascriptは、http通信にXHRHttpRequestを使用します。

XHR応答が到着すると、ブラウザがヘッダーを処理するため、これらの401ネットワークメッセージが表示されます。ただし、XHR応答が別のホストから送信された場合、javascriptおよび応答ヘッダーにCORSヘッダーが含まれていない場合(例:Access-Control-Allow-Origin: *)、ブラウザーはXHRレイヤーに情報を返しません。その結果、応答本文はstatus(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 の詳細について

6
John Siu

W3C によると、ステータス属性が0に設定されている場合、次のことを意味します。

  • 状態はUNSENTまたはOPENEDです。

または

  • エラーフラグが設定されます。

これはAngular2の問題ではなく、リクエストに問題があるようです。

2
Supamiu

Chrome devツールではなく、サードパーティのHTTPプロトコルモニター(CharlesProxyなど)を使用して、APIサービスに実際に送信されているヘッダーと401を返すかどうかを確認する必要があります。

2
Harry

同じ問題が発生し、サーバーが正しい応答を送信しなかったことが原因でした(コンソールログにAngularエラーのステータスが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>

以前に定義された/ errors/...を処理するコントローラー

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

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

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

    }
}
1
TimothyBrake

このアイテムにつまずいた:

私の場合に起こることはそれでした:

  • 別のドメインからRESTをリクエストしていました
  • リソースは401を返しましたが、エラー応答に「Access-Control-Allow-Origin」が設定されていませんでした。
  • Chrome(またはブラウザ)は401を受け取り、ネットワークタブに表示されます(以下のカウントを参照してください:401)が、Angularには渡されませんでした

enter image description here

  • cORSが許可されていなかったため(「Access-Control-Allow-Origin」ヘッダーがない)-Chromeはこの応答をAngularに渡すことができませんでした。このようにChromeが、Angularではありません。

  • 解決策は簡単でした(TimothyBrakeの答えを拡張)-欠落しているヘッダーをエラー応答に追加します。 Springブートではresponse.addHeader("Access-Control-Allow-Origin", "*");と入力し、整理されました。

@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");
  }
}

PS:BeanがWebSecurityConfigurerAdapterのHttpSecurity configに提供されていることを確認してください。参照: https://www.baeldung.com/spring-security-basic-authentication 疑わしい場合.

お役に立てれば。

0
Witold Kaczurba