How to handle expired session using spring-securit

2019-07-28 02:19发布

问题:

I'm using spring-security and jQuery in my application. Main page uses loading content dynamically into tabs via Ajax. And all is ok, however sometimes I've got the login page inside my tab and if I type credentials I will be redirected to the content page without tabs.

So I'd like to handle this situation. I would like to just write a global handler for all ajax responses that will do window.location.reload() if we need to authenticate.

回答1:

I'd faced the same problem. Please see the solution I adopted and check whether it is useful for you.

My log-page used a old model controller instead of spring 3.0 annotation model.

I registered a global ajax error handler as follows

jQuery(document).ajaxError(
    function(event, request, ajaxOptions, thrownError) {
        try {
            var result = getJsonObject(request.responseText);//Convert the json reply to json object
            if (result.timeout) {
                window.location.reload();
            }
        } catch (e) {
            // Ignore this error
        }
    });

Then in my log-in controller, I checks whether the original request was a ajax request or not using the x-requested-with header. If it was a ajax request then I returns a json response saying {"timeout" : true}.

private boolean isAjaxRequest(HttpServletRequest request) {
    boolean isAjaxRequest = false;

    SavedRequest savedRequest = (SavedRequest) request.getSession()
            .getAttribute(
                    DefaultSavedRequest.SPRING_SECURITY_SAVED_REQUEST_KEY);
    if (savedRequest != null) {
        List<String> ajaxHeaderValues = savedRequest
                .getHeaderValues("x-requested-with");
        for (String value : ajaxHeaderValues) {
            if (StringUtils.equalsIgnoreCase("XMLHttpRequest", value)) {
                isAjaxRequest = true;
            }
        }
    }
    return isAjaxRequest;
}

.............   
.............   
.............   

if (isAjaxRequest(request)) {
    Map<String, Object> model = new HashMap<String, Object>();
    model.put("timeout", true);
    return new ModelAndView(new JSONView(model));//Returns a json object.
} else {
    //return login page
}

Sample implementation of JSONView

import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSON;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;

import org.springframework.web.servlet.View;

import com.greytip.common.json.CougarJsonConfig;

public class JSONView implements View {
    private JSON jsonObject;
    private JsonConfig jsonConfig;
    private String value;

    public JSONView(Object value) {
        this();
        jsonObject = JSONObject.fromObject(value, jsonConfig);
    }

    public JSONView(List<?> value) {
        this();
        jsonObject = JSONArray.fromObject(value, jsonConfig);
    }

    public JSONView(String value) {
        this();
        this.value = value;
    }

    public JSONView() {
        jsonConfig = new JsonConfig();//Your json config
    }

    @SuppressWarnings("unchecked")
    public void render(Map map, HttpServletRequest request,
    HttpServletResponse response) throws Exception {
        if (jsonObject != null) {
            jsonObject.write(response.getWriter());
        }
        if (value != null) {
            response.getWriter().write(value);
        }
    }

    public String getContentType() {
        return "text/json";
    }

}

This uses the json-lib library to convert the objects to json format.

Spring 3.0 has very good support for jackson library, you can try to use it.