Grails Spring Security AJAX使用请求页面的HTML响应,而不是来自ajaxSuccess()的JSON

cha*_*ead 6 ajax grails spring-security

所以我一直在玩Grails的Spring Security,我度过了一段美好的时光,但我仍然坚持通过AJAX登录一件小事.我有一个登录表格,/j_spring_security_check通过AJAX发布,以便登录,它工作得很好,但当我直接进入登录页面时,我感到困惑的是,2)当我被重定向到登录时我尝试访问安全页面时的页面.登录页面是/login/auth,我用auth.gspAJAXified表单替换了标准表单.以下是两种情况:

  1. 我浏览到/login/auth直接,当我这样做,并登录使用AJAX我得到的标准JSON对象回来了,这是我得到的东西像{"success":true,"username":"charles"}{"error":"Sorry, we were not able to find a user with that username and password."}-没有惊喜-一切都很好.
  2. 由于/login/auth当我浏览到/users/list我的应用程序中的另一个控制器/操作(例如)并且我未经过身份验证时,我是"登录"页面,我会/login/auth按预期重定向到.因此,当我输入伪造凭证时,我会{"error":"Sorry, we were not able to find a user with that username and password."}按预期返回,但是当我使用正确的凭据登录时,我会在响应正文中找回最初请求的页面的实际HTML.理想情况下,我希望得到类似的东西{"success":true,"username":"charles", referer:"/users/list"}- 这样我的登录表单可以做很酷的动画片,然后重定向到最初请求的URL.我看这是怎么回事,在情况1号ajaxSuccess()LoginController.groovy被调用(返回JSON) -但在这种情况下,它不会叫,我无法找出是什么被调用,这样我可以破解它做什么我想要.

有一个更好的方法吗?或者有人能指出我正确的方向吗?我非常感谢任何帮助!

非常感谢!

:)

这是我的AJAX调用,如果它有帮助,虽然它是非常标准的:

<script>
$(document).ready(function(){
    $("#submit").click(function(){
        $("#response").html("Attempting login...");
        var formdata = $('#loginForm').serialize();
        $.ajax({
            url: "/UserDemo/j_spring_security_check",
            type: 'post',
            data: formdata,
            success: function(r){
                if (r.success) {
                    $("#response").html("Success!");
                } else if (r.error) {
                    $("#response").html(r.error);
                }
            }
        });
    });
});
Run Code Online (Sandbox Code Playgroud)

Dav*_*one 0

我相信我有一个答案可以帮助你。我最近一直在研究这个问题,这是我想出的解决方案。我确信它并不完美,但它对我来说效果很好。

首先,我必须弄清楚为什么 Grails Spring Security 插件没有按预期重定向到我的 LoginController 中的 ajaxSuccess 操作(请参阅Spring Security 插件文档)。我发现该插件正在寻找标头或查询参数(请参阅github 上的 Spring Security 插件源代码。将我的凭据发布到此 URI,我能够获得重定向以转到控制器中的正确操作: /j_spring_security_check?ajax=true

其次,我更改了 LoginController.groovy 中 ajaxSuccess 操作的实现。您可以根据需要返回任何内容来支持您自己的实现。

/**
 * The Ajax success redirect url.
 */
def ajaxSuccess(){
    def currentUser = springSecurityService.principal
    [success: true, user: [id:currentUser.id, fullName:currentUser.fullName, confirmed:currentUser.confirmed, enabled:currentUser.enabled]]
}
Run Code Online (Sandbox Code Playgroud)

第三,我想使用“Accept”HTTP 标头来确定何时返回 json,以及何时让控制器渲染 GSP 视图。我创建了一个 Grails 过滤器,它会查找一些参数或标头来确定何时“jsonify”我的结果。总体思路是,我将从控制器返回模型并将其渲染为 json (或 jsonp)。我相信我从一个名为 jsonify 的插件或类似的插件中获取了这个概念。这是我在过滤器中使用的代码:

jsonify(controller: '*', action: '*') {
        after = { Map model ->
            String acceptHeader = request.getHeader('accept')

            boolean isAcceptHeaderApplicationJson = "application/json".equals(acceptHeader)
            boolean isJsonRequest = 'json'.equalsIgnoreCase(params.format?.trim()) || isAcceptHeaderApplicationJson
            boolean isJsonpRequest = StringUtils.isNotBlank(params.callback)

            if(isJsonRequest != true && isJsonpRequest != true){
                return true
            }


            // check if we can unwrap the model (such in the case of a show)
            def modelToRenderAsJson = model?.size() == 1 ? model.find { true }.value : model
            if(isJsonpRequest){
                response.setContentType('application/javascript;charset=utf-8')
                render "${params.callback}(${modelToRenderAsJson as JSON})"
            }else{
                response.setContentType('application/json;charset=utf-8')
                render modelToRenderAsJson as JSON
            }

            return false
        }
    }
Run Code Online (Sandbox Code Playgroud)

最后,我可以使用正在运行的 Grails 应用程序和名为 Postman 的 Google Chrome 插件对此进行测试。我附上了我的邮递员配置的屏幕截图,希望它能有所帮助。

邮差Ajax登录截图