无法连接到grails v3 rest controller,获取403,访问被拒绝

时间:2017-03-06 22:39:05

标签: rest grails plugins spring-security-rest

过程。

创建了一个新的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 api login

我尝试使用返回的密钥进行后验证,并获得html 200,看起来像

最后我尝试拨打我的/ api / posts服务。我剪切并粘贴我的密钥并添加到GET标题并提交,我得到403 /禁止

enter image description here

我无法在配置中看到我的错误,并且忘记了今天的生活意愿。任何人都可以看到 - 指出我的配置不起作用的地方。

无法看到我出错的地方 - 我希望有一双新眼睛可以帮助发现,我在日志跟踪中有关于最后/ 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

0 个答案:

没有答案