Angular2 REST request HTTP status code 401 change à 0

je développe une application Angular2. Il semble que lorsque mon token d'accès expire, le code de statut HTTP 401 soit changé en valeur 0 dans l'objet de réponse. Je reçois 401 non autorisé mais L'objet de réponse D'erreur a un statut de 0. Cela m'empêche de piéger une erreur 401 et de tenter d'actualiser le jeton. Qu'est-ce qui fait que le code de statut HTTP 401 est changé en code de statut HTTP 0?

<!-Voici une capture d'écran de Firefox's console:

enter image description here

Voici mon code:

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

ce code réside dans un service http personnalisé qui étend le HTTP D'Angular2 pour que je puisse intercepter les erreurs dans un seul endroit.

dans Google Chrome, je reçois ce message d'erreur:

XMLHttpRequest cannot load https://api.cloudcms.com/repositories/XXXXXXXXXXXXXXXX/branches/XXXXXXXXXXXXXXXX/nodesXXXXXXXXXXXXXXXX. Non. L'en-tête' Access-Control-Allow-Origin ' est présent sur la ressource demandée. Origine 21-->http://screwtopmedia.local.solutiaconsulting.com' n'est donc pas autorisé à y accéder. La réponse contenait le code de statut HTTP 401.

c'est déroutant car j'inclus l'en-tête 'Access-Control-Allow-Origin' dans request.

<!-Voici une image des résultats reçus dans Google Chrome:

enter image description here

j'ai essayé d'accéder En-tête de réponse 'WWW-Authenticate' comme un moyen de piéger pour 401. Toutefois, le code suivant renvoie une valeur NULL:

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

c'est curieux que j'obtienne un problème CORS parce que je n'obtiens pas d'erreurs CORS quand un token d'accès valide est fourni.

Comment puis-je piéger le code de statut HTTP 401? Pourquoi le code de statut HTTP 401 est-il changé à 0?

Merci pour votre aide.

21
demandé sur Ankit Singh 2016-08-17 17:17:42

6 réponses

je travaille pour Cloud CMS. Je peux confirmer que nous avons correctement paramétré les en-têtes CORS sur les appels API. Toutefois, pour 401 réponses, les en-têtes ne sont pas réglés correctement. Ce problème a été résolu et le correctif sera disponible sur l'API publique à la fin de cette semaine.

BTW si vous utilisez notre pilote javascript https://github.com/gitana/gitana-javascript-driver au lieu d'écrire directement à L'API, le flux re-auth est géré automatiquement et vous n'avez pas besoin de piéger 401 les erreurs à tous.

5
répondu Harry 2016-09-07 16:12:10

Le problème est lié à SCRO demandesc'github question

aucun en-tête' Access-Control-Allow-Origin ' n'est présent sur la requête ressource

signifie que 'Access-Control-Allow-Origin' est obligatoire dans les en-têtes de réponse.

Angular ne reçoit pas de codes de statut, c'est pourquoi il vous donne un 0 qui est causé par le navigateur ne permettant pas le xml parser pour analyser l' response pour cause d'invalidité headers.

Vous devez ajouter correct CORS des en-têtes pour votre error response ainsi que success.

16
répondu Ankit Singh 2017-08-03 09:45:54

Si cloudcms.com faire pour ne pas définir le Access-Control-Allow-Origin dans la réponse 401, alors rien de ce que vous pouvez faire. Vous devez correctement ouvrir billet de soutien avec eux pour confirmer si c'est un comportement normal.

javascript dans les navigateurs (FF, Chrome & Safari) que j'ai testé ne recevra aucune information Si L'erreur CORS se produit, autre que l'état 0. Angular2 n'a aucun contrôle.


j'ai créé un test simple et j'obtiens le même résultat que le vôtre:

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

après beaucoup googler, Je j'ai trouvé ce qui suit (https://github.com/angular/angular.js/issues/3336):

lucassp commente le 19 août 2013

j'ai trouvé le problème depuis un moment maintenant mais j'ai oublié de poster ici une réponse. Chaque réponse, même erreur 500, doit avoir les en-têtes CORS attachés. Si le serveur n'attache pas les en-têtes CORS à la réponse Error 500, alors L'objet XHR ne l'analysera pas, de sorte que L'objet XHR n'aura pas de corps de réponse, de statut ou de toute autre réponse. les données à l'intérieur.

résultat du moniteur réseau de Firefox semble supporter la raison ci-dessus.

Javascript demande recevra de réponse vide. javascript request

demande D'url simple (copier & coller le lien dans la barre d'adresse) obtiendra le corps de réponse Plain url request

Javascript utiliser Xhrhttprequest pour la communication http.

quand une réponse XHR arrive, le navigateur traite l'en-tête, c'est pourquoi vous verrez ces messages du réseau 401. Cependant, si la réponse XHR provient d'un autre hôte, le javascript et l'en-tête de réponse ne contiennent pas d'en-tête CORS(par exemple Access-Control-Allow-Origin: *), le navigateur ne transmet aucune information à la couche XHR. En conséquence, la réponse du corps sera complètement vide avec aucun statut(0).

j'ai testé avec FF 48.0.1, Chrome 52.0.2743.116 et Safari 9.1.2, et ils ont tous le même comportement.

utilisez le moniteur de réseau de navigateur pour vérifier la réponse l'en-tête pour ceux 401 Unauthorized entrées, il est très probable qu'il n'y a pas de Access-Control-Allow-Origin en-tête et de causer le problème que vous affrontez. Cela peut être d'un bug ou d'une conception du prestataire de services secondaires.

Access-Control-Allow-Origin est une réponse seulement en-tête http. Pour plus d'informations sur https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS#The_HTTP_response_headers

6
répondu John Siu 2016-08-30 01:28:49

Selon W3C, si l'attribut status est défini à 0, cela signifie que:

  • L'état est non ENVOYÉS ou OUVERT.

ou

  • le drapeau d'erreur est activé.

je pense que ce n'est pas un Angular2 problème, il semble que votre demande a un problème.

2
répondu Supamiu 2016-08-17 14:27:48

vous devriez utiliser un moniteur de protocole http tiers (comme CharlesProxy) plutôt que les outils de Chrome dev pour confirmer quels en-têtes sont réellement envoyés au service API et s'il retourne un 401.

2
répondu Harry 2016-08-21 13:34:08

j'ai eu le même problème et c'était dû au fait que le serveur n'envoyait pas la bonne réponse (même si le journal de bord de la console indiquait un 401, l'erreur angulaire avait l'état 0). Mon serveur était Tomcat avec L'application Java utilisant MVC de printemps et la sécurité de printemps.

il fonctionne maintenant en utilisant la configuration suivante:

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>

Contrôleur pour gérer le /erreur./.. précédemment défini

@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
répondu user2966436 2016-08-19 13:43:33