【问题标题】:Grails & Spring Security - Saved request - Empty parameters and unbound command objectGrails & Spring Security - 保存的请求 - 空参数和未绑定的命令对象
【发布时间】:2014-09-07 09:28:57
【问题描述】:

我有一个控制器,它接受POST 的表单。控制器的这个方法/动作受 Spring Security 保护。在这种情况下,用户的会话已过期,他们单击提交按钮。

Spring 安全性正在创建一个保存的请求并将用户重定向到登录页面。登录后,Spring Security 将重定向到表单的 POST url。但是,控制器方法/动作中的参数为空(控制器和动作名称除外),并且命令对象未填充。

使用onInteractiveAuthenticationEvent 中的一些简单代码,我可以看到保存的请求具有参数映射中的所有参数。

grails.plugins.springsecurity.onInteractiveAuthenticationSuccessEvent = { e, appCtx ->

    def request = org.codehaus.groovy.grails.plugins.springsecurity.SecurityRequestHolder.getRequest()
    def response = org.codehaus.groovy.grails.plugins.springsecurity.SecurityRequestHolder.getResponse()
    org.springframework.security.web.savedrequest.SavedRequest savedRequest = new org.springframework.security.web.savedrequest.HttpSessionRequestCache().getRequest(request, response);

    println savedRequest
    if (savedRequest) {
        savedRequest.getParameterMap().each { k, v ->
            println "${k}: ${v}"
        }
    }
}

关于为什么控制器操作/方法的参数和命令对象为空且未绑定的任何想法?我希望在成功登录后,保存的请求将用于填充两个参数,然后依次将命令绑定到参数。

我已经使用 Grails 2.0.4、Spring Security Core Plugin 1.2.7.3 以及 Grails 2.4.2 和 Spring Security Core Plugin 2.0-RC3 对此进行了测试。

【问题讨论】:

  • 命令对象只会填充当前请求中的任何内容。我不知道 Spring 安全性对保存的请求做了什么,但显然它没有从中检索请求参数以在启动重定向时重用。
  • @JeffScottBrown 同意,这就是问题所在。从我对 Spring Security 的理解来看,似乎应该如此。我猜我可能不得不拆开 Spring Security 和 Grails 插件,并找出为什么这不会发生,除非有人能指出我另一个方向(我希望)。
  • 我这里有同样的问题,我在这里创建了一个问题:jira.grails.org/browse/GPSPRINGSECURITYCORE-297
  • @Erik 我最终创建了一个过滤器,该过滤器将在登录时拦截保存的参数并将它们存储在辅助会话变量中,然后在到达该页面时填充参数。如果您愿意,我可以添加此示例作为答案。我知道我可以使用 Spring Security 过滤器链来完成它,但我需要继续做更重要的事情并选择使用 Grails 过滤器来处理这个问题。
  • 您好 Joshua,感谢您的帮助。我现在通过在 GET 中转换表单来解决它,并在操作中再次创建命令。

标签: spring grails spring-security


【解决方案1】:

由于这似乎留给您(Spring Security 的用户)来实现,我决定使用 Grails 过滤器来实现。我知道它可以使用 Spring Security 过滤器实现并放置在过滤器链中(如 Spring Security API 文档所示),但我需要继续做其他事情。

所以,这是我所做的一个例子。

package com.example

class SavedRequestFilters {

    def filters = {
        // only after a login/auth check to see if there are any saved parameters
        savedRequestCheck(controller: 'login', action: 'auth') {
            after = {
                org.springframework.security.web.savedrequest.SavedRequest savedRequest = new org.springframework.security.web.savedrequest.HttpSessionRequestCache().getRequest(request, response)
                if (savedRequest) {
                    // store the parameters and target uri into the session for later use
                    session['savedRequestParams'] = [
                        uri: savedRequest.getRedirectUrl(),
                        data: savedRequest.getParameterMap()
                    ]
                }
            }
        }

        all(controller:'*', action:'*') {
            before = {
                // if the session contains dr saved request parameters
                if (session['savedRequestParams']) {
                    def savedRequestParams = session['savedRequestParams']
                    // only if the target uri is the current will the params be needed
                    if (savedRequestParams.uri.indexOf("/${controllerName}/") > -1) {
                        savedRequestParams.data.each { k, v ->
                            params[k] = v.join(",")
                        }
                        // clear the session storage
                        session['savedRequestParams'] = null
                    }
                }
            }
        }
    }
}

【讨论】:

  • 如果参数是从多部分表单发送的,我们如何获取它们?
  • 我不知道。我似乎记得savedRequestParams 不支持多部分表单,尽管您应该去探索它的源代码以确保它。
猜你喜欢
  • 1970-01-01
  • 2015-12-12
  • 1970-01-01
  • 2011-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-20
相关资源
最近更新 更多