基于Spring Security的AJAX请求需要登录的解决方案


当我们采用SpringSecurity进行安全控制时,除了正常的基于浏览器地址栏的请求URL安全拦截之外,还会经常遇到AJAX调用受权限拦 截的请求时返回值不能处理的情况,按照默认的配置,如果AJAX请求的url需要用户登录而用户未登录或者会话已过期了,这时会被自动拦截并转到登录界面 进行登录,这时,ajax请求实际上是返回了登录页面的html代码,这个代码是不能进行json处理的。经过实验,可以有两个思路:

1、登录页面设置为某个 .do页面,在这个页面中做检验:

boolean isAjax = "XMLHttpRequest".equals(request.getHeader("X-Requested-With")); 
        //如果是ajax请求  
        if (isAjax) {         
            String jsonObject = "{\"success\":false,\"isLoginRequired\":true}";  
            String contentType = "application/json";  
            response.setContentType(contentType);  
            response.setCharacterEncoding("UTF-8");
            PrintWriter out = response.getWriter();  
            out.print(jsonObject);  
            out.flush();  
            out.close();  
            return;  
        }

判断如果是ajax过来的请求,则返回一个json格式的字符串,用于前台处理。  前台如果是采用了jquery,可以扩展ajax请求,拦截所有的ajax请求的返回结果,进行全局处理:

(function($) {
    // 备份jquery的ajax方法
    var _ajax = $.ajax;

    // 重写jquery的ajax方法
    $.ajax = function(opt) {
        // 备份opt中error和success方法
        var fn = {
            error : function(XMLHttpRequest, textStatus, errorThrown) {
            },
            success : function(data, textStatus) {
            }
        };
        if (opt.error) {
            fn.error = opt.error;
        }
        if (opt.success) {
            fn.success = opt.success;
        }

        // 扩展增强处理
        var _opt = $.extend(opt, {
            error : function(XMLHttpRequest, textStatus, errorThrown) {
                // 错误方法增强处理
                fn.error(XMLHttpRequest, textStatus, errorThrown);
            },
            success : function(data, textStatus) {
                // 成功回调方法增强处理
                if(data){
                    if (!data.success && data.isLoginRequired) {
                        showLoginWindow();
                    } else {
                        fn.success(data, textStatus);
                    }
                }


            }
        });
        _ajax(_opt);
    };
})(jQuery);

function showLoginWindow() {
    alert("请登录");  //可根据需要定制
}

这种方式有一个不太好的地方:ajax全局拦截之后,提示登录,然后就不会向下走了,这时如果弹出用户登录框进行登录,则用户登录成功之后,以前的操作不会继续执行了,用户需要重新再去操作一下。

2、 还有一种方案,原理类似: 在安全中配置一个<access-denied-handler ref="accessDeniedHandler"/>, 但这个是存取拒绝的拦截处理,如果用户还未登录,是不会被拦截的,可以考虑在用户匿名访问时,默认创建一个特殊的用户对象,这个用户权限是很低的,没有普 通用户的权限,比如ROLE_USER,而我们一般会配置有权限的资源要求最低是有ROLE_USER角色也就是普通用户身份,这样,当用户请求这个资源 时,会被安全拒绝,通常默认是转到403错误页面,如果配置了access-denied-handler,那么也可以转到这个handler配置的一 个.do上去,再在这个do中按照上面的方法进行判断处理。

这个方案不好的地方在于,不存在匿名用户的说法了,因为通过用户上下文来获取当前用户时,肯定会得到一个User对象。在这个handler中,需要处理用户是否登录的情况,如果未登录,则转到登录页面进行登录,如果已登录,则转到真正的403页面,或者json串。

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM