我正在使用Grails 1.3.7和最新的spring-security-core插件。我在LoginController中实现了以下方法:
def authAjax = {
response.setHeader 'Location', SpringSecurityUtils.securityConfig.auth.ajaxLoginFormUrl
response.sendError HttpServletResponse.SC_UNAUTHORIZED
}
在我的全球JavaScript文件中,我有以下内容:
$.ajaxSetup({
error: function(xhr, status, err) {
if (xhr.status == 401) {
// display a login form in a dialog
}
}
});
登录表单是直接来自插件文档的标准登录表单。唯一的区别是我使用jQuery提交表单如下:
var params = $('#ajaxLoginForm').serialize();
$.post($('#ajaxLoginForm').attr('action'), params, function(jsonData) {
if (jsonData.success) {
$('#login-dialog').dialog('close');
} else {
alert('TODO: display errors');
}
}, 'json');
问题是我第一次点击登录按钮时,我似乎正在验证确定,但是从服务器返回的响应是基于Referer请求标头的302重定向。所以$ .post()的主体永远不会被运行。我正在获取HTML而不是JSON。它实际上并没有在第二次提交之前点击我的LoginController.ajaxSuccess方法。我已阅读并重新阅读文档,但我必须遗漏一些内容。
更新:看起来它可能不是Referer问题,因为第二次发布表单时,Referer仍然存在。所以我完全不知道为什么我必须提交表单两次才能调用ajaxSuccess方法。
答案 0 :(得分:6)
当您未经授权尝试访问受保护资源时,Spring Security会在您的会话中保存该请求(http://static.springsource.org/spring-security/site/apidocs/org/springframework/security/ web / savedrequest / DefaultSavedRequest.html),然后当您成功进行身份验证时,它会将您重定向到该请求。您可以使用Spring Security配置全面关闭此行为,但这可能不是您想要的大多数工作流程。您也可以在authAjax方法中明确地从会话中删除SavedRequest,但同样,这可能不是用户的最佳体验。
我认为如果没有SavedRequest重定向到insted,LoginController.ajaxSuccess只会被点击,所以你要取回的HTML应该是你原始请求的结果,当时是未经授权的。所以,诀窍是你想要使用你曾经用来处理原始请求的任何函数作为#ajaxLoginForm提交的成功方法。
答案 1 :(得分:0)
Gregg,您可能正在为401响应调整默认的servlet容器行为。我建议你使用类似的东西:
def authAjax = {
response.setHeader 'Location', SpringSecurityUtils.securityConfig.auth.ajaxLoginFormUrl
render status: 401, contentType: "application/json", {
message = "You are not authorized for this page"
}
}
我没有测试过,所以让我知道它是怎么回事。