Grails:用户在ajax请求运行时注销

时间:2014-06-10 09:49:49

标签: ajax grails spring-security

有一个带有Spring Security Core插件的Grails(v.2.3.2)Web应用程序(v.2.0-RC2)。

我偶然发现了在后台运行ajax请求时注销的用户的问题。

方案如下:

  1. 用户请求网页
  2. 当页面准备就绪时,我会发出ajax请求
  3. 用户在服务器端仍在处理ajax请求时注销
  4. 当然,服务器端在很大程度上取决于当前用户,并且应用程序在第三步时崩溃,因为当前用户突然消失,因为springSecurityService表示用户未登录。

    这是我用来获取UserService中的当前用户的代码。

    public User getLoggedInUser() {
        if (!springSecurityService.isLoggedIn()) {
            return null
        }
    
        User user = User.get(springSecurityService.getPrincipal().id)
        user
    }
    

    其中,返回当前用户,直到用户退出为止,导致问题。

    我提出了使UserService有状态并将当前用户存储在单独字段中的想法。

    static scope = 'request' // create a new instance for every request
    
    private Long currentUserId = null
    
    public User getLoggedInUser() {
        if (!currentUserId) {
            if (!springSecurityService.isLoggedIn()) {
                return null
            }
    
            // Store the ID of the current user in the instance variable.
            currentUserId = springSecurityService.getPrincipal().id
        }
    
        // Fetch and return the user.
        return User.get(currentUserId)
    }
    

    此外,我创建了一个新的Spring bean,它为我的UserService定义了一个代理对象。

    userServiceProxy(ScopedProxyFactoryBean) {
        targetBeanName = 'userService'
        proxyTargetClass = true
    }
    

    现在,这适用于大多数情况,但在没有Web请求时会失败。特别是在BootStrap.groovy中,我使用了我的应用程序的其他服务。

    这是我收到的错误消息:

      

    初始化应用程序时出错:创建名为'scopedTarget.userServiceProxy'的bean时出错:当前线程的作用域'请求'无效;考虑为这个bean定义一个范围代理,如果你想从一个单例引用它;嵌套异常是java.lang.IllegalStateException:找不到线程绑定请求:您是指在实际Web请求之外的请求属性,还是在最初接收线程之外处理请求?如果您实际上是在Web请求中操作并仍然收到此消息,则您的代码可能在DispatcherServlet / DispatcherPortlet之外运行:在这种情况下,请使用RequestContextListener或RequestContextFilter来公开当前请求。

    有关如何解决此问题的任何建议吗?

1 个答案:

答案 0 :(得分:0)

经过一番调查和大量的咒骂后,终于找到了解决方案。

这是我在BootStrap.groovy中用来模仿正在进行的网络请求的代码。

class BootStrap {

    def init = { ServletContext servletContext ->

        // Mock request and response.
        HttpServletRequest request = new MockHttpServletRequest(servletContext)
        HttpServletResponse response = new MockHttpServletResponse()

        // Now store them in the current thread.
        GrailsWebRequest grailsRequest = new GrailsWebRequest(request, response, servletContext)
        WebUtils.storeGrailsWebRequest(grailsRequest)

        /**
         * Perform whatever you need to do that requires an active web request.
         */

    }
}