有一个带有Spring Security Core插件的Grails(v.2.3.2)Web应用程序(v.2.0-RC2)。
我偶然发现了在后台运行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
中,我使用了我的应用程序的其他服务。
这是我收到的错误消息:
初始化应用程序时出错:创建名为'scopedTarget.userServiceProxy'的bean时出错:当前线程的作用域'请求'无效;考虑为这个bean定义一个范围代理,如果你想从一个单例引用它;嵌套异常是java.lang.IllegalStateException:找不到线程绑定请求:您是指在实际Web请求之外的请求属性,还是在最初接收线程之外处理请求?如果您实际上是在Web请求中操作并仍然收到此消息,则您的代码可能在DispatcherServlet / DispatcherPortlet之外运行:在这种情况下,请使用RequestContextListener或RequestContextFilter来公开当前请求。
有关如何解决此问题的任何建议吗?
答案 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.
*/
}
}