Grails Spring 安全 Rest 400 错误请求错误
Grails Spring Security Rest 400 BAD REQUEST ERROR
我一直在尝试使用 windows 中的 curl 验证 grails spring security rest url /api/login
。但不能这样做。
我总是以 400 BAD REQUEST ERROR.
结束
这些是我的配置
BuildConfig.groovy
compile ":asset-pipeline:2.5.7"
compile ":spring-security-core:2.0.0"
compile ":spring-security-rest:1.5.4", {
excludes: 'spring-security-core'
}
// plugins needed at runtime but not for compilation
runtime ":hibernate4:4.3.10" // or ":hibernate:3.6.10.18"
runtime ":database-migration:1.4.0"
runtime ":jquery:1.11.1"
runtime "org.grails.plugins:mysql-connectorj:5.1.22.1"
runtime ":cors:1.1.6"
============================================= =======================
Config.groovy
// Added by the Spring Security Core plugin:
grails.plugin.springsecurity.userLookup.userDomainClassName = 'com.aes.apprater.SecUser'
grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'com.aes.apprater.SecUserSecRole'
grails.plugin.springsecurity.authority.className = 'com.aes.apprater.SecRole'
grails.plugin.springsecurity.controllerAnnotations.staticRules = [
'/': ['permitAll'],
'/index': ['permitAll'],
'/index.gsp': ['permitAll'],
'/assets/**': ['permitAll'],
'/**/js/**': ['permitAll'],
'/**/css/**': ['permitAll'],
'/**/images/**': ['permitAll'],
'/**/favicon.ico': ['permitAll']
]
grails.plugin.springsecurity.securityConfigType = "InterceptUrlMap"
grails.plugin.springsecurity.interceptUrlMap = [
'/project/**': ['ROLE_ADMIN'],
'/appRater/**': ['ROLE_ADMIN'],
'/mobilePlatform/**': ['ROLE_ADMIN'],
'/**': ['IS_AUTHENTICATED_ANONYMOUSLY']
]
grails.plugin.springsecurity.filterChain.chainMap = [
'/api/**': 'JOINED_FILTERS,-exceptionTranslationFilter,-authenticationProcessingFilter,-securityContextPersistenceFilter,-rememberMeAuthenticationFilter', // Stateless chain
'/**': 'JOINED_FILTERS,-restTokenValidationFilter,-restExceptionTranslationFilter' // Traditional chain
]
grails.plugin.springsecurity.rest.login.active=true
grails.plugin.springsecurity.rest.login.failureStatusCode=401
grails.plugin.springsecurity.rest.token.validation.active=true
输出:
C:\Users\admin>curl -i -X POST -H "Content-Type: application/json" -d '{"usernam
e":"xxxxx", "password":"xxxx"}' http://localhost:8080/xxxx-2.0/api/login
curl: (3) [globbing] unmatched close brace/bracket in column 14
HTTP/1.1 400 Bad Request
Server: Apache-Coyote/1.1
Content-Length: 0
Date: Fri, 28 Apr 2017 09:16:44 GMT
Connection: close
调试日志:
|Loading Grails 2.5.6
|Configuring classpath
.
|Environment set to development
.................................
|Packaging Grails application
.............................................
|Running Grails application
Configuring Spring Security Core ...
... finished configuring Spring Security Core
Configuring Spring Security REST ...
... finished configuring Spring Security REST
2017-05-02 13:10:00,852 [localhost-startStop-1] DEBUG intercept.FilterSecurityInterceptor - Validated configuration attributes
2017-05-02 13:10:04,407 [localhost-startStop-1] DEBUG hierarchicalroles.RoleHierarchyImpl - setHierarchy() - The following role hierarchy was set:
2017-05-02 13:10:04,425 [localhost-startStop-1] INFO web.DefaultSecurityFilterChain - Creating filter chain: Ant [pattern='/api/**'], [grails.plugin.springsecurity.web.SecurityRequestHolderFilter@243ac73f, grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter@eef0bae, grails.plugin.springsecurity.rest.RestAuthenticationFilter@6fe7d42a, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@5d1a4acb, grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter@6924852d, grails.plugin.springsecurity.rest.RestTokenValidationFilter@5ca38348, org.springframework.security.web.access.ExceptionTranslationFilter@73001b7b, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@c0c6339]
2017-05-02 13:10:04,425 [localhost-startStop-1] INFO web.DefaultSecurityFilterChain - Creating filter chain: Ant [pattern='/**'], [grails.plugin.springsecurity.web.SecurityRequestHolderFilter@243ac73f, org.springframework.security.web.context.SecurityContextPersistenceFilter@146395d, grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter@eef0bae, grails.plugin.springsecurity.web.authentication.GrailsUsernamePasswordAuthenticationFilter@29600952, grails.plugin.springsecurity.rest.RestAuthenticationFilter@6fe7d42a, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@5d1a4acb, grails.plugin.springsecurity.web.filter.GrailsRememberMeAuthenticationFilter@6003fbb6, grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter@6924852d, org.springframework.security.web.access.ExceptionTranslationFilter@25829af9, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@c0c6339]
|Server running. Browse to http://localhost:8090/apprater-2.0
.2017-05-02 13:10:06,221 [http-bio-8090-exec-10] DEBUG web.FilterChainProxy - /index.gsp at position 3 of 10 in additional filter chain; firing Filter: 'MutableLogoutFilter'
2017-05-02 13:10:06,221 [http-bio-8090-exec-10] DEBUG web.FilterChainProxy - /index.gsp at position 4 of 10 in additional filter chain; firing Filter: 'GrailsUsernamePasswordAuthenticationFilter'
2017-05-02 13:10:06,221 [http-bio-8090-exec-10] DEBUG web.FilterChainProxy - /index.gsp at position 5 of 10 in additional filter chain; firing Filter: 'RestAuthenticationFilter'
.2017-05-02 13:10:06,285 [http-bio-8090-exec-10] DEBUG web.FilterChainProxy - /index.gsp at position 6 of 10 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2017-05-02 13:10:06,287 [http-bio-8090-exec-10] DEBUG web.FilterChainProxy - /index.gsp at position 7 of 10 in additional filter chain; firing Filter: 'GrailsRememberMeAuthenticationFilter'
2017-05-02 13:10:06,288 [http-bio-8090-exec-10] DEBUG web.FilterChainProxy - /index.gsp at position 8 of 10 in additional filter chain; firing Filter: 'GrailsAnonymousAuthenticationFilter'
.2017-05-02 13:10:06,300 [http-bio-8090-exec-10] DEBUG web.FilterChainProxy - /index.gsp reached end of additional filter chain; proceeding with original chain
.2017-05-02 13:10:07,785 [http-bio-8090-exec-10] DEBUG context.HttpSessionSecurityContextRepository - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2017-05-02 13:10:07,786 [http-bio-8090-exec-10] DEBUG context.HttpSessionSecurityContextRepository$SaveToSessionResponseWrapper - Skip invoking on
2017-05-02 13:10:07,786 [http-bio-8090-exec-10] DEBUG context.HttpSessionSecurityContextRepository$SaveToSessionResponseWrapper - Skip invoking on
2017-05-02 13:10:07,786 [http-bio-8090-exec-10] DEBUG context.HttpSessionSecurityContextRepository$SaveToSessionResponseWrapper - Skip invoking on
2017-05-02 13:10:07,788 [http-bio-8090-exec-10] DEBUG access.ExceptionTranslationFilter - Chain processed normally
2017-05-02 13:10:07,788 [http-bio-8090-exec-10] DEBUG context.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
2017-05-02 13:10:14,009 [http-bio-8090-exec-2] DEBUG matcher.AntPathRequestMatcher - Checking match of request : '/api/login'; against '/api/**'
2017-05-02 13:10:14,010 [http-bio-8090-exec-2] DEBUG web.FilterChainProxy - /api/login at position 1 of 8 in additional filter chain; firing Filter: 'SecurityRequestHolderFilter'
2017-05-02 13:10:14,010 [http-bio-8090-exec-2] DEBUG web.FilterChainProxy - /api/login at position 2 of 8 in additional filter chain; firing Filter: 'MutableLogoutFilter'
2017-05-02 13:10:14,010 [http-bio-8090-exec-2] DEBUG web.FilterChainProxy - /api/login at position 3 of 8 in additional filter chain; firing Filter: 'RestAuthenticationFilter'
终于在grails controller中写了一个测试用例,结果是curl抛出400 bad request错误。配置没有问题。下面的测试用例证明了这一点。
when: 'login with the admin'
RestBuilder rest = new RestBuilder()
def resp = rest.post("http://localhost:${serverPort}/xxx/api/login") {
accept('application/json')
contentType('application/json')
json {
username = 'xxx'
password = 'xxx'
}
}
then:
resp.status == 200
resp.json.roles.find { it == 'ROLE_ADMIN' }
when:
def accessToken = resp.json.access_token
then:
accessToken
when:
resp = rest.get("http://localhost:${serverPort}/xxx/appRaterRest/index") {
accept('application/json')
header('Authorization', "Bearer ${accessToken}" )
}
then:
resp.status == 200
我一直在尝试使用 windows 中的 curl 验证 grails spring security rest url /api/login
。但不能这样做。
我总是以 400 BAD REQUEST ERROR.
结束
这些是我的配置
BuildConfig.groovy
compile ":asset-pipeline:2.5.7"
compile ":spring-security-core:2.0.0"
compile ":spring-security-rest:1.5.4", {
excludes: 'spring-security-core'
}
// plugins needed at runtime but not for compilation
runtime ":hibernate4:4.3.10" // or ":hibernate:3.6.10.18"
runtime ":database-migration:1.4.0"
runtime ":jquery:1.11.1"
runtime "org.grails.plugins:mysql-connectorj:5.1.22.1"
runtime ":cors:1.1.6"
============================================= =======================
Config.groovy
// Added by the Spring Security Core plugin:
grails.plugin.springsecurity.userLookup.userDomainClassName = 'com.aes.apprater.SecUser'
grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'com.aes.apprater.SecUserSecRole'
grails.plugin.springsecurity.authority.className = 'com.aes.apprater.SecRole'
grails.plugin.springsecurity.controllerAnnotations.staticRules = [
'/': ['permitAll'],
'/index': ['permitAll'],
'/index.gsp': ['permitAll'],
'/assets/**': ['permitAll'],
'/**/js/**': ['permitAll'],
'/**/css/**': ['permitAll'],
'/**/images/**': ['permitAll'],
'/**/favicon.ico': ['permitAll']
]
grails.plugin.springsecurity.securityConfigType = "InterceptUrlMap"
grails.plugin.springsecurity.interceptUrlMap = [
'/project/**': ['ROLE_ADMIN'],
'/appRater/**': ['ROLE_ADMIN'],
'/mobilePlatform/**': ['ROLE_ADMIN'],
'/**': ['IS_AUTHENTICATED_ANONYMOUSLY']
]
grails.plugin.springsecurity.filterChain.chainMap = [
'/api/**': 'JOINED_FILTERS,-exceptionTranslationFilter,-authenticationProcessingFilter,-securityContextPersistenceFilter,-rememberMeAuthenticationFilter', // Stateless chain
'/**': 'JOINED_FILTERS,-restTokenValidationFilter,-restExceptionTranslationFilter' // Traditional chain
]
grails.plugin.springsecurity.rest.login.active=true
grails.plugin.springsecurity.rest.login.failureStatusCode=401
grails.plugin.springsecurity.rest.token.validation.active=true
输出:
C:\Users\admin>curl -i -X POST -H "Content-Type: application/json" -d '{"usernam
e":"xxxxx", "password":"xxxx"}' http://localhost:8080/xxxx-2.0/api/login
curl: (3) [globbing] unmatched close brace/bracket in column 14
HTTP/1.1 400 Bad Request
Server: Apache-Coyote/1.1
Content-Length: 0
Date: Fri, 28 Apr 2017 09:16:44 GMT
Connection: close
调试日志:
|Loading Grails 2.5.6
|Configuring classpath
.
|Environment set to development
.................................
|Packaging Grails application
.............................................
|Running Grails application
Configuring Spring Security Core ...
... finished configuring Spring Security Core
Configuring Spring Security REST ...
... finished configuring Spring Security REST
2017-05-02 13:10:00,852 [localhost-startStop-1] DEBUG intercept.FilterSecurityInterceptor - Validated configuration attributes
2017-05-02 13:10:04,407 [localhost-startStop-1] DEBUG hierarchicalroles.RoleHierarchyImpl - setHierarchy() - The following role hierarchy was set:
2017-05-02 13:10:04,425 [localhost-startStop-1] INFO web.DefaultSecurityFilterChain - Creating filter chain: Ant [pattern='/api/**'], [grails.plugin.springsecurity.web.SecurityRequestHolderFilter@243ac73f, grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter@eef0bae, grails.plugin.springsecurity.rest.RestAuthenticationFilter@6fe7d42a, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@5d1a4acb, grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter@6924852d, grails.plugin.springsecurity.rest.RestTokenValidationFilter@5ca38348, org.springframework.security.web.access.ExceptionTranslationFilter@73001b7b, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@c0c6339]
2017-05-02 13:10:04,425 [localhost-startStop-1] INFO web.DefaultSecurityFilterChain - Creating filter chain: Ant [pattern='/**'], [grails.plugin.springsecurity.web.SecurityRequestHolderFilter@243ac73f, org.springframework.security.web.context.SecurityContextPersistenceFilter@146395d, grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter@eef0bae, grails.plugin.springsecurity.web.authentication.GrailsUsernamePasswordAuthenticationFilter@29600952, grails.plugin.springsecurity.rest.RestAuthenticationFilter@6fe7d42a, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@5d1a4acb, grails.plugin.springsecurity.web.filter.GrailsRememberMeAuthenticationFilter@6003fbb6, grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter@6924852d, org.springframework.security.web.access.ExceptionTranslationFilter@25829af9, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@c0c6339]
|Server running. Browse to http://localhost:8090/apprater-2.0
.2017-05-02 13:10:06,221 [http-bio-8090-exec-10] DEBUG web.FilterChainProxy - /index.gsp at position 3 of 10 in additional filter chain; firing Filter: 'MutableLogoutFilter'
2017-05-02 13:10:06,221 [http-bio-8090-exec-10] DEBUG web.FilterChainProxy - /index.gsp at position 4 of 10 in additional filter chain; firing Filter: 'GrailsUsernamePasswordAuthenticationFilter'
2017-05-02 13:10:06,221 [http-bio-8090-exec-10] DEBUG web.FilterChainProxy - /index.gsp at position 5 of 10 in additional filter chain; firing Filter: 'RestAuthenticationFilter'
.2017-05-02 13:10:06,285 [http-bio-8090-exec-10] DEBUG web.FilterChainProxy - /index.gsp at position 6 of 10 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2017-05-02 13:10:06,287 [http-bio-8090-exec-10] DEBUG web.FilterChainProxy - /index.gsp at position 7 of 10 in additional filter chain; firing Filter: 'GrailsRememberMeAuthenticationFilter'
2017-05-02 13:10:06,288 [http-bio-8090-exec-10] DEBUG web.FilterChainProxy - /index.gsp at position 8 of 10 in additional filter chain; firing Filter: 'GrailsAnonymousAuthenticationFilter'
.2017-05-02 13:10:06,300 [http-bio-8090-exec-10] DEBUG web.FilterChainProxy - /index.gsp reached end of additional filter chain; proceeding with original chain
.2017-05-02 13:10:07,785 [http-bio-8090-exec-10] DEBUG context.HttpSessionSecurityContextRepository - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2017-05-02 13:10:07,786 [http-bio-8090-exec-10] DEBUG context.HttpSessionSecurityContextRepository$SaveToSessionResponseWrapper - Skip invoking on
2017-05-02 13:10:07,786 [http-bio-8090-exec-10] DEBUG context.HttpSessionSecurityContextRepository$SaveToSessionResponseWrapper - Skip invoking on
2017-05-02 13:10:07,786 [http-bio-8090-exec-10] DEBUG context.HttpSessionSecurityContextRepository$SaveToSessionResponseWrapper - Skip invoking on
2017-05-02 13:10:07,788 [http-bio-8090-exec-10] DEBUG access.ExceptionTranslationFilter - Chain processed normally
2017-05-02 13:10:07,788 [http-bio-8090-exec-10] DEBUG context.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
2017-05-02 13:10:14,009 [http-bio-8090-exec-2] DEBUG matcher.AntPathRequestMatcher - Checking match of request : '/api/login'; against '/api/**'
2017-05-02 13:10:14,010 [http-bio-8090-exec-2] DEBUG web.FilterChainProxy - /api/login at position 1 of 8 in additional filter chain; firing Filter: 'SecurityRequestHolderFilter'
2017-05-02 13:10:14,010 [http-bio-8090-exec-2] DEBUG web.FilterChainProxy - /api/login at position 2 of 8 in additional filter chain; firing Filter: 'MutableLogoutFilter'
2017-05-02 13:10:14,010 [http-bio-8090-exec-2] DEBUG web.FilterChainProxy - /api/login at position 3 of 8 in additional filter chain; firing Filter: 'RestAuthenticationFilter'
终于在grails controller中写了一个测试用例,结果是curl抛出400 bad request错误。配置没有问题。下面的测试用例证明了这一点。
when: 'login with the admin'
RestBuilder rest = new RestBuilder()
def resp = rest.post("http://localhost:${serverPort}/xxx/api/login") {
accept('application/json')
contentType('application/json')
json {
username = 'xxx'
password = 'xxx'
}
}
then:
resp.status == 200
resp.json.roles.find { it == 'ROLE_ADMIN' }
when:
def accessToken = resp.json.access_token
then:
accessToken
when:
resp = rest.get("http://localhost:${serverPort}/xxx/appRaterRest/index") {
accept('application/json')
header('Authorization', "Bearer ${accessToken}" )
}
then:
resp.status == 200