programing

프록시로부터의 HTTP 302 응답을 angularjs 단위로 처리합니다.

javamemo 2023. 3. 31. 21:21
반응형

프록시로부터의 HTTP 302 응답을 angularjs 단위로 처리합니다.

여러 응용 프로그램의 글로벌 인증을 확인하는 역방향 프록시가 있습니다.사용자가 연결 해제되어도 응용 프로그램을 사용하려고 하면 프록시는 302 응답을 보냅니다.

HTTP/1.1 302 Found
Date: Wed, 11 Sep 2013 09:05:34 GMT
Cache-Control: no-store
Location: https://other.url.com/globalLoginPage.html
Content-Length: 561
Content-Type: text/html; charset=iso-8859-1
Via: 1.1 my-proxy.com
Connection: Keep-Alive

비어 입니다.angularJs는 0입니다.그래서 나는 정말 아무 것도 할 수 없는 것 같아...
이 주제에 대해 몇 가지 질문을 보았는데도 무슨 일이 일어나고 있는지 모르겠어요(프록시 또는 로케이션의 다른 도메인으로 인한 CORS?, 브라우저 동작 302?).
특히 답변에는 다음과 같은 내용이 있습니다(https://stackoverflow.com/a/17903447/1093925):

주의: 서버가 응답 코드를 301 또는 302로 설정하면 Location 헤더는 자동으로 XMLHttpRequest 오브젝트 뒤에 투과적으로 이어지기 때문에 얻을 수 없습니다.

"XMLHttpRequest" "XMLHttpRequest" "XMLHttpRequest" "XMLHttpRequest?"
Chrome의 매우 오래된 버전(새로운 버전은 사용할 수 없음)에서는 네트워크 패널에 대응하는 요구가 표시되어 있습니다만, 응답이 없기 때문에 실패하는 것 같습니다.
파이어폭스는 파이어폭스.

프록시 설정 및 응답을 변경할 수 없기 때문에 어떻게 할 수 있습니까?


저는 오늘 시나리오를 재연했습니다만, 새로운 버전의 파이어 버그 덕분에, 무슨 일이 일어나고 있는지 더 자세히 알 수 있었습니다.
나는 크로스 도메인 정책이라는 내 질문에서 anwser와 멀지 않았다.
어플리케이션에 의한 HTTP 요구이기 때문에 브라우저는 다음 XMLHttpRequest(앱 내에서는 동일한 요구로 보입니다)를 거부합니다.따라서 오류와 빈 응답입니다.
저는 할 수 생각합니다.

내 앱에서도 같은 문제가 있었어.302 리다이렉트 응답의 「캐치」는 할 수 없습니다.브라우저는 Angular가 그것을 손에 넣기 전에 그것을 포착한다.그래서 실제로 당신이 답변을 받았을 때는 이미 너무 늦었다.

나쁜 소식은 각진 플랫폼에서는 문제가 되지 않는다는 것입니다.xmlHttpRequest는 이러한 동작을 지원하지 않습니다.또한 브라우저는 사용자가 어떤 조치를 취하기 전에 동작합니다.참조: XmlhttpRequest의 리다이렉트 방지

좋은 소식은 응답을 가로채는 방법으로 이 문제를 회피하고 사랑스런 302임을 인식할 수 있는 방법을 찾는 것입니다.이게 해킹이지만 지금으로선 최선이에요

를 들어, 제 앱에서는 리다이렉트가 앱의 login.html 페이지로 돌아왔고, 앱에서는 200상태의 응답을 얻었고, 응답 데이터는 제 login.html 페이지의 내용입니다.그래서 인터셉터에서 결과가 문자열인지 확인하고(보통 그렇지 않습니다! 효율성은 없습니다.) 확인했습니다.그렇다면 로그인 페이지인지 아닌지는 확인했습니다.그렇게 하면 방향 전환을 잡아서 내 방식대로 처리할 수 있을 거야

yourApp.factory('redirectInterceptor', ['$location', '$q', function($location, $q) {
    return function(promise) {
        promise.then(
            function(response) {
                if (typeof response.data === 'string') {
                    if (response.data.indexOf instanceof Function &&
                        response.data.indexOf('<html id="ng-app" ng-app="loginApp">') != -1) {
                        $location.path("/logout");
                        window.location = url + "logout"; // just in case
                    }
                }
                return response;
            },
            function(response) {
                return $q.reject(response);
            }
        );
        return promise;
    };
}]);

그런 다음 이 인터셉터를 앱에 삽입하십시오. 다음과 같습니다.

$httpProvider.responseInterceptors.push('redirectInterceptor');

행운을 빌어요.

- 직접 할 수 있는 .302 - Redirect 。 이렇게 , 하다, 하다, 하다, 이렇게 쓸 수 있어요.httpInterceptor와드도 하다, 하다, 하다, 하다를 넣어야 요.$httpProvider어플리케이션 DI 목록과 구성 기능의 어딘가에 다음과 같은 참조가 있습니다.

$httpProvider.responseInterceptors.push('HttpInterceptor');

대행 수신기의 예는 다음과 같습니다.

window.angular.module('HttpInterceptor', [])
.factory('HttpInterceptor', ['$q', '$injector',
    function($q, $injector) {
        'use strict';

        return function(promise) {
            return promise.then(success, error);
        };

        function success(response) {
            return response;
        }

        function error(response) {
            var isAuthRequest = (response.config.url.indexOf('/v1/rest/auth') !== -1);

            //if we are on the authenticating don't open the redirect dialog
            if (isAuthRequest) {
                return $q.reject(response);
            }

            //open dialog and return rejected promise
            openErrorDialog(response);
            return $q.reject(response);
        }

        function openErrorDialog(response) {
            $injector.get('$dialog').dialog({
                backdropFade: true,
                dialogFade: true,
                dialogClass: 'modal newCustomerModal',
                resolve: {
                    errorData: function() {
                        return response.data;
                    },
                    errorStatus: function() {
                        return response.status;
                    }
                }
            })
            .open('/views/error-dialog-partial.htm',
                'errorDialogController')
            .then(function(response) {
                if (response) {
                    window.location = '/';
                }
            });
        }
    }
]);

위에서 설명한 바와 같이 xmlHttpRequest는 리다이렉트 반환을 지원하지 않기 때문에 Angular에서는 302개의 응답을 사용할 수 없습니다.브라우저는 사용자가 리다이렉트를 실행하기 전에 동작합니다.

및 코드
헤더를 할 수 .X-Redirect츠키노「」의 값X-Redirect 、 [ URL ]로 하는 URL이어야 .https://other.url.com/globalLoginPage.html

$http.get(orig_url).then(function(response) {
        // do stuff
    }, function (response) {
        var headers = response.headers();
        if ('x-redirect' in headers)
        {
            document.location.href = headers['x-redirect'];
        }
        return response;
    }
}

보다 글로벌한 솔루션에서는 HTTP 대행 수신기를 사용할 수도 있습니다.

app.factory('myHttpInterceptor', function ($q, myCache) {
    return {
        request: function (config) {
            return config;
        },
        response: function(response){
            var headers = response.headers();
            if ('x-redirect' in headers)
            {
                document.location.href = headers['x-redirect'];
            }    
            return response;
        },
        responseError: function(rejection) {    
            switch(rejection.status)
            {
                case 302:
                    // this will not occur, use the custom header X-Redirect instead
                    break;
                case 403:
                    alert.error(rejection.data, 'Forbidden');
                    break;
            }
            return $q.reject(rejection);
        }
    };
});

커스텀 헤더 서버측을 설정할 수 있습니다.
PHP Symfony:

$response = new Response('', 204);
$response->headers->set('X-Redirect', $this->generateUrl('other_url'));
return $response;

비슷한 문제가 있어서 Ofer Segev가 제공하는 솔루션을 검토했는데, 다른 페이지의 html fragment와 일치하는지 확인하기 위해 응답 내용을 확인하는 것은 저에게 너무 허접하게 느껴졌습니다.누군가 페이지를 바꾸면 어떻게 되나요?

다행히 백엔드도 제어할 수 있었기 때문에 302(Redirect)를 반환하는 대신 403(Forbidden)을 반환하고 헤더 내의 원하는 위치를 전달했습니다.302와는 달리 403은 에러 핸들러로 처리되며, 여기서 다음에 수행할 작업을 결정할 수 있습니다.그 결과 핸들러는 다음과 같습니다.

function ($scope, $http) {
    $http.get(_localAPIURL).then(function (response) {
            // do what I'd normally do
        }, function (response) {
        if (response.status == 403)
        {
            window.location.href = response.headers().location;
        }
        else
        {
            // handle the error
        }

참고용입니다.Iframe 형식으로 302를 반환할 것으로 예상되는 콜을 발신할 수도 있습니다.이렇게 하면 페이지에 남아서 https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage과 통신할 수 있습니다.

언급URL : https://stackoverflow.com/questions/18737674/handle-http-302-response-from-proxy-in-angularjs

반응형