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

标签 ajax grails spring-security

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

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

场景如下:

  • 用户请求网页
  • 页面准备就绪后,我会触发ajax请求
  • 当服务器端仍在处理ajax请求时,用户注销

  • 当然,服务器端很大程度上取决于当前用户,并且应用程序崩溃了,因为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中,我在其中使用应用程序的其他服务。

    这是我收到的错误消息:

    Error initializing the application: Error creating bean with name 'scopedTarget.userServiceProxy': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.



    对于如何解决这个问题,有任何的建议吗?

    最佳答案

    经过一番调查和许多wear骂的话,终于找到了解决方案。

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

    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.
             */
    
        }
    }
    

    关于ajax - Grails:运行ajax请求时用户注销,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24137879/

    相关文章:

    jquery - 读取从 MVC View 模型创建的 JSON 对象

    javascript - React中ajax后计数

    java - Spring 登录将我重定向到登录页面,即使我看到的页面不 protected

    java - Spring Data Redis 和 Spring Security Data 依赖冲突

    java - 使用 Spring ACL 3 保护域对象

    javascript - 淡出功能以及 slidetoggle 功能

    jquery - 来自ajax post调用的json解析错误

    grails - 使用Fields插件2.0.2时呈现不带千位分隔符的Integer的最简单方法

    grails - 每当某些服务发生故障时,在 Grails View 顶部显示状态消息

    mysql - Grails bootstrap 有时无法保存