zoukankan      html  css  js  c++  java
  • Ajax登陆,使用Spring Security缓存跳转到登陆前的链接

    Spring Security缓存的应用之登陆后跳转到登录前源地址

    什么意思?

    1. 用户访问网站,打开了一个链接:(origin url)起源链接
    2. 请求发送给服务器,服务器判断用户请求了受保护的资源。
    3. 由于用户没有登录,服务器重定向到登录页面:/login
    4. 填写表单,点击登录
    5. 浏览器将用户名密码以表单形式发送给服务器
    6. 服务器验证用户名密码。成功,进入到下一步。否则要求用户重新认证(第三步)
    7. 服务器对用户拥有的权限(角色)判定。有权限,重定向到origin url; 权限不足,返回状态码403( “禁止”)。

    从第3步,我们可以知道,用户的请求被中断了。
    用户登录成功后(第7步),会被重定向到origin url,spring security通过使用缓存的请求,使得被中断的请求能够继续执行。
    具体请看探究Spring Security缓存请求

    我这里仅讲解如何在ajax登陆后跳转到登录前的链接。

    1. 首先,如果想跳转到登陆之前的链接,我们需要拿到缓存:

    SavedRequest savedRequest = requestCache.getRequest(request, response);
    

    注意!若用户是直接访问没有权限限制的登陆页面,是不会有缓存的,也就是说savedRequest = null ,所以在使用缓存之前,我们需要做一个非null判断,也就是:

     if (savedRequest != null) {
     		// 逻辑代码
     }
    

    2. 取到登录前访问的url

    String url = savedRequest.getRedirectUrl();
    

    3. 使用hashMap建立一个对象,这是为了后续向浏览器返回json数据

     Map json = new HashMap<String, Object>();
                json.put("code", 0);
                json.put("message", "操作成功");
                json.put("url", url);
    

    可以看到这个json 对象比较简单,其中url属性是为了让浏览器端的js跳转的

    4.设置响应体编码和格式

    response.setContentType(FebsConstant.JSON_UTF8);
    

    5.向浏览器进行响应数据,这里的数据是json格式,是使用jackson工具包完成的,Maven地址:JacksonMaven地址

    response.getWriter().write(mapper.writeValueAsString(ResponseBo.ok(messsage, url)));
    

    下面是完整的Java代码:

    
    @Override
        public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
            // 不管请求哪个页面,登陆成功后仅打开指定页面index
    //        redirectStrategy.sendRedirect(request, response, "/index");
    		// 获取缓存
            SavedRequest savedRequest = requestCache.getRequest(request, response);
            // 设置响应格式和编码
            response.setContentType(FebsConstant.JSON_UTF8);
            
    		// 缓存非空判断
            if (savedRequest != null) {
                // 跳转到之前引发跳转的url
                String url = savedRequest.getRedirectUrl();
                
                String messsage = "成功";
                // 准备json
                Map json = new HashMap<String, Object>();
                json.put("code", 0);
                json.put("message", "操作成功");
                json.put("url", url);
    
                Object jsons = ResponseBo.ok(messsage, url);
                response.getWriter().write(mapper.writeValueAsString(ResponseBo.ok(messsage, url)));
            } else {
            	// 这个是没有缓存,直接跳转到默认ajax默认的页面
                response.getWriter().write(mapper.writeValueAsString(ResponseBo.ok()));
            }
        }
    

    6. 前端页面Ajax代码:

        $.ajax(
            {
                type: "post",
                url: "/login",
                // 登陆表单数据序列化
                data: $form.serialize(),
                dataType: "json",
                error: function (data, type, err) {
                    if (data.responseJSON != undefined) {
                        console.log(data.responseJSON.error != undefined);
                        console.log(JSON.stringify(data.responseJSON.error));
                        $MB.n_danger("error:" + JSON.stringify(data.responseJSON.error));
                    }
                },
                success: function (data) {
                    console.log(JSON.stringify(data));
                    alert(JSON.stringify(data));
    
                    if (data.code == 0) {
                        // 如果有url,则跳转该url
                        if (data.url != undefined) {
                            $form[0].reset();
                            window.location.href = data.url;
                        } else {
                            // 重置表单的输入框内容
                            $form[0].reset();
                            window.location.href = '/index';
                            // $form.attr("action", '/index');
                        }
    
                    } else {
                        // if (r.msg !== '验证码不能为空!') reloadCode();
                        console.log(data.message);
                    }
                },
            }
        );
    

    7.不出意外的话,浏览器会收到下面的数据:

    {"code":0,"message":"操作成功"}
    

    如果你也收到了这条数据,说明已经成功了。

  • 相关阅读:
    Yield Usage Understanding
    Deadclock on calling async methond
    How to generate file name according to datetime in bat command
    Run Unit API Testing Which Was Distributed To Multiple Test Agents
    druid的关键参数+数据库连接池运行原理
    修改idea打开新窗口的默认配置
    spring boot -thymeleaf-url
    @pathvariable和@RequestParam的区别
    spring boot -thymeleaf-域对象操作
    spring boot -thymeleaf-遍历list和map
  • 原文地址:https://www.cnblogs.com/gobyte/p/10754273.html
Copyright © 2011-2022 走看看