Grails Spring 安全插件 AJAX 身份验证

Posted

技术标签:

【中文标题】Grails Spring 安全插件 AJAX 身份验证【英文标题】:Grails spring security plugin AJAX authentication 【发布时间】:2012-11-30 18:36:41 【问题描述】:

我一直在寻找这个问题的答案。我希望能够使用将验证身份验证的 spring 安全核心插件在 Grails 应用程序中发送 JSON 数据。我似乎无法让它工作。

我正在尝试使用 cURL 和以下命令对此进行测试:

curl -v -H "Content-Type: application/json" -X POST --data @ajax_login.json http://localhost:8080/j_spring_security_check?ajax=true

我的 ajax_login.json 看起来像这样:


    "j_username":"user@email.com",
    "j_password":"password"

我的回复是这样的:

* About to connect() to localhost port 8080 (#0)
*   Trying 127.0.0.1... connected
* Connected to localhost (127.0.0.1) port 8080 (#0)
> POST /j_spring_security_check?ajax=true HTTP/1.1
> User-Agent: curl/7.21.4 (universal-apple-darwin11.0) libcurl/7.21.4 OpenSSL/0.9.8r zlib/1.2.5
> Host: localhost:8080
> Accept: */*
> Content-Type: application/json
> Content-Length: 63
> 
< HTTP/1.1 302 Moved Temporarily
< Server: Apache-Coyote/1.1
< Set-Cookie: JSESSIONID=974763464D383CD90962E8933DBB8335; Path=/
< Set-Cookie: grails_remember_me=""; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Path=/
< Location: http://localhost:8080/login/authfail;jsessionid=974763464D383CD90962E8933DBB8335?ajax=true
< Content-Length: 0
< Date: Wed, 12 Dec 2012 22:53:27 GMT
< 
* Connection #0 to host localhost left intact
* Closing connection #0

我希望根据 LoginController 的 ajaxSuccess 操作看到类似的内容:


    "success":true,
    "username":"user@email.com"

或者至少是每个 LoginController 的 ajaxfail 操作的失败 JSON:


    "error":"#yourdoingitwrong"

仅供参考,我的 config.groovy 有这个:

grails.plugins.springsecurity.interceptUrlMap = [
  '/css/**':    ['IS_AUTHENTICATED_ANONYMOUSLY'],
  '/common.css':  ['IS_AUTHENTICATED_ANONYMOUSLY'],
  '/favicon.ico': ['IS_AUTHENTICATED_ANONYMOUSLY'],
  '/images/**': ['IS_AUTHENTICATED_ANONYMOUSLY'],
  '/js/**':   ['IS_AUTHENTICATED_ANONYMOUSLY'],
  '/login/**':  ['IS_AUTHENTICATED_ANONYMOUSLY'],
  '/logout/**': ['IS_AUTHENTICATED_ANONYMOUSLY'],
  '/register/**': ['IS_AUTHENTICATED_ANONYMOUSLY'],
  '/error/**':  ['IS_AUTHENTICATED_ANONYMOUSLY'],
  '/**':      ['IS_AUTHENTICATED_REMEMBERED']
]

我已将 GormUserDetailsS​​ervice 子类化并重写 loadUserByUsername 以进行自己的查找,但传入的用户名是空白...空字符串。我知道这一点,因为我能够在该方法中设置断点,并且当我发送我的 cURL 命令时,执行会结束。

还有什么我遗漏的细节吗?

【问题讨论】:

Http stats 302 表示重定向。如果您尝试调用登录帖子后出现在“位置”中的 url,会发生什么?在您的示例中是:localhost:8080/login/… 【参考方案1】:

在 curl 命令中添加参数 -L 应该会有所帮助

服务器响应中的以下部分:

HTTP/1.1 302 Moved Temporarily 
Location: http://localhost:8080/login/authfail;jsessionid=974763464D383CD90962E8933DBB8335?ajax=true

告诉 curl/browser 请求的页面已移动到新位置(login/authfail)。这样服务器将客户端重定向到新的 URL。 Web 浏览器 会立即向新位置发出请求,但 curl 的默认行为不会自动跟随重定向。

参数-L/--location 指示curl 跟随重定向。有关详细信息,请参阅 ma​​n curl

【讨论】:

谢谢。这正是我所缺少的!我可以在 cURL 帮助中看到这一点,但我真的不明白为什么这是我需要的。你能解释一下添加了什么吗?【参考方案2】:

我仍然想知道如何根据请求发出 cURL 命令,但我能够通过 jQuery.ajax 成功通信:

<html>
<head>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
    <script type="text/javascript">
    $(function() 
        $('#btnPush').on('click', function() 
            $.ajax(
                url: 'http://localhost:8080/j_spring_security_check',
                type: 'POST',
                data: 
                    j_username: 'user@email.com',
                    j_password: 'password'
                ,
                success: function(data, textStatus, jqXHR) 
                    alert('Success!!!');
                ,
                error: function(jqXHR, textStatus, errorThrown) 
                    alert('Fail!');
                
            );
        );
    );
    </script>
</head>
<body>
<button id='btnPush'>Push Me!</button>
</body>
</html>

这个 HTML 文件必须包含在我的 Grails 应用程序 web-app 文件夹中。我猜这不是跨域请求。

【讨论】:

以上是关于Grails Spring 安全插件 AJAX 身份验证的主要内容,如果未能解决你的问题,请参考以下文章

Grails,从 Acegi 升级到 Spring 安全插件

grails spring安全休息插件

Grails Spring Security 插件:Getting 302 for Ajax Request for timeout Session

Groovy:使用 Grails 和 Spring 安全核心插件时出现意外令牌

Grails 3 Spring 安全插件

grails 2.4.0.M1 中的 spring 安全插件出错