我正在使用Grails 2.5.0的 spring-security-rest:1.5.0.RC2 。我为用户配置文件信息UserProfileController创建了一个控制器,它扩展了RestfulController。登录工作正常以及检索用户配置文件。但是,当我尝试\ api \ logout时,我得到了
HTTP/1.1 403 Forbidden
注销时我指定了Bearer令牌,以便正确地找到用户,但似乎想要使用静态规则来确定是否允许访问注销页面,并且因为如果结束访问权限它就找不到规则被拒绝。这是由于最近版本的grails中引入的页面的悲观锁定。见下面的日志。
2015-04-20 22:44:04,252 [http-bio-8080-exec-8] DEBUG matcher.AntPathRequestMatcher - Checking match of request : '/api/logout'; against '/api/**'
2015-04-20 22:44:04,252 [http-bio-8080-exec-8] DEBUG web.FilterChainProxy - /api/logout at position 1 of 7 in additional filter chain; firing Filter: 'MutableLogoutFilter'
2015-04-20 22:44:04,252 [http-bio-8080-exec-8] DEBUG web.FilterChainProxy - /api/logout at position 2 of 7 in additional filter chain; firing Filter: 'RestAuthenticationFilter'
2015-04-20 22:44:04,252 [http-bio-8080-exec-8] DEBUG rest.RestAuthenticationFilter - Actual URI is /api/logout; endpoint URL is /api/login
2015-04-20 22:44:04,252 [http-bio-8080-exec-8] DEBUG web.FilterChainProxy - /api/logout at position 3 of 7 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2015-04-20 22:44:04,253 [http-bio-8080-exec-8] DEBUG web.FilterChainProxy - /api/logout at position 4 of 7 in additional filter chain; firing Filter: 'GrailsAnonymousAuthenticationFilter'
2015-04-20 22:44:04,253 [http-bio-8080-exec-8] DEBUG filter.GrailsAnonymousAuthenticationFilter - Populated SecurityContextHolder with anonymous token: 'grails.plugin.springsecurity.authentication.GrailsAnonymousAuthenticationToken@dc4a600: Principal: org.springframework.security.core.userdetails.User@dc730200: Username: __grails.anonymous.user__; Password: [PROTECTED]; Enabled: false; AccountNonExpired: false; credentialsNonExpired: false; AccountNonLocked: false; Granted Authorities: ROLE_ANONYMOUS; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@0: RemoteIpAddress: fe80:0:0:0:414:abd0:23ec:bb74%10; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
2015-04-20 22:44:04,253 [http-bio-8080-exec-8] DEBUG web.FilterChainProxy - /api/logout at position 5 of 7 in additional filter chain; firing Filter: 'RestTokenValidationFilter'
2015-04-20 22:44:04,253 [http-bio-8080-exec-8] DEBUG bearer.BearerTokenReader - Looking for bearer token in Authorization header, query string or Form-Encoded body parameter
2015-04-20 22:44:04,253 [http-bio-8080-exec-8] DEBUG bearer.BearerTokenReader - Found bearer token in Authorization header
2015-04-20 22:44:04,253 [http-bio-8080-exec-8] DEBUG rest.RestTokenValidationFilter - Token found: eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0Mjk1OTE0NDEsInN1YiI6InN3YXZlayIsInJvbGVzIjpbIlJPTEVfQURNSU4iLCJST0xFX1VTRVIiXSwiaWF0IjoxNDI5NTg3ODQxfQ.am7f4VaQgdRWyMzBvfyT_jAmxeOZPhlURaNjdxVS6rM
2015-04-20 22:44:04,253 [http-bio-8080-exec-8] DEBUG rest.RestTokenValidationFilter - Trying to authenticate the token
2015-04-20 22:44:04,254 [http-bio-8080-exec-8] DEBUG rest.RestAuthenticationProvider - Trying to validate token eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0Mjk1OTE0NDEsInN1YiI6InN3YXZlayIsInJvbGVzIjpbIlJPTEVfQURNSU4iLCJST0xFX1VTRVIiXSwiaWF0IjoxNDI5NTg3ODQxfQ.am7f4VaQgdRWyMzBvfyT_jAmxeOZPhlURaNjdxVS6rM
2015-04-20 22:44:04,254 [http-bio-8080-exec-8] DEBUG rest.JwtService - Parsed an HMAC signed JWT
2015-04-20 22:44:04,256 [http-bio-8080-exec-8] DEBUG jwt.JwtTokenStorageService - Successfully verified JWT
2015-04-20 22:44:04,256 [http-bio-8080-exec-8] DEBUG rest.JwtService - Parsed an HMAC signed JWT
2015-04-20 22:44:04,257 [http-bio-8080-exec-8] DEBUG rest.RestAuthenticationProvider - Now is Mon Apr 20 22:44:04 CDT 2015 and token expires at Mon Apr 20 23:44:01 CDT 2015
2015-04-20 22:44:04,257 [http-bio-8080-exec-8] DEBUG rest.RestAuthenticationProvider - Expiration: 56
2015-04-20 22:44:04,258 [http-bio-8080-exec-8] DEBUG rest.RestAuthenticationProvider - Authentication result: grails.plugin.springsecurity.rest.token.AccessToken(accessToken:eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0Mjk1OTE0NDEsInN1YiI6InN3YXZlayIsInJvbGVzIjpbIlJPTEVfQURNSU4iLCJST0xFX1VTRVIiXSwiaWF0IjoxNDI5NTg3ODQxfQ.am7f4VaQgdRWyMzBvfyT_jAmxeOZPhlURaNjdxVS6rM, expiration:56, refreshToken:null, principal:org.springframework.security.core.userdetails.User@caf81bff: Username: swavek; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER, super:grails.plugin.springsecurity.rest.token.AccessToken@31b92fe9: Principal: org.springframework.security.core.userdetails.User@caf81bff: Username: swavek; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_ADMIN, ROLE_USER)
2015-04-20 22:44:04,258 [http-bio-8080-exec-8] DEBUG rest.RestTokenValidationFilter - Token authenticated. Storing the authentication result in the security context
2015-04-20 22:44:04,258 [http-bio-8080-exec-8] DEBUG rest.RestTokenValidationFilter - Authentication result: grails.plugin.springsecurity.rest.token.AccessToken(accessToken:eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0Mjk1OTE0NDEsInN1YiI6InN3YXZlayIsInJvbGVzIjpbIlJPTEVfQURNSU4iLCJST0xFX1VTRVIiXSwiaWF0IjoxNDI5NTg3ODQxfQ.am7f4VaQgdRWyMzBvfyT_jAmxeOZPhlURaNjdxVS6rM, expiration:56, refreshToken:null, principal:org.springframework.security.core.userdetails.User@caf81bff: Username: swavek; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER, super:grails.plugin.springsecurity.rest.token.AccessToken@31b92fe9: Principal: org.springframework.security.core.userdetails.User@caf81bff: Username: swavek; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_ADMIN, ROLE_USER)
2015-04-20 22:44:04,259 [http-bio-8080-exec-8] DEBUG rest.RestTokenValidationFilter - Continuing the filter chain
2015-04-20 22:44:04,259 [http-bio-8080-exec-8] DEBUG web.FilterChainProxy - /api/logout at position 6 of 7 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2015-04-20 22:44:04,259 [http-bio-8080-exec-8] DEBUG web.FilterChainProxy - /api/logout at position 7 of 7 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2015-04-20 22:44:04,260 [http-bio-8080-exec-8] DEBUG intercept.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /api/logout; Attributes: [_DENY_]
2015-04-20 22:44:04,260 [http-bio-8080-exec-8] DEBUG intercept.FilterSecurityInterceptor - Previously Authenticated: grails.plugin.springsecurity.rest.token.AccessToken(accessToken:eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0Mjk1OTE0NDEsInN1YiI6InN3YXZlayIsInJvbGVzIjpbIlJPTEVfQURNSU4iLCJST0xFX1VTRVIiXSwiaWF0IjoxNDI5NTg3ODQxfQ.am7f4VaQgdRWyMzBvfyT_jAmxeOZPhlURaNjdxVS6rM, expiration:56, refreshToken:null, principal:org.springframework.security.core.userdetails.User@caf81bff: Username: swavek; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER, super:grails.plugin.springsecurity.rest.token.AccessToken@31b92fe9: Principal: org.springframework.security.core.userdetails.User@caf81bff: Username: swavek; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_ADMIN, ROLE_USER)
2015-04-20 22:44:04,260 [http-bio-8080-exec-8] DEBUG hierarchicalroles.RoleHierarchyImpl - getReachableGrantedAuthorities() - From the roles [ROLE_ADMIN, ROLE_USER] one can reach [ROLE_ADMIN, ROLE_USER] in zero or more steps.
2015-04-20 22:44:04,261 [http-bio-8080-exec-8] DEBUG access.ExceptionTranslationFilter - Access is denied (user is not anonymous); delegating to AccessDeniedHandler
Config.groovy中的我的controllerAnnotations.staticRules没有指定任何\ api **
我的filterChain.chainMap看起来像这样
grails.plugin.springsecurity.filterChain.chainMap = [
'/api/**': 'JOINED_FILTERS,-exceptionTranslationFilter,-authenticationProcessingFilter,-securityContextPersistenceFilter,-rememberMeAuthenticationFilter', // Stateless chain
'/**': 'JOINED_FILTERS,-restTokenValidationFilter,-restExceptionTranslationFilter' // Traditional chain
]
实现它的控制器的注销方法有哪些安全注释?我怎样才能做到这一点?
谢谢
答案 0 :(得分:1)
首先,RestLogoutFilter
不在链中。但即便如此,使用JWT时也没有注销功能。引用documentation:
使用JWT令牌(默认策略)时无法注销,因为服务器中没有保留任何状态。如果您仍想要注销,则可以通过创建
JwtTokenStorageService
的子类并覆盖方法storeToken
和removeToken
来提供自己的实现。 然后,在resources.groovy
tokenStorageService
注册您的实施。然而,更合理的方法是从客户端删除令牌(例如,浏览器的本地存储)并让令牌过期(无论如何它们将过期,与其他存储如Memcached或Redis不同每次访问都会刷新。