有一个带有Spring Security Core插件(v.2.0-RC2)的Grails(v.2.3.2)Web应用程序。
我偶然发现在后台运行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/