Logout Grails Spring安全Rest注销

Logout Grails Spring安全Rest注销,logout,grails-3.0,spring-security-rest,Logout,Grails 3.0,Spring Security Rest,我正在使用Grails3.1.4和SpringSecurityREST插件2.0.0.M2来实现一个带有AngularJS的单页应用程序。 登录和验证工作得非常好,但当我调用logout时,会出现404错误 调试时,插件RestLogoutFilter中出现异常: try { log.debug "Trying to remove the token" tokenStorageService.removeToken accessToken.accessToken } catch

我正在使用Grails3.1.4和SpringSecurityREST插件2.0.0.M2来实现一个带有AngularJS的单页应用程序。 登录和验证工作得非常好,但当我调用logout时,会出现404错误

调试时,插件RestLogoutFilter中出现异常:

try {
    log.debug "Trying to remove the token"
    tokenStorageService.removeToken accessToken.accessToken
} catch (TokenNotFoundException tnfe) {
    servletResponse.sendError HttpServletResponse.SC_NOT_FOUND, "Token not found"
}
例外情况:

grails.plugin.springsecurity.rest.token.storage.TokenNotFoundException: 
Token eyJh... cannot be removed as this is a stateless implementation
召唤

tokenStorageService.loadUserByToken(accessToken.accessToken)
有效,因此令牌肯定在令牌存储中

我的Spring安全配置是

grails.plugin.springsecurity.userLookup.userDomainClassName = 'myapp.User'
grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'myapp.UserRole'
grails.plugin.springsecurity.authority.className = 'myapp.Role'
grails.plugin.springsecurity.userLookup.usernamePropertyName='email'
grails.plugin.springsecurity.rest.login.usernamePropertyName='email'
grails.plugin.springsecurity.rest.token.storage.gorm.usernamePropertyName='email'
grails.plugin.springsecurity.rest.logout.endpointUrl = '/api/logout'
grails.plugin.springsecurity.controllerAnnotations.staticRules = [
        [pattern: '/',               access: ['permitAll']],
        [pattern: '/error',          access: ['permitAll']],
        [pattern: '/index',          access: ['permitAll']],
        [pattern: '/index.gsp',      access: ['permitAll']],
        [pattern: '/shutdown',       access: ['permitAll']],
        [pattern: '/assets/**',      access: ['permitAll']],
        [pattern: '/**/js/**',       access: ['permitAll']],
        [pattern: '/**/css/**',      access: ['permitAll']],
        [pattern: '/**/images/**',   access: ['permitAll']],
        [pattern: '/**/favicon.ico', access: ['permitAll']],
        [pattern: '/api/logout',     access: ['isAuthenticated()']]
]

grails.plugin.springsecurity.filterChain.chainMap = [
        [pattern: '/assets/**',      filters: 'none'],
        [pattern: '/**/js/**',       filters: 'none'],
        [pattern: '/**/css/**',      filters: 'none'],
        [pattern: '/**/images/**',   filters: 'none'],
        [pattern: '/**/favicon.ico', filters: 'none'],
        [pattern: '/api/**',       filters: 'JOINED_FILTERS,-anonymousAuthenticationFilter,-exceptionTranslationFilter,-authenticationProcessingFilter,-securityContextPersistenceFilter,-rememberMeAuthenticationFilter']
]

我的配置中是否有错误或其他错误?

在提问几分钟后找到了答案

Spring Security Rest声明:

使用JWT令牌(默认策略)时无法注销,因为服务器中不保留任何状态。如果仍然希望注销,可以通过创建JwtTokenStorageService的子类并重写storeToken和removeToken方法来提供自己的实现。 然后,在resources.groovy中将您的实现注册为tokenStorageService

然而,更合理的方法是从客户端(例如浏览器的本地存储)移除令牌,让令牌过期(它们无论如何都会过期,不像其他存储,如Memcached或Redis,每次访问时都会刷新)


因此,如果使用JWT进行授权,只需删除客户端上的令牌就足够了。

您是否有任何教程介绍如何实现第一个建议;“如果您仍然希望注销,可以通过创建JwtTokenStorageService的子类并重写storeToken和removeToken方法来提供自己的实现。然后,在resources.groovy中将您的实现注册为tokenStorageService。”不,我没有,但基本思想很简单。您可以创建一个类似于
CustomJwtTokenStorageService
的类,并从
JwtTokenStorageService
派生它。然后实现一些存储和删除机制,并在resources.groovy中注册新服务,如下所述。需要了解的重要一点是,JWT令牌实际上并没有保存在服务器上,因此不需要以这种方式实现注销机制,在客户端上删除令牌就足够了。