Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 12884|回复: 0

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

[复制链接]
  • TA的每日心情
    奋斗
    4 天前
  • 签到天数: 792 天

    [LV.10]以坛为家III

    2049

    主题

    2107

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    723136
    发表于 2021-4-17 11:36:46 | 显示全部楼层 |阅读模式

    当我们采用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串。

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-9-18 11:05 , Processed in 0.130856 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表