2015-02-10 120 views
0

我有一個Grails項目,主要是一個REST API。我定義的端點在沒有彈簧安全性的情況下工作正常,並且所有的url都可以訪問並且響應正常。 因此,轉向身份驗證,我安裝了grails-spring-security-rest插件。 這裏的配置:grails-spring-security-rest插件和pelsimistic lockdown

Config.groovy中

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'] 

UrlMappings.groovy

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工作正常,並給了我一個有效的令牌憑據是否OK的資源。

當試圖用它來訪問以下控制器,我可以訪問由FilterSecurityInterceptor

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.[email protected]40a2eeba: Principal: [email protected]: 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.[email protected]40a2eeba: Principal: [email protected]: 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.[email protected]40a2eeba: Principal: [email protected]: 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

謝謝!

回答

0

UrlMappings中的名稱空間是問題所在。 刪除了兩個url映射中的命名空間定義以及控制器中的靜態變量「namespace」後,生活又恢復了良好。