当前位置: 首页 > 知识库问答 >
问题:

grails Spring Securityrest插件和伪锁

连昊天
2023-03-14

我有一个Grails项目,主要是一个REST API。我定义的endpoint在没有Spring Security性的情况下可以正常工作,所有URL都可以访问并响应正常。所以,转到身份验证,我安装了grails Spring Securityrest插件。以下是配置:

配置。棒极了

grails.plugin.springsecurity.filterChain.chainMap = [
        '/api/**': 'JOINED_FILTERS,-exceptionTranslationFilter,-authenticationProcessingFilter,-securityContextPersistenceFilter,-rememberMeAuthenticationFilter',  // Stateless chain
        '/**': 'JOINED_FILTERS,-restTokenValidationFilter,-restExceptionTranslationFilter'                                                                          // Traditional chain
]

grails.plugin.springsecurity.userLookup.userDomainClassName = 'transportados.backend.User'
grails.plugin.springsecurity.userLookup.authorityJoinClassName = 'transportados.backend.UserRole'
grails.plugin.springsecurity.authority.className = 'transportados.backend.Role'
grails.plugin.springsecurity.controllerAnnotations.staticRules = [
    '/':                              ['permitAll'],
    '/index':                         ['permitAll'],
    '/index.gsp':                     ['permitAll'],
    '/**/js/**':                      ['permitAll'],
    '/**/css/**':                     ['permitAll'],
    '/**/images/**':                  ['permitAll'],
    '/**/favicon.ico':                ['permitAll']

URL映射。棒极了

class UrlMappings {

    static mappings = {
        "/$controller/$action?/$id?(.$format)?"{
            constraints {
                // apply constraints here
            }
        }


        /*******************************************************************************************************************
         ***********************************************  API v1  **********************************************************
         *******************************************************************************************************************/

        // Shipments
        "/api/v1/shipments"(controller: "Shipment", action: [POST: 'save', GET: 'index'], namespace:'v1')
        "/api/v1/shipments/${id}"(controller: "Shipment", action: [PUT: 'update', GET: 'show', DELETE:'delete'], namespace:'v1')

        // Carrier
        "/api/v1/carriers"(controller: "Carrier", action: [POST: 'save', GET: 'index'], namespace:'v1')
        "/api/v1/carriers/${id}"(controller: "Carrier", action: [PUT: 'update', GET: 'show', DELETE:'delete'], namespace:'v1')

        // Item
        "/api/v1/items"(controller: "Item", action: [POST: 'save', GET: 'index'], namespace:'v1')
        "/api/v1/items/${id}"(controller: "Item", action: [PUT: 'update', GET: 'show', DELETE:'delete'], namespace:'v1')

        // Quote
        "/api/v1/quotes"(controller: "Quote", action: [POST: 'save', GET: 'index'], namespace:'v1')
        "/api/v1/quotes/${id}"(controller: "Quote", action: [PUT: 'update', GET: 'show', DELETE:'delete'], namespace:'v1')

        // Review
        "/api/v1/reviews"(controller: "Review", action: [POST: 'save', GET: 'index'], namespace:'v1')
        "/api/v1/reviews/${id}"(controller: "Review", action: [PUT: 'update', GET: 'show', DELETE:'delete'], namespace:'v1')

        // User
        "/api/v1/users"(controller: "User", action: [POST: 'save', GET: 'index'], namespace:'v1')
        "/api/v1/users/${id}"(controller: "User", action: [PUT: 'update', GET: 'show', DELETE:'delete'], namespace:'v1')

        // Vehicle
        "/api/v1/vehicles"(controller: "Vehicle", action: [POST: 'save', GET: 'index'], namespace:'v1')
        "/api/v1/vehicles/${id}"(controller: "Vehicle", action: [PUT: 'update', GET: 'show', DELETE:'delete'], namespace:'v1')

        "/"(view:"/index")
        "500"(view:'/error')
    }
}

资源http://localhost:8080/api/login工作正常,如果凭证没有问题,给我一个有效的令牌。

当试图使用它访问以下控制器时,FilterSecurity Interceptor拒绝了我的访问

package transportados.backend

import static org.springframework.http.HttpStatus.*
import grails.transaction.Transactional
import grails.plugin.springsecurity.annotation.Secured

@Secured(['ROLE_ADMIN'])
@Transactional(readOnly = true)
class ShipmentController {

    static namespace = 'v1'
    static responseFormats = ['json', 'xml']
    //static allowedMethods = [index: "GET", save: "POST", update: "PUT", delete: "DELETE"]

    def index(Integer max) {
        params.max = Math.min(max ?: 10, 100)
        respond Shipment.list(params), [status: OK]
    }

    def show(Shipment shipment) {
        respond shipment
    }

    @Transactional
    def save(Shipment shipmentInstance) {
        if (shipmentInstance == null) {
            render status: NOT_FOUND
            return
        }

        shipmentInstance.validate()
        if (shipmentInstance.hasErrors()) {
            render status: NOT_ACCEPTABLE
            return
        }

        shipmentInstance.save flush:true
        respond shipmentInstance, [status: CREATED]
    }

    @Transactional
    def update(Shipment shipmentInstance) {
        if (shipmentInstance == null) {
            render status: NOT_FOUND
            return
        }

        shipmentInstance.validate()
        if (shipmentInstance.hasErrors()) {
            render status: NOT_ACCEPTABLE
            return
        }

        shipmentInstance.save flush:true
        respond shipmentInstance, [status: OK]
    }

    @Transactional
    def delete(Shipment shipmentInstance) {

        if (shipmentInstance == null) {
            render status: NOT_FOUND
            return
        }

        shipmentInstance.delete flush:true
        render status: NO_CONTENT
    }
}

以下是日志:

|Server running. Browse to http://localhost:8080/
2015-02-09 21:04:43,549 [http-bio-8080-exec-6] DEBUG matcher.AntPathRequestMatcher  - Checking match of request : '/api/v1/shipments'; against '/api/v1/**'
2015-02-09 21:04:43,550 [http-bio-8080-exec-6] DEBUG web.FilterChainProxy  - /api/v1/shipments at position 1 of 7 in additional filter chain; firing Filter: 'MutableLogoutFilter'
2015-02-09 21:04:43,550 [http-bio-8080-exec-6] DEBUG web.FilterChainProxy  - /api/v1/shipments at position 2 of 7 in additional filter chain; firing Filter: 'RestAuthenticationFilter'
2015-02-09 21:04:43,561 [http-bio-8080-exec-6] DEBUG rest.RestAuthenticationFilter  - Actual URI is /api/v1/shipments; endpoint URL is /api/login
2015-02-09 21:04:43,561 [http-bio-8080-exec-6] DEBUG web.FilterChainProxy  - /api/v1/shipments at position 3 of 7 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2015-02-09 21:04:43,561 [http-bio-8080-exec-6] DEBUG web.FilterChainProxy  - /api/v1/shipments at position 4 of 7 in additional filter chain; firing Filter: 'GrailsAnonymousAuthenticationFilter'
2015-02-09 21:04:43,561 [http-bio-8080-exec-6] DEBUG web.FilterChainProxy  - /api/v1/shipments at position 5 of 7 in additional filter chain; firing Filter: 'RestTokenValidationFilter'
2015-02-09 21:04:43,564 [http-bio-8080-exec-6] DEBUG bearer.BearerTokenReader  - Looking for bearer token in Authorization header, query string or Form-Encoded body parameter
2015-02-09 21:04:43,566 [http-bio-8080-exec-6] DEBUG bearer.BearerTokenReader  - Found bearer token in Authorization header
2015-02-09 21:04:43,567 [http-bio-8080-exec-6] DEBUG rest.RestTokenValidationFilter  - Token found: eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0MjM1MjkwMzAsInN1YiI6Im1lIiwicm9sZXMiOlsiUk9MRV9BRE1JTiJdLCJpYXQiOjE0MjM1MjU0MzB9.CLUxW5reqfnn-UDUtNul7CTRg4O5GIuz4zeY1UghQn
2015-02-09 21:04:43,567 [http-bio-8080-exec-6] DEBUG rest.RestTokenValidationFilter  - Trying to authenticate the token
2015-02-09 21:04:43,581 [http-bio-8080-exec-6] DEBUG rest.RestAuthenticationProvider  - Trying to validate token eyJhbGciOiJIUzI1NiJ9.eyJleHAiOjE0MjM1MjkwMzAsInN1YiI6Im1lIiwicm9sZXMiOlsiUk9MRV9BRE1JTiJdLCJpYXQiOjE0MjM1MjU0MzB9.CLUxW5reqfnn-UDUtNul7CTRg4O5GIuz4zeY1UghQn
2015-02-09 21:04:43,602 [http-bio-8080-exec-6] DEBUG jwt.JwtTokenStorageService  - Parsed an HMAC signed JWT
2015-02-09 21:04:43,688 [http-bio-8080-exec-6] DEBUG jwt.JwtTokenStorageService  - Successfully verified JWT
2015-02-09 21:04:43,692 [http-bio-8080-exec-6] DEBUG rest.RestAuthenticationProvider  - Authentication result: com.odobo.grails.plugin.springsecurity.rest.RestAuthenticationToken@40a2eeba: Principal: org.springframework.security.core.userdetails.User@d98: Username: me; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_ADMIN
2015-02-09 21:04:43,692 [http-bio-8080-exec-6] DEBUG rest.RestTokenValidationFilter  - Token authenticated. Storing the authentication result in the security context
2015-02-09 21:04:43,692 [http-bio-8080-exec-6] DEBUG rest.RestTokenValidationFilter  - Authentication result: com.odobo.grails.plugin.springsecurity.rest.RestAuthenticationToken@40a2eeba: Principal: org.springframework.security.core.userdetails.User@d98: Username: me; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_ADMIN
2015-02-09 21:04:43,694 [http-bio-8080-exec-6] DEBUG rest.RestTokenValidationFilter  - Continuing the filter chain
2015-02-09 21:04:43,695 [http-bio-8080-exec-6] DEBUG web.FilterChainProxy  - /api/v1/shipments at position 6 of 7 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2015-02-09 21:04:43,695 [http-bio-8080-exec-6] DEBUG web.FilterChainProxy  - /api/v1/shipments at position 7 of 7 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2015-02-09 21:04:43,696 [http-bio-8080-exec-6] DEBUG intercept.FilterSecurityInterceptor  - Secure object: FilterInvocation: URL: /api/v1/shipments; Attributes: [_DENY_]
2015-02-09 21:04:43,696 [http-bio-8080-exec-6] DEBUG intercept.FilterSecurityInterceptor  - Previously Authenticated: com.odobo.grails.plugin.springsecurity.rest.RestAuthenticationToken@40a2eeba: Principal: org.springframework.security.core.userdetails.User@d98: Username: me; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_ADMIN; Credentials: [PROTECTED]; Authenticated: true; Details: null; Granted Authorities: ROLE_ADMIN
2015-02-09 21:04:43,696 [http-bio-8080-exec-6] DEBUG hierarchicalroles.RoleHierarchyImpl  - getReachableGrantedAuthorities() - From the roles [ROLE_ADMIN] one can reach [ROLE_ADMIN] in zero or more steps.
2015-02-09 21:04:43,703 [http-bio-8080-exec-6] DEBUG access.ExceptionTranslationFilter  - Access is denied (user is not anonymous); delegating to AccessDeniedHandler
Message: Access is denied
    Line | Method
->>   47 | decide             in grails.plugin.springsecurity.access.vote.AuthenticatedVetoableDecisionManager
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|    102 | processFilterChain in com.odobo.grails.plugin.springsecurity.rest.RestTokenValidationFilter
|     68 | doFilter . . . . . in     ''
|     53 | doFilter           in grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter
|    122 | doFilter . . . . . in com.odobo.grails.plugin.springsecurity.rest.RestAuthenticationFilter
|     82 | doFilter           in grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter
|   1145 | runWorker . . . .  in java.util.concurrent.ThreadPoolExecutor
|    615 | run                in java.util.concurrent.ThreadPoolExecutor$Worker
^    744 | run . . . . . . .  in java.lang.Thread

有什么想法吗?这让我有点疯狂: S

谢谢!

共有2个答案

颛孙飞
2023-03-14

Spring Security核心插件不支持命名空间控制器:https://stackoverflow.com/a/21896846/2923710

或者,您可以在配置中尝试使用interceptUrlMap。groovy,如中所述http://grails-plugins.github.io/grails-spring-security-core/guide/requestMappings.html#configGroovyMap

齐英朗
2023-03-14

URL映射中的名称空间是问题所在。在删除urlmappings中的名称空间定义和控制器中的静态变量“namespace”之后,生活又好过了。

 类似资料:
  • 问题内容: 因此,我正在AngularJS中创建一个新站点,并且对此非常喜欢! 但是,我遇到了一个问题。我试图在我的textareas中添加一个名为“ Redactor”的jQuery插件,但是我认为正在发生的事情是,当我初始化该插件时,它将替换textarea元素。之所以有问题,是因为我为文本区域设置了“ ng-model”属性,如下所示: 我正在使用AngularJS UI拾取焦点事件,然后在

  • 新的Maven项目是在eclipse中创建的。但是Pom.xml显示了一些错误。 “无法计算构建计划:Plugin org.apache.maven。插件:maven resources插件:2.6或其一个依赖项无法解析:未能读取org.apache.maven的工件描述符。插件:maven resources插件:jar:2.6 Plugin org.apache.maven。插件:maven

  • 下载、安装国内期货交易插件 OpenQuant系统中可以由第三方服务商或者开发者自行进行扩展,例如行情源的接入、交易通道的接入、历史数据源的接入等等,这些扩展我们称之为插件(Plugins)。 上期技术公司的CTP系统是获取国内期货实时行情、进行交易的主要平台。各个主流期货经纪商均支持客户通过CTP柜台进行期货、期权的交易。您可以在SmartQuant中文网站(http://www.smartqu

  • 问题内容: 和之间有什么区别?我们什么时候必须使用完? 双冒号和单冒号表示法是区分伪类和伪元素。 以上声明的实际含义是什么? 问题答案: 伪类: CSS伪类是关键字,其前面带有一个冒号(:),并添加到选择器的末尾,以指定要对选定元素进行样式设置( 仅当它们处于特定状态时) 。例如,您可能只想在元素被鼠标指针悬停时设置样式,或者在元素被禁用或选中时选中一个复选框,或者是作为其父元素在DOM树中的第一

  • 本文向大家介绍CSS的伪类和伪对象有什么不同?相关面试题,主要包含被问及CSS的伪类和伪对象有什么不同?时的应答技巧和注意事项,需要的朋友参考一下 伪类:我们常用的比如,hover,focus等,我认为伪类是为了弥补选择器的不足。还有伪类选择器,比如first-child,nth-child. 伪元素 : ::before ::after 是为了创建一个dom元素,使用content属性指定要插入

  • 问题内容: 在下面的Jenkins作业配置中, Refspec 和 Branch specifier(默认为空白) 之间有什么区别: 我试图在作业配置中设置Refspec选项: 在我的构建从属服务器上的克隆仓库中,.git / config文件如下所示: 似乎 fetch 的值不正确(从jenkins作业配置中读取)。此外,它对磁盘空间消耗没有影响。 问题答案: Refspec 定义了 获取 操作