etc./StackOverFlow

jQuery Ajax 호출 후 리디렉션 요청을 관리하는 방법

청렴결백한 만능 재주꾼 2022. 3. 4. 07:55
반응형

질문자 :Elliot Vargas


$.post() 를 사용하여 Ajax를 사용하여 서블릿을 호출한 다음 결과 HTML 조각을 사용하여 사용자의 현재 페이지에서 div 그러나 세션 시간이 초과되면 서버는 리디렉션 지시문을 보내 사용자를 로그인 페이지로 보냅니다. 이 경우 jQuery는 div 요소를 로그인 페이지의 내용으로 대체하여 사용자의 눈이 실제로 보기 드문 장면을 보게 합니다.

jQuery 1.2.6을 사용하여 Ajax 호출에서 리디렉션 지시문을 관리하려면 어떻게 해야 합니까?



나는 이 질문을 읽고 브라우저가 리디렉션을 투명하게 처리하는 것을 피하기 위해 응답 HTTP 상태 코드 를 278로 설정하는 것과 관련하여 명시된 접근 방식을 구현했습니다. 이게 효과가 있긴 했지만 약간의 해킹이라 조금 불만족스러웠습니다.

더 파고들고 나서 이 접근 방식을 버리고 JSON을 사용했습니다. 이 경우 AJAX 요청에 대한 모든 응답은 상태 코드 200을 가지며 응답 본문에는 서버에서 구성된 JSON 개체가 포함됩니다. 그런 다음 클라이언트의 JavaScript는 JSON 개체를 사용하여 수행해야 할 작업을 결정할 수 있습니다.

나는 당신과 비슷한 문제가있었습니다. 두 가지 가능한 응답이 있는 AJAX 요청을 수행합니다. 하나는 브라우저를 새 페이지로 리디렉션 하고 다른 하나는 현재 페이지의 기존 HTML 양식을 새 페이지로 교체하는 것입니다. 이를 수행하는 jQuery 코드는 다음과 같습니다.

 $.ajax({ type: "POST", url: reqUrl, data: reqBody, dataType: "json", success: function(data, textStatus) { if (data.redirect) { // data.redirect contains the string URL to redirect to window.location.href = data.redirect; } else { // data.form contains the HTML for the replacement form $("#myform").replaceWith(data.form); } } });

data.redirectdata.form 2가지 멤버를 갖도록 서버에서 구성됩니다. 나는 이 접근 방식이 훨씬 낫다는 것을 알았다.


Steg

다음과 같이 이 문제를 해결했습니다.

  1. 응답에 사용자 정의 헤더 추가:

     public ActionResult Index(){ if (!HttpContext.User.Identity.IsAuthenticated) { HttpContext.Response.AddHeader("REQUIRES_AUTH","1"); } return View(); }
  2. JavaScript 함수를 ajaxSuccess 이벤트에 바인딩하고 헤더가 있는지 확인합니다.

     $(document).ajaxSuccess(function(event, request, settings) { if (request.getResponseHeader('REQUIRES_AUTH') === '1') { window.location = '/'; } });

Community Wiki

301 및 302 응답을 올바르게 처리하는 브라우저는 없습니다. 그리고 실제로 표준은 Ajax 라이브러리 공급업체에게 엄청난 골칫거리인 "투명하게" 처리해야 한다고 말합니다. Ra-Ajax에서 우리는 서버로부터 투명하게 리디렉션을 처리하기 위해 HTTP 응답 상태 코드 278(일부 "미사용" 성공 코드)을 사용해야 했습니다...

이것은 저를 정말 짜증나게 합니다. 만약 여기 누군가가 W3C에서 "풀" 기능을 가지고 있다면 W3C에 301 및 302 코드를 직접 처리해야 한다는 사실을 알려주시면 감사하겠습니다...! ;)


Thomas Hansen

결국 구현된 솔루션은 Ajax 호출의 콜백 함수에 래퍼를 사용하고 이 래퍼에서 반환된 HTML 청크에 특정 요소가 있는지 확인하는 것이었습니다. 요소가 발견되면 래퍼가 리디렉션을 실행했습니다. 그렇지 않은 경우 래퍼는 호출을 실제 콜백 함수로 전달했습니다.

예를 들어 래퍼 함수는 다음과 같았습니다.

 function cbWrapper(data, funct){ if($("#myForm", data).length > 0) top.location.href="login.htm";//redirection else funct(data); }

그런 다음 Ajax 호출을 할 때 다음과 같은 것을 사용했습니다.

 $.post("myAjaxHandler", { param1: foo, param2: bar }, function(data){ cbWrapper(data, myActualCB); }, "html" );

이것은 모든 Ajax 호출이 항상 페이지의 일부를 교체하는 데 사용하는 DIV 요소 내부에 HTML을 반환했기 때문에 효과가 있었습니다. 또한 로그인 페이지로 리디렉션하기만 하면 됩니다.


Elliot Vargas

나는 레몬을 약간 트위스트한 Timmerz의 방법을 좋아합니다. JSON을 예상할 때 text/html의 contentType 이 반환되면 리디렉션될 가능성이 큽니다. 제 경우에는 페이지를 새로고침하기만 하면 로그인 페이지로 리디렉션됩니다. 아, 그리고 jqXHR 상태가 200인지 확인하십시오. 오류 기능에 있기 때문에 어리석은 것처럼 보입니다. 그렇지 않으면 합법적인 오류가 반복적으로 다시 로드됩니다(죄송합니다).

 $.ajax( error: function (jqXHR, timeout, message) { var contentType = jqXHR.getResponseHeader("Content-Type"); if (jqXHR.status === 200 && contentType.toLowerCase().indexOf("text/html") >= 0) { // assume that our login has expired - reload our current page window.location.reload(); } });

BrianY

낮은 수준의 $.ajax() 호출을 사용합니다.

 $.ajax({ url: "/yourservlet", data: { }, complete: function(xmlHttp) { // xmlHttp is a XMLHttpRquest object alert(xmlHttp.status); } });

리디렉션을 위해 다음을 시도하십시오.

 if (xmlHttp.code != 200) { top.location.href = '/some/other/page'; }

Till

누군가에게 도움이 될 수 있으므로 내 접근 방식을 공유하고 싶었습니다.

기본적으로 사용자 이름 표시와 같은 인증 작업을 처리하는 JavaScript 모듈과 로그인 페이지로 의 리디렉션을 처리하는 이 경우를 포함했습니다.

내 시나리오: 기본적으로 모든 요청을 수신하고 로그인 페이지에 대한 302 및 위치 헤더로 응답하는 ISA 서버가 있습니다.

내 JavaScript 모듈에서 내 초기 접근 방식 은 다음과 같습니다.

 $(document).ajaxComplete(function(e, xhr, settings){ if(xhr.status === 302){ //check for location header and redirect... } });

문제(여기에 이미 많은 사람들이 언급했듯이)는 브라우저가 자체적으로 리디렉션을 처리하므로 내 ajaxComplete 콜백이 호출되지 않았지만 대신 분명히 status 200 이미 리디렉션된 로그인 페이지 의 응답을 받았습니다. 문제: 성공적인 200 응답이 실제 로그인 페이지인지 아니면 다른 임의의 페이지인지 어떻게 감지합니까?

해결책

302 리디렉션 응답을 캡처할 수 없었기 때문에 로그인 페이지 자체의 URL이 포함 LoginPage 모듈에서 이제 헤더를 수신하고 리디렉션을 수행합니다.

 if(xhr.status === 200){ var loginPageRedirectHeader = xhr.getResponseHeader("LoginPage"); if(loginPageRedirectHeader && loginPageRedirectHeader !== ""){ window.location.replace(loginPageRedirectHeader); } }

...그리고 그것은 매력처럼 작동합니다 :). LoginPage 헤더에 URL을 포함하는 이유가 궁금할 xhr 개체에서 자동 위치 리디렉션으로 인해 GET 의 URL을 결정할 방법이 없기 때문입니다...


Juri

나는 이 주제가 오래되었다는 것을 알고 있지만 내가 발견하고 이전에 여기에서 설명한 또 다른 접근 방식을 제공할 것입니다. 기본적으로 WIF와 함께 ASP.MVC를 사용하고 있습니다 (그러나 이것은 이 주제의 컨텍스트에 대해 실제로 중요하지 않습니다. 어떤 프레임워크를 사용하든 대답은 적절합니다. 단서는 변경되지 않습니다. - ajax 요청을 수행하는 동안 인증 실패와 관련된 문제 처리) ) .

아래에 표시된 접근 방식은 모든 ajax 요청에 즉시 적용할 수 있습니다(beforeSend 이벤트를 분명히 재정의하지 않는 경우).

 $.ajaxSetup({ beforeSend: checkPulse, error: function (XMLHttpRequest, textStatus, errorThrown) { document.open(); document.write(XMLHttpRequest.responseText); document.close(); } });

CheckPulse 요청이 수행되기 전에 CheckPulse 메서드가 호출됩니다(가장 간단한 컨트롤러 메서드).

 [Authorize] public virtual void CheckPulse() {}

사용자가 인증되지 않은 경우(토큰이 만료된 경우) 이러한 메서드에 액세스할 수 없습니다( Authorize 속성으로 보호됨). 프레임워크가 인증을 처리하기 때문에 토큰이 만료되는 동안 응답에 http 상태 302를 넣습니다. 브라우저가 302 응답을 투명하게 처리하지 않도록 하려면 Global.asax에서 이를 포착하고 응답 상태를 변경하십시오(예: 200 OK). 또한 헤더를 추가하여 이러한 응답을 특별한 방식으로 처리하도록 지시합니다(나중에 클라이언트 측에서).

 protected void Application_EndRequest() { if (Context.Response.StatusCode == 302 && (new HttpContextWrapper(Context)).Request.IsAjaxRequest()) { Context.Response.StatusCode = 200; Context.Response.AddHeader("REQUIRES_AUTH", "1"); } }

마지막으로 클라이언트 측에서 이러한 사용자 정의 헤더를 확인하십시오. 존재하는 경우 - 로그온 페이지로의 전체 리디렉션을 수행해야 합니다(내 경우 window.location 은 내 프레임워크에서 자동으로 처리되는 요청의 url로 대체됨).

 function checkPulse(XMLHttpRequest) { var location = window.location.href; $.ajax({ url: "/Controller/CheckPulse", type: 'GET', async: false, beforeSend: null, success: function (result, textStatus, xhr) { if (xhr.getResponseHeader('REQUIRES_AUTH') === '1') { XMLHttpRequest.abort(); // terminate further ajax execution window.location = location; } } }); }

jwaliszko

이를 처리하는 더 좋은 방법은 기존 HTTP 프로토콜 응답 코드, 특히 401 Unauthorized 를 활용하는 것입니다.

해결 방법은 다음과 같습니다.

  1. 서버 측: 세션이 만료되고 요청이 ajax인 경우. 401 응답 코드 헤더 보내기
  2. 클라이언트 측: ajax 이벤트에 바인딩

     $('body').bind('ajaxSuccess',function(event,request,settings){ if (401 == request.status){ window.location = '/users/login'; } }).bind('ajaxError',function(event,request,settings){ if (401 == request.status){ window.location = '/users/login'; } });

IMO 이것은 더 일반적이며 새로운 사용자 정의 사양/헤더를 작성하지 않습니다. 또한 기존 ajax 호출을 수정할 필요가 없습니다.

편집: 아래 @Rob의 설명에 따라 401(인증 오류에 대한 HTTP 상태 코드)이 표시기여야 합니다. 자세한 내용은 403 Forbidden vs 401 Unauthorized HTTP 응답 을 참조하세요. 일부 웹 프레임워크는 인증 및 권한 부여 오류 모두에 403을 사용하므로 그에 따라 조정하십시오. 고마워 롭.


rynop

이 문제를 다음과 같이 해결했습니다.

응답을 처리하는 미들웨어를 추가하고, ajax 요청에 대한 리디렉션인 경우 리디렉션 URL을 사용하여 응답을 일반 응답으로 변경합니다.

 class AjaxRedirect(object): def process_response(self, request, response): if request.is_ajax(): if type(response) == HttpResponseRedirect: r = HttpResponse(json.dumps({'redirect': response['Location']})) return r return response

그런 다음 ajaxComplete에서 응답에 리디렉션이 포함되어 있으면 리디렉션이어야 하므로 브라우저의 위치를 변경합니다.

 $('body').ajaxComplete(function (e, xhr, settings) { if (xhr.status == 200) { var redirect = null; try { redirect = $.parseJSON(xhr.responseText).redirect; if (redirect) { window.location.href = redirect.replace(/\?.*$/, "?next=" + window.location.pathname); } } catch (e) { return; } } }

Tyr

내가 찾은 또 다른 솔루션(전역 동작을 설정하려는 경우 특히 유용함)은 $.ajaxsetup() 메서드를 statusCode 속성 과 함께 사용하는 것입니다. 다른 사람들이 지적한 것처럼 리디렉션 상태 코드( 3xx )를 사용하지 말고 대신 4xx 를 사용하고 리디렉션 클라이언트 측을 처리하십시오.

 $.ajaxSetup({ statusCode : { 400 : function () { window.location = "/"; } } });

400 을 처리하려는 상태 코드로 바꾸십시오. 이미 언급했듯이 401 Unauthorized 는 좋은 생각이 될 수 있습니다. 400 이 매우 불특정하기 때문에 400을 사용하고 더 구체적인 경우(잘못된 로그인 자격 증명 등)에 401 따라서 직접 리디렉션하는 대신 세션 시간이 초과되고 리디렉션 클라이언트 측을 처리하면 4xx backbone.js와 같은 프레임워크에서도 저에게 완벽하게 작동합니다.


morten.c

나는 나를 위해 작동하는 간단한 솔루션을 가지고 있으며 서버 코드 변경이 필요하지 않습니다 ... 육두구 tsp를 추가하십시오 ...

 $(document).ready(function () { $(document).ajaxSend( function(event,request,settings) { var intercepted_success = settings.success; settings.success = function( a, b, c ) { if( request.responseText.indexOf( "<html>" ) > -1 ) window.location = window.location; else intercepted_success( a, b, c ); }; }); });

html 태그가 있는지 확인하지만 indexOf를 변경하여 로그인 페이지에 존재하는 고유 문자열을 검색할 수 있습니다...


Timmerz

주어진 솔루션의 대부분은 추가 헤더 또는 부적절한 HTTP 코드를 사용하여 해결 방법을 사용합니다. 이러한 솔루션은 아마도 작동하지만 약간 '해키'한 느낌이 들 것입니다. 나는 다른 해결책을 생각해 냈습니다.

401 응답에서 리디렉션(passiveRedirectEnabled="true")하도록 구성된 WIF를 사용하고 있습니다. 리디렉션은 일반 요청을 처리할 때 유용하지만 AJAX 요청에서는 작동하지 않습니다(브라우저가 302/리디렉션을 실행하지 않기 때문에).

global.asax에서 다음 코드를 사용하여 AJAX 요청에 대한 리디렉션을 비활성화할 수 있습니다.

 void WSFederationAuthenticationModule_AuthorizationFailed(object sender, AuthorizationFailedEventArgs e) { string requestedWithHeader = HttpContext.Current.Request.Headers["X-Requested-With"]; if (!string.IsNullOrEmpty(requestedWithHeader) && requestedWithHeader.Equals("XMLHttpRequest", StringComparison.OrdinalIgnoreCase)) { e.RedirectToIdentityProvider = false; } }

이렇게 하면 AJAX 요청에 대해 401 응답을 반환할 수 있습니다. 그러면 자바스크립트가 페이지를 다시 로드하여 처리할 수 있습니다. 페이지를 다시 로드하면 WIF에서 처리할 401이 발생합니다(WIF는 사용자를 로그인 페이지로 리디렉션합니다).

401 오류를 처리하는 자바스크립트의 예:

 $(document).ajaxError(function (event, jqxhr, settings, exception) { if (jqxhr.status == 401) { //Forbidden, go to login //Use a reload, WIF will redirect to Login location.reload(true); } });

Rob

이 문제는 ASP.NET MVC RedirectToAction 메서드를 사용하여 나타날 수 있습니다. div에 응답을 표시하는 양식을 방지하려면 $.ajaxSetup으로 응답을 수신하기 위해 일종의 ajax 응답 필터를 수행하면 됩니다. 응답에 MVC 리디렉션이 포함된 경우 JS 측에서 이 표현식을 평가할 수 있습니다. 아래 JS에 대한 예제 코드:

 $.ajaxSetup({ dataFilter: function (data, type) { if (data && typeof data == "string") { if (data.indexOf('window.location') > -1) { eval(data); } } return data; } });

데이터가 "window.location = '/Acount/Login'"인 경우 필터는 이를 포착하고 데이터를 표시하는 대신 리디렉션을 수행하도록 평가합니다.


Przemek Marcinkiewicz

Vladimir Prudnikov와 Thomas Hansen이 말한 것을 종합하면:

  • 서버 측 코드를 변경하여 XHR인지 감지하십시오. 그렇다면 리디렉션의 응답 코드를 278로 설정합니다. django에서:
 if request.is_ajax(): response.status_code = 278

이렇게 하면 브라우저가 응답을 성공으로 처리하고 Javascript에 전달합니다.

  • JS에서 양식 제출이 Ajax를 통해 이루어졌는지 확인하고 응답 코드를 확인하고 필요한 경우 리디렉션합니다.
 $('#my-form').submit(function(event){ event.preventDefault(); var options = { url: $(this).attr('action'), type: 'POST', complete: function(response, textStatus) { if (response.status == 278) { window.location = response.getResponseHeader('Location') } else { ... your code here ... } }, data: $(this).serialize(), }; $.ajax(options); });

Graham King

 <script> function showValues() { var str = $("form").serialize(); $.post('loginUser.html', str, function(responseText, responseStatus, responseXML){ if(responseStatus=="success"){ window.location= "adminIndex.html"; } }); } </script>

Priyanka

노력하다

 $(document).ready(function () { if ($("#site").length > 0) { window.location = "<%= Url.Content("~") %>" + "Login/LogOn"; } });

로그인 페이지에 넣으십시오. 메인 페이지의 div에 로드된 경우 로그인 페이지로 리디렉션됩니다. "#site"는 로그인 페이지를 제외한 모든 페이지에 있는 div의 id입니다.


podeig

Spring Security를 사용하는 경우 답변이 작동하는 것처럼 보이지만 LoginUrlAuthenticationEntryPoint를 확장하고 AJAX를보다 강력하게 처리하기 위해 특정 코드를 추가하는 것을 발견했습니다. 대부분의 예제는 인증 실패뿐만 아니라 모든 리디렉션을 가로챕니다. 이것은 내가 작업하는 프로젝트에 바람직하지 않았습니다. 실패한 AJAX 요청을 캐시하지 않으려면 ExceptionTranslationFilter를 확장하고 "sendStartAuthentication" 메소드를 재정의하여 캐시 단계를 제거해야 할 수도 있습니다.

AjaxAwareAuthenticationEntryPoint의 예:

 public class AjaxAwareAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint { public AjaxAwareAuthenticationEntryPoint(String loginUrl) { super(loginUrl); } @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { if (isAjax(request)) { response.sendError(HttpStatus.UNAUTHORIZED.value(), "Please re-authenticate yourself"); } else { super.commence(request, response, authException); } } public static boolean isAjax(HttpServletRequest request) { return request != null && "XMLHttpRequest".equals(request.getHeader("X-Requested-With")); } }

출처: 1 , 2


John

내 login.php 페이지에 다음을 넣어 이 문제를 해결했습니다.

 <script type="text/javascript"> if (top.location.href.indexOf('login.php') == -1) { top.location.href = '/login.php'; } </script>

Paul Richards

@Steg가 설명한 대로 문제를 다시 인용하겠습니다.

나는 당신과 비슷한 문제가있었습니다. 브라우저를 새 페이지로 리디렉션하는 응답과 현재 페이지의 기존 HTML 양식을 새 페이지로 바꾸는 응답의 2가지 가능한 응답이 있는 ajax 요청을 수행합니다.

IMHO 이것은 진정한 도전이며 현재 HTTP 표준으로 공식적으로 확장되어야 합니다.

나는 새로운 Http 표준이 새로운 상태 코드를 사용할 것이라고 믿습니다. 의미: 현재 301/302 는 브라우저에게 이 요청 location 가져오도록 지시합니다.

확장 표준에서 응답 status: 308 (예시)인 경우 브라우저는 기본 페이지를 제공된 location

그 말은; 나는 이미 이 미래의 동작을 모방하는 경향이 있으므로 document.redirect가 필요할 때 서버가 다음과 같이 응답하도록 합니다.

 status: 204 No Content x-status: 308 Document Redirect x-location: /login.html

JS가 " status: 204 "를 x-status: 308 location 헤더에 제공된 페이지로 document.redirect를 수행합니다.

이것이 당신에게 의미가 있습니까?


Chaim Klar

일부 사용자는 다음이 유용할 수 있습니다.

인증 토큰 없이 전송되는 모든 휴식 작업에 대해 클라이언트가 로그인 페이지로 리디렉션되기를 원했습니다. 내 모든 휴식 작업은 Ajax 기반이므로 Ajax 성공 기능을 처리하는 대신 로그인 페이지로 리디렉션하는 좋은 일반적인 방법이 필요했습니다.

이것이 내가 한 일입니다.

모든 Ajax 요청에서 내 서버는 Json 200 응답 "NEED TO AUTHENTICATE"를 반환합니다(클라이언트가 인증해야 하는 경우).

Java(서버 측)의 간단한 예:

 @Secured @Provider @Priority(Priorities.AUTHENTICATION) public class AuthenticationFilter implements ContainerRequestFilter { private final Logger m_logger = LoggerFactory.getLogger(AuthenticationFilter.class); public static final String COOKIE_NAME = "token_cookie"; @Override public void filter(ContainerRequestContext context) throws IOException { // Check if it has a cookie. try { Map<String, Cookie> cookies = context.getCookies(); if (!cookies.containsKey(COOKIE_NAME)) { m_logger.debug("No cookie set - redirect to login page"); throw new AuthenticationException(); } } catch (AuthenticationException e) { context.abortWith(Response.ok("\"NEED TO AUTHENTICATE\"").type("json/application").build()); } } }

내 Javascript에서 다음 코드를 추가했습니다.

 $.ajaxPrefilter(function(options, originalOptions, jqXHR) { var originalSuccess = options.success; options.success = function(data) { if (data == "NEED TO AUTHENTICATE") { window.location.replace("/login.html"); } else { originalSuccess(data); } }; });

그게 다야.


Tomer

서블릿에서 response.setStatus(response.SC_MOVED_PERMANENTLY); 리디렉션에 필요한 '301' xmlHttp 상태를 보내려면...

$.ajax 함수에서 .toString() 함수를 사용하면 안 됩니다...

if (xmlHttp.status == 301) { top.location.href = 'xxxx.jsp'; }

문제는 매우 유연하지 않고 리디렉션할 위치를 결정할 수 없다는 것입니다.

서블릿을 통해 리디렉션하는 것이 가장 좋은 방법입니다. 하지만 여전히 올바른 방법을 찾을 수 없습니다.


Juan Toro

나는 단지 전체 페이지에 대한 모든 ajax 요청을 처리하고 싶었습니다. @SuperG가 시작했습니다. 내가 끝내는 것은 다음과 같습니다.

 // redirect ajax requests that are redirected, not found (404), or forbidden (403.) $('body').bind('ajaxComplete', function(event,request,settings){ switch(request.status) { case 301: case 404: case 403: window.location.replace("http://mysite.tld/login"); break; } });

내 결정의 기준이 되는 특정 http 상태 코드를 구체적으로 확인하고 싶었습니다. 그러나 성공 이외의 다른 것을 얻기 위해 ajaxError에 바인딩할 수 있습니다(200개만 가능).

 $('body').bind('ajaxError', function(event,request,settings){ window.location.replace("http://mysite.tld/login"); }

Bretticus

값도 전달하려면 세션 변수를 설정하고 액세스할 수도 있습니다. 예: jsp에서 다음을 작성할 수 있습니다.

 <% HttpSession ses = request.getSession(true); String temp=request.getAttribute("what_you_defined"); %>

그런 다음이 임시 값을 자바 스크립트 변수에 저장하고 놀 수 있습니다.


karthik339

헤더 솔루션으로 성공하지 못했습니다. 내 ajaxSuccess / ajaxComplete 메서드에서 선택되지 않았습니다. 사용자 정의 응답과 함께 Steg의 답변을 사용했지만 JS 측을 일부 수정했습니다. $.get$.post 메서드를 사용할 수 있도록 각 함수에서 호출하는 메서드를 설정합니다.

 function handleAjaxResponse(data, callback) { //Try to convert and parse object try { if (jQuery.type(data) === "string") { data = jQuery.parseJSON(data); } if (data.error) { if (data.error == 'login') { window.location.reload(); return; } else if (data.error.length > 0) { alert(data.error); return; } } } catch(ex) { } if (callback) { callback(data); } }

사용 예시...

 function submitAjaxForm(form, url, action) { //Lock form form.find('.ajax-submit').hide(); form.find('.loader').show(); $.post(url, form.serialize(), function (d) { //Unlock form form.find('.ajax-submit').show(); form.find('.loader').hide(); handleAjaxResponse(d, function (data) { // ... more code for if auth passes ... }); }); return false; }

jocull

HTTP Header 추가하여 문제를 해결합니다. 서버 측의 모든 요청에 대한 응답 직전에 현재 요청된 URL을 응답의 헤더에 추가합니다.

서버의 내 응용 프로그램 유형은 Asp.Net MVC 이며 이를 수행할 수 있는 좋은 장소가 있습니다. Global.asax 에서 다음과 Application_EndRequest 이벤트를 구현했습니다.

 public class MvcApplication : System.Web.HttpApplication { // ... // ... protected void Application_EndRequest(object sender, EventArgs e) { var app = (HttpApplication)sender; app.Context.Response.Headers.Add("CurrentUrl",app.Context. Request.CurrentExecutionFilePath); } }

그것은 나를 위해 완벽하게 작동합니다! JQuery $.post 의 모든 응답에는 요청된 url 302 , 303 ,... POST 메서드의 결과로 제공되는 다른 응답 헤더가 있습니다.

그리고 다른 중요한 점은 서버 측이나 클라이언트 측에서 코드를 수정할 필요가 없다는 것입니다.

다음은 이러한 방식으로 오류, 메시지 및 ...와 같은 사후 조치의 다른 정보에 액세스하는 기능입니다.

나는 이것을 게시했는데 누군가를 도울 수 있습니다 :)


Ali Adlavaran

나는 땜질하고있는 django 앱에서이 문제를 겪고있었습니다 (면책 조항 : 나는 배우기 위해 땜질하고 있으며 결코 전문가가 아닙니다). 내가하고 싶었던 것은 jQuery ajax를 사용하여 DELETE 요청을 리소스에 보내고 서버 측에서 삭제 한 다음 (기본적으로) 홈페이지로 리디렉션을 보내는 것입니다. HttpResponseRedirect('/the-redirect/') 를 보냈을 때 jQuery의 ajax 메서드는 302 대신 200을 수신했습니다.

 response = HttpResponse(status='300') response['Location'] = '/the-redirect/' return response

그런 다음 다음과 같이 jQuery.ajax를 사용하여 클라이언트에서 요청을 보내거나 처리했습니다.

 <button onclick="*the-jquery*">Delete</button> where *the-jquery* = $.ajax({ type: 'DELETE', url: '/resource-url/', complete: function(jqxhr){ window.location = jqxhr.getResponseHeader('Location'); } });

300을 사용하는 것이 "옳지" 않을 수도 있지만 적어도 내가 원하는 대로 작동했습니다.

추신 : 이것은 SO의 모바일 버전에서 편집하는 데 큰 고통이었습니다. 내 대답이 끝났을 때 어리석은 ISP가 내 서비스 취소 요청을 완료했습니다!


Benny Jobigan

XMLHttpRequest 보내기 프로토타입을 후크할 수도 있습니다. 이것은 하나의 핸들러를 사용하는 모든 전송(jQuery/dojo/etc)에 대해 작동합니다.

500 페이지 만료 오류를 처리하기 위해 이 코드를 작성했지만 200 리디렉션을 트래핑하는 데에도 잘 작동해야 합니다. readyState의 의미에 대한 XMLHttpRequest onreadystatechange에 대한 위키피디아 항목을 준비합니다.

 // Hook XMLHttpRequest var oldXMLHttpRequestSend = XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.send = function() { //console.dir( this ); this.onreadystatechange = function() { if (this.readyState == 4 && this.status == 500 && this.responseText.indexOf("Expired") != -1) { try { document.documentElement.innerHTML = this.responseText; } catch(error) { // IE makes document.documentElement read only document.body.innerHTML = this.responseText; } } }; oldXMLHttpRequestSend.apply(this, arguments); }

Curtis Yallop

@John 및 @Arpad 링크 및 @RobWinch 링크 의 답변을 사용하여 작업 솔루션을 얻었습니다.

저는 Spring Security 3.2.9와 jQuery 1.10.2를 사용합니다.

Spring의 클래스를 확장하여 AJAX 요청에서만 4XX 응답을 발생시킵니다.

 public class CustomLoginUrlAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint { public CustomLoginUrlAuthenticationEntryPoint(final String loginFormUrl) { super(loginFormUrl); } // For AJAX requests for user that isn't logged in, need to return 403 status. // For normal requests, Spring does a (302) redirect to login.jsp which the browser handles normally. @Override public void commence(final HttpServletRequest request, final HttpServletResponse response, final AuthenticationException authException) throws IOException, ServletException { if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) { response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied"); } else { super.commence(request, response, authException); } } }

applicationContext-security.xml

 <security:http auto-config="false" use-expressions="true" entry-point-ref="customAuthEntryPoint" > <security:form-login login-page='/login.jsp' default-target-url='/index.jsp' authentication-failure-url="/login.jsp?error=true" /> <security:access-denied-handler error-page="/errorPage.jsp"/> <security:logout logout-success-url="/login.jsp?logout" /> ... <bean id="customAuthEntryPoint" class="com.myapp.utils.CustomLoginUrlAuthenticationEntryPoint" scope="singleton"> <constructor-arg value="/login.jsp" /> </bean> ... <bean id="requestCache" class="org.springframework.security.web.savedrequest.HttpSessionRequestCache"> <property name="requestMatcher"> <bean class="org.springframework.security.web.util.matcher.NegatedRequestMatcher"> <constructor-arg> <bean class="org.springframework.security.web.util.matcher.MediaTypeRequestMatcher"> <constructor-arg> <bean class="org.springframework.web.accept.HeaderContentNegotiationStrategy"/> </constructor-arg> <constructor-arg value="#{T(org.springframework.http.MediaType).APPLICATION_JSON}"/> <property name="useEquals" value="true"/> </bean> </constructor-arg> </bean> </property> </bean>

내 JSP에서 여기에 표시된 대로 전역 AJAX 오류 처리기를 추가합니다.

 $( document ).ajaxError(function( event, jqxhr, settings, thrownError ) { if ( jqxhr.status === 403 ) { window.location = "login.jsp"; } else { if(thrownError != null) { alert(thrownError); } else { alert("error"); } } });

또한 JSP 페이지의 AJAX 호출에서 기존 오류 처리기를 제거합니다.

 var str = $("#viewForm").serialize(); $.ajax({ url: "get_mongoDB_doc_versions.do", type: "post", data: str, cache: false, async: false, dataType: "json", success: function(data) { ... }, // error: function (jqXHR, textStatus, errorStr) { // if(textStatus != null) // alert(textStatus); // else if(errorStr != null) // alert(errorStr); // else // alert("error"); // } });

나는 그것이 다른 사람들을 돕기를 바랍니다.

Update1 양식 로그인 구성에 옵션(always-use-default-target="true")을 추가해야 한다는 것을 알았습니다. 이것은 AJAX 요청이 로그인 페이지로 리디렉션된 후(세션 만료로 인해) Spring이 이전 AJAX 요청을 기억하고 로그인 후 자동으로 리디렉션하기 때문에 필요했습니다. 그러면 반환된 JSON이 브라우저 페이지에 표시됩니다. 물론, 내가 원하는 것은 아닙니다.

Update2 always-use-default-target="true" 를 사용하는 대신 requstCache에서 AJAX 요청을 차단하는 @RobWinch 예제를 사용하세요. 이렇게 하면 로그인 후 일반 링크를 원래 대상으로 리디렉션할 수 있지만 AJAX는 로그인 후 홈 페이지로 이동합니다.


Darren Parker

아래의 경우와 같이 statusCode 옵션을 사용합니다. 리디렉션은 일반적으로 리디렉션에 대한 301, 302 상태 코드입니다.

 $.ajax({ type: <HTTP_METHOD>, url: {server.url}, data: {someData: true}, statusCode: { 301: function(responseObject, textStatus, errorThrown) { //yor code goes here }, 302: function(responseObject, textStatus, errorThrown) { //yor code goes here } } }) .done(function(data){ alert(data); }) .fail(function(jqXHR, textStatus){ alert('Something went wrong: ' + textStatus); }) .always(function(jqXHR, textStatus) { alert('Ajax request was finished') });

sumit

출처 : http:www.stackoverflow.com/questions/199099/how-to-manage-a-redirect-request-after-a-jquery-ajax-call

반응형