Javascript 如何在jQuery Ajax调用后管理重定向请求
我使用Javascript 如何在jQuery Ajax调用后管理重定向请求,javascript,jquery,ajax,redirect,Javascript,Jquery,Ajax,Redirect,我使用$.post()使用Ajax调用servlet,然后使用生成的HTML片段替换用户当前页面中的div元素。但是,如果会话超时,服务器将发送重定向指令,将用户发送到登录页面。在本例中,jQuery将用登录页面的内容替换div元素,迫使用户亲眼目睹一个罕见的场景 如何使用jQuery 1.2.6管理来自Ajax调用的重定向指令?使用低级的$.Ajax()调用: $.ajax({ url: "/yourservlet", data: { }, complete: function(x
$.post()
使用Ajax调用servlet,然后使用生成的HTML片段替换用户当前页面中的div
元素。但是,如果会话超时,服务器将发送重定向指令,将用户发送到登录页面。在本例中,jQuery将用登录页面的内容替换div
元素,迫使用户亲眼目睹一个罕见的场景
如何使用jQuery 1.2.6管理来自Ajax调用的重定向指令?使用低级的
$.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';
}
if(xhr.status === 200){
var loginPageRedirectHeader = xhr.getResponseHeader("LoginPage");
if(loginPageRedirectHeader && loginPageRedirectHeader !== ""){
window.location.replace(loginPageRedirectHeader);
}
}
此外,您可能希望将用户重定向到给定的in头URL。所以最后看起来是这样的:
$.ajax({
//.... other definition
complete:function(xmlHttp){
if(xmlHttp.status.toString()[0]=='3'){
top.location.href = xmlHttp.getResponseHeader('Location');
}
});
UPD:Opps。有相同的任务,但不起作用。做这些事。找到解决方案后,我会向您展示。在servlet中,您应该放置
response.setStatus(response.SC\u永久移动)代码>
要发送重定向所需的“301”xmlHttp状态
在$.ajax函数中,您不应该使用.toString()
函数…,只要
if(xmlHttp.status==301){
top.location.href='xxxx.jsp';
}
问题是它不是很灵活,你无法决定要重定向到哪里
通过servlet重定向应该是最好的方法。但是我仍然找不到正确的方法。没有浏览器能够正确处理301和302响应。事实上,标准甚至说他们应该“透明地”处理它们,这对于Ajax库供应商来说是一个巨大的难题。在年,我们被迫使用HTTP响应状态代码278(只是一些“未使用”的成功代码)来透明地处理来自服务器的重定向
这真的让我很恼火,如果这里有人对W3C有一些“吸引力”,我会很感激你能让W3C知道我们真的需要自己处理301和302代码…!;) 最终实现的解决方案是为Ajax调用的回调函数使用包装器,并在这个包装器中检查返回的HTML块上是否存在特定元素。如果找到元素,则包装器执行重定向。如果没有,包装器将调用转发给实际的回调函数
例如,我们的包装函数类似于:
function cbWrapper(data, funct){
if($("#myForm", data).length > 0)
top.location.href="login.htm";//redirection
else
funct(data);
}
$.post("myAjaxHandler",
{
param1: foo,
param2: bar
},
function(data){
cbWrapper(data, myActualCB);
},
"html"
);
$.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);
}
}
});
然后,在进行Ajax调用时,我们使用了如下内容:
function cbWrapper(data, funct){
if($("#myForm", data).length > 0)
top.location.href="login.htm";//redirection
else
funct(data);
}
$.post("myAjaxHandler",
{
param1: foo,
param2: bar
},
function(data){
cbWrapper(data, myActualCB);
},
"html"
);
$.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);
}
}
});
这对我们来说是有效的,因为所有Ajax调用总是在一个DIV元素中返回HTML,我们用它来替换页面的一部分。此外,我们只需要重定向到登录页面。我通过以下方法解决了此问题:
将自定义标头添加到响应:
public ActionResult Index(){
if (!HttpContext.User.Identity.IsAuthenticated)
{
HttpContext.Response.AddHeader("REQUIRES_AUTH","1");
}
return View();
}
将JavaScript函数绑定到事件并检查标头是否存在:
$(document).ajaxSuccess(function(event, request, settings) {
if (request.getResponseHeader('REQUIRES_AUTH') === '1') {
window.location = '/';
}
});
把弗拉基米尔·普鲁德尼科夫和托马斯·汉森的话放在一起:
- 更改服务器端代码以检测它是否是XHR。如果是,则将重定向的响应代码设置为278。
在django:
这使得浏览器将响应视为成功,并将其交给Javascript
- 在JS中,确保表单提交是通过Ajax进行的,检查响应代码并根据需要重定向:
我阅读了这个问题,并实现了关于将响应HTTP状态代码设置为278的方法,以避免浏览器透明地处理重定向。尽管这样做有效,但我还是有点不满意,因为这有点像黑客
在进行了更多的挖掘之后,我放弃了这种方法并使用了。在这种情况下,对AJAX请求的所有响应的状态代码都是200,响应的主体包含一个在服务器上构造的JSON对象。然后,客户端上的JavaScript可以使用JSON对象来决定它需要做什么
我和你有类似的问题。我执行一个AJAX请求,该请求有两种可能的响应:一种将浏览器重定向到新页面,另一种将当前页面上的现有HTML表单替换为新表单。执行此操作的jQuery代码如下所示:
function cbWrapper(data, funct){
if($("#myForm", data).length > 0)
top.location.href="login.htm";//redirection
else
funct(data);
}
$.post("myAjaxHandler",
{
param1: foo,
param2: bar
},
function(data){
cbWrapper(data, myActualCB);
},
"html"
);
$.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);
}
}
});
JSON对象“data”在服务器上构造为有两个成员:data.redirect
和data.form
。我发现这种方法要好得多。我只是想抓住整个页面的任何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");
}
我有一个简单的解决方案,适合我,不需要更改服务器代码…只需添加一茶匙肉豆蔻
$(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 );
};
});
});
$(文档).ready(函数()
{
$(文档).ajaxSend(
功能(事件、请求、设置)
{
var intercepted_success=settings.success;
settings.success=功能(a、b、c)
{
if(request.responseText.indexOf(“”>-1)
window.location=window.location;
其他的
拦截成功(a、b、c);
};
});
});
我检查html标记是否存在,但您可以更改indexOf以搜索登录页面中存在的任何唯一字符串…试试看
$(document).ready(function () {
if ($("#site").length > 0) {
window.location = "<%= Url.Content("~") %>" + "Login/LogOn";
}
});
$(文档).ready(函数(){
如果($(“#站点”)。长度>0){
window.location=”“+“登录/登录”;
}
});
把它放在登录页面上。如果它被加载到主页上的div中,它将重定向到登录页面。“#site”是一个div的id,它位于除登录页面之外的所有页面上。我喜欢Timmerz的方法,不过有点柠檬味。如果您在期待JSON时返回contentType的text/html,您很可能被重定向。在我的例子中,我只需重新加载页面,它就会被重定向到登录页面。哦,检查一下
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
$('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;
}
}
}
// 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);
}
$(document).ajaxComplete(function(e, xhr, settings){
if(xhr.status === 302){
//check for location header and redirect...
}
});
if(xhr.status === 200){
var loginPageRedirectHeader = xhr.getResponseHeader("LoginPage");
if(loginPageRedirectHeader && loginPageRedirectHeader !== ""){
window.location.replace(loginPageRedirectHeader);
}
}
$('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';
}
});
<% HttpSession ses = request.getSession(true);
String temp=request.getAttribute("what_you_defined"); %>
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;
}
$.ajaxSetup({
beforeSend: checkPulse,
error: function (XMLHttpRequest, textStatus, errorThrown) {
document.open();
document.write(XMLHttpRequest.responseText);
document.close();
}
});
[Authorize]
public virtual void CheckPulse() {}
protected void Application_EndRequest()
{
if (Context.Response.StatusCode == 302
&& (new HttpContextWrapper(Context)).Request.IsAjaxRequest())
{
Context.Response.StatusCode = 200;
Context.Response.AddHeader("REQUIRES_AUTH", "1");
}
}
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;
}
}
});
}
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"));
}
}
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;
}
}
$(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);
}
});
$.ajaxSetup({
statusCode : {
400 : function () {
window.location = "/";
}
}
});
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);
}
}
@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());
}
}
}
$.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);
}
};
});
$.ajaxSetup({
dataFilter: function (data, type) {
if (data && typeof data == "string") {
if (data.indexOf('window.location') > -1) {
eval(data);
}
}
return data;
}
});
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);
}
}
}
<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>
$( document ).ajaxError(function( event, jqxhr, settings, thrownError ) {
if ( jqxhr.status === 403 ) {
window.location = "login.jsp";
} else {
if(thrownError != null) {
alert(thrownError);
} else {
alert("error");
}
}
});
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");
// }
});
status: 204 No Content
x-status: 308 Document Redirect
x-location: /login.html