过程。
创建了一个新的grails v3应用程序,并将以下依赖项添加到build.gradle
compile group: 'org.springframework.security', name: 'spring-security-core', version: '4.2.1.RELEASE'
compile 'org.grails.plugins:spring-security-core:3.1.1'
compile "org.grails.plugins:spring-security-rest:2.0.0.M2"
使用grails安全快速入门创建用户角色组配置,并在bootstrap.groovy中为用户设置用户,一些角色和一些帖子。查看/ dbconsole并保存记录。我的基本集成测试似乎有效
像这样创建了一个休息控制器 - 我此时没有保护任何东西
import grails.rest.RestfulController
class PostRestController extends RestfulController {
static responseFormats = ["json", "xml"]
//constructor - tells rest controller which domain class to scaffold
PostRestController() {
super (Post)
}
}
在网上阅读了很多内容之后,我已经在我的application.groovy 中找到了这个结果
//added to avoid login screens for dbconsole. if you add /** at end it works
grails.plugin.springsecurity.rejectIfNoRule = true//false//
grails.plugin.springsecurity.fii.rejectPublicInvocations = false
grails.plugin.springsecurity.securityConfigType = "Annotation"
grails.plugin.springsecurity.useSecurityEventListener = true //enable security events
//Rest
grails.plugin.springsecurity.useBasicAuth = true
grails.plugin.springsecurity.basic.realName = "coffeeShopApp"
grails.plugin.springsecurity.rest.login.useJsonCredentials = true //default
grails.plugin.springsecurity.rest.login.active = true //default
grails.plugin.springsecurity.rest.login.endpointUrl = '/api/login'
grails.plugin.springsecurity.rest.login.failureStatusCode = 401
grails.plugin.springsecurity.rest.token.validation.enableAnonymousAccess = true
// Added by the Spring Security Core plugin:
grails.plugin.springsecurity.userLookup.userDomainClassName = 'org.softwood.security.User'
grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'org.softwood.security.UserToUserGroup'
grails.plugin.springsecurity.authority.className = 'org.softwood.security.Role'
grails.plugin.springsecurity.authority.groupAuthorityNameField = 'authorities'
grails.plugin.springsecurity.useRoleGroups = true
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: '/dbconsole/**', access: ['permitAll']], //added
[pattern: '/console/**', access: ['permitAll']], //added
[pattern: '/secureTest/secure', access: ['ROLE_ADMIN']],
[pattern: '/secureTest/index', access: ['permitAll']],
[pattern: '/secureTest/willsPage', access: ["authentication.name == 'will'"]],
[pattern: '/api/**', access: ['permitAll']],
[pattern: '/assets/**', access: ['permitAll']],
[pattern: '/**/js/**', access: ['permitAll']],
[pattern: '/**/css/**', access: ['permitAll']],
[pattern: '/**/images/**', access: ['permitAll']],
[pattern: '/**/favicon.ico', access: ['permitAll']]
]
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/guest/**', filters: 'anonymousAuthenticationFilter,' +
'restTokenValidationFilter,' +
'restExceptionTranslationFilter,' +
'filterInvocationInterceptor'],
[pattern: '/api/**', filters: 'JOINED_FILTERS,' +
'-anonymousAuthenticationFilter,' +
'-exceptionTranslationFilter,' +
'-authenticationProcessingFilter,' +
'-securityContextPersistenceFilter,' +
'-rememberMeAuthenticationFilter'],
[pattern: '/**', filters: 'JOINED_FILTERS,' +
//'-basicAuthenticationFeature,' +
//'-basicExceptionTranslationFilter,' +
'-restTokenValidationFilter,' +
'-restExceptionTranslationFilter']
]
我的静态规则/ api / **为permit all。我根据春季安全休息文档更新了/ api / **的链图
我更新了我的UrlMappings,如下所示
class UrlMappings {
static mappings = {
//add alternate url mapping for rest based resources
"/api/posts" (resources : "postRest")
"/api/guest/posts" (resources : "postRest")
"/$controller/$action?/$id?(.$format)?"{
constraints {
// apply constraints here
}
}
"/"(view:"/index")
"500"(view:'/error')
"404"(view:'/notFound')
}
}
当我在grails控制台中运行url-mappings-report时,我的网址看起来正确曝光
我运行应用程序 - 一切正常
然后当我使用chrome rest client连接时,我使用chrome发布到api / login - 这给了我200和access_token
我尝试使用返回的密钥进行后验证,并获得html 200,看起来像
最后我尝试拨打我的/ api / posts服务。我剪切并粘贴我的密钥并添加到GET标题并提交,我得到403 /禁止
我无法在配置中看到我的错误,并且忘记了今天的生活意愿。任何人都可以看到 - 指出我的配置不起作用的地方。
无法看到我出错的地方 - 我希望有一双新眼睛可以帮助发现,我在日志跟踪中有关于最后/ api /来宾/帖子的信息 - 这可能有帮助
2017-03-06 22:32:05.239 DEBUG --- [nio-8080-exec-5] o.s.s.w.a.i.FilterSecurityInterceptor : Secure object: FilterInvocation: URL: /api/guest/posts; Attributes: [permitAll]
2017-03-06 22:32:05.239 DEBUG --- [nio-8080-exec-5] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: grails.plugin.springsecurity.authentication.GrailsAnonymousAuthenticationToken@f23b6234: 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@ffffc434: RemoteIpAddress: 192.168.1.238; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
2017-03-06 22:32:05.239 DEBUG --- [nio-8080-exec-5] o.s.s.a.h.RoleHierarchyImpl : getReachableGrantedAuthorities() - From the roles [ROLE_ANONYMOUS] one can reach [ROLE_ANONYMOUS] in zero or more steps.
2017-03-06 22:32:05.250 DEBUG --- [nio-8080-exec-5] o.s.s.w.a.i.FilterSecurityInterceptor : Authorization successful
2017-03-06 22:32:05.250 DEBUG --- [nio-8080-exec-5] o.s.s.w.a.i.FilterSecurityInterceptor : RunAsManager did not change Authentication object
2017-03-06 22:32:05.250 DEBUG --- [nio-8080-exec-5] o.s.security.web.FilterChainProxy : /api/guest/posts reached end of additional filter chain; proceeding with original chain
2017-03-06 22:32:05.277 DEBUG --- [nio-8080-exec-5] o.s.s.w.a.ExceptionTranslationFilter : Chain processed normally
2017-03-06 22:32:05.288 DEBUG --- [nio-8080-exec-5] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/error'; against '/assets/**'
2017-03-06 22:32:05.288 DEBUG --- [nio-8080-exec-5] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/error'; against '/**/js/**'
2017-03-06 22:32:05.288 DEBUG --- [nio-8080-exec-5] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/error'; against '/**/css/**'
2017-03-06 22:32:05.288 DEBUG --- [nio-8080-exec-5] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/error'; against '/**/images/**'
2017-03-06 22:32:05.288 DEBUG --- [nio-8080-exec-5] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/error'; against '/**/favicon.ico'
2017-03-06 22:32:05.288 DEBUG --- [nio-8080-exec-5] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/error'; against '/api/guest/**'
2017-03-06 22:32:05.288 DEBUG --- [nio-8080-exec-5] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/error'; against '/api/**'
2017-03-06 22:32:05.288 DEBUG --- [nio-8080-exec-5] o.s.s.w.u.matcher.AntPathRequestMatcher : Request '/error' matched by universal pattern '/**'
2017-03-06 22:32:05.288 DEBUG --- [nio-8080-exec-5] o.s.security.web.FilterChainProxy : /error at position 1 of 12 in additional filter chain; firing Filter: 'SecurityRequestHolderFilter'
2017-03-06 22:32:05.288 DEBUG --- [nio-8080-exec-5] o.s.security.web.FilterChainProxy : /error at position 2 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2017-03-06 22:32:05.289 DEBUG --- [nio-8080-exec-5] w.c.HttpSessionSecurityContextRepository : No HttpSession currently exists
2017-03-06 22:32:05.289 DEBUG --- [nio-8080-exec-5] w.c.HttpSessionSecurityContextRepository : No SecurityContext was available from the HttpSession: null. A new one will be created.
2017-03-06 22:32:05.289 DEBUG --- [nio-8080-exec-5] o.s.security.web.FilterChainProxy : /error at position 3 of 12 in additional filter chain; firing Filter: 'MutableLogoutFilter'
2017-03-06 22:32:05.289 DEBUG --- [nio-8080-exec-5] o.s.s.w.u.matcher.AntPathRequestMatcher : Checking match of request : '/error'; against '/logoff'
2017-03-06 22:32:05.289 DEBUG --- [nio-8080-exec-5] o.s.security.web.FilterChainProxy : /error at position 4 of 12 in additional filter chain; firing Filter: 'GrailsUsernamePasswordAuthenticationFilter'
2017-03-06 22:32:05.289 DEBUG --- [nio-8080-exec-5] o.s.security.web.FilterChainProxy : /error at position 5 of 12 in additional filter chain; firing Filter: 'RestAuthenticationFilter'
2017-03-06 22:32:05.289 DEBUG --- [nio-8080-exec-5] o.s.security.web.FilterChainProxy : /error at position 6 of 12 in additional filter chain; firing Filter: 'BasicAuthenticationFilter'
2017-03-06 22:32:05.289 DEBUG --- [nio-8080-exec-5] o.s.security.web.FilterChainProxy : /error at position 7 of 12 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2017-03-06 22:32:05.289 DEBUG --- [nio-8080-exec-5] o.s.security.web.FilterChainProxy : /error at position 8 of 12 in additional filter chain; firing Filter: 'GrailsRememberMeAuthenticationFilter'
2017-03-06 22:32:05.289 DEBUG --- [nio-8080-exec-5] o.s.security.web.FilterChainProxy : /error at position 9 of 12 in additional filter chain; firing Filter: 'GrailsAnonymousAuthenticationFilter'
2017-03-06 22:32:05.289 DEBUG --- [nio-8080-exec-5] o.s.security.web.FilterChainProxy : /error at position 10 of 12 in additional filter chain; firing Filter: 'UpdateRequestContextHolderExceptionTranslationFilter'
2017-03-06 22:32:05.289 DEBUG --- [nio-8080-exec-5] o.s.security.web.FilterChainProxy : /error at position 11 of 12 in additional filter chain; firing Filter: 'UpdateRequestContextHolderExceptionTranslationFilter'
2017-03-06 22:32:05.289 DEBUG --- [nio-8080-exec-5] o.s.security.web.FilterChainProxy : /error at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2017-03-06 22:32:05.293 DEBUG --- [nio-8080-exec-5] o.s.security.web.FilterChainProxy : /error reached end of additional filter chain; proceeding with original chain
2017-03-06 22:32:07.314 DEBUG --- [nio-8080-exec-5] w.c.HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2017-03-06 22:32:07.315 DEBUG --- [nio-8080-exec-5] s.s.w.c.SecurityContextPersistenceFilter : SecurityContextHolder now cleared, as request processing completed
最后 - 我启用了fii.rejectPublicInvocations并再次尝试,当我访问URL时,我得到了这个堆栈跟踪
java.lang.IllegalArgumentException: Secure object invocation FilterInvocation: URL: /api/posts was denied as public invocations are not allowed via this interceptor. This indicates a configuration error because the rejectPublicInvocations property is set to 'true'
at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:201)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:124)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:91)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:115)
at grails.plugin.springsecurity.web.UpdateRequestContextHolderExceptionTranslationFilter.doFilter(UpdateRequestContextHolderExceptionTranslationFilter.groovy:64)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:115)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
现在变得有点绝望,此时所有人都对此表示赞赏
注意 - 请参阅下面的评论 - 我做了一个' hack'像这样在PostRestController上 - 并将结果强制为' true'。现在允许我使用登录密钥访问api / guest / posts(匿名)和/ api / posts
@Secured (closure = {
assert request
assert ctx
println """details passed to rest controller >
authentication name : ${authentication.name}
is authenticed : ${isAuthenticated()}
has any role from admin or user: ${hasAnyRole('ROLE_ADMIN','ROLE_USER')}
has role admin : ${hasRole('ROLE_ADMIN')}
principal : $principal
"""
true
} )
class PostRestController extends RestfulController {
static responseFormats = ["json", "xml"]
//constructor - tells rest controller which domain class to scaffold
PostRestController() {
super (Post)
}
}
我已经启用了调试过滤器,当我访问api / posts时输出这个
Request received for '/api/posts':
SecurityContextHolderAwareRequestWrapper[ FirewalledRequest[ org.apache.catalina.connector.RequestFacade@3085690a]]
servletPath:/api/posts
pathInfo:null
Security filter chain: [
SecurityRequestHolderFilter
MutableLogoutFilter
RestAuthenticationFilter
SecurityContextHolderAwareRequestFilter
RestTokenValidationFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
]
我从闭包中写入控制台的跟踪给了我这个
details passed to rest controller >
authentication name : will
is authenticed : true
has any role from admin or user: true
has role admin : true
principal : grails.plugin.springsecurity.userdetails.GrailsUser@37afd2: Username: will; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN,ROLE_USER