0
votes

I use Spring Security ACL plugin and have no ACLs set before. I want to access the following service method:

@PostFilter("hasPermission(filterObject, read) or hasPermission(filterObject, admin)")
List<Company> list(Map params = [:]) {
   return Company.list(params)
}

I gave permission to the admin user for a company. When I access the above method everything works fine. The problem occurs when I stopped the server and do grails clean. When I restart and access the above method I get the following error. It is very strange because it worked the first time before the grails clean without errors.

2015-08-08 14:57:02,509 [http-nio-8080-exec-5] ERROR errors.GrailsExceptionResolver  - ClassCastException occurred when processing request: [GET] /test2/home/list
java.lang.String cannot be cast to java.lang.Long. Stacktrace follows:
Message: java.lang.String cannot be cast to java.lang.Long
    Line | Method
->>  305 | doCall                 in org.grails.datastore.gorm.GormStaticApi$_withCriteria_closure11
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|    302 | execute                in org.grails.datastore.mapping.core.DatastoreUtils
|     37 | execute . . . . . . .  in org.grails.datastore.gorm.AbstractDatastoreApi
|    304 | withCriteria           in org.grails.datastore.gorm.GormStaticApi
|    128 | lookupObjectIdentities in grails.plugin.springsecurity.acl.jdbc.GormAclLookupStrategy
|    106 | doCall                 in grails.plugin.springsecurity.acl.jdbc.GormAclLookupStrategy$_readAclsById_closure1
|     78 | readAclsById . . . . . in grails.plugin.springsecurity.acl.jdbc.GormAclLookupStrategy
|    288 | readAclsById           in grails.plugin.springsecurity.acl.AclService
|    127 | list . . . . . . . . . in test2.HomeController
|    198 | doFilter               in grails.plugin.cache.web.filter.PageFragmentCachingFilter
|     63 | doFilter . . . . . . . in grails.plugin.cache.web.filter.AbstractFilter
|     53 | doFilter               in grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter
|     62 | doFilter . . . . . . . in grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter
|   1142 | runWorker              in java.util.concurrent.ThreadPoolExecutor
|    617 | run . . . . . . . . .  in java.util.concurrent.ThreadPoolExecutor$Worker
^    745 | run                    in java.lang.Thread
Error |
2015-08-08 14:57:03,030 [http-nio-8080-exec-6] ERROR errors.GrailsExceptionResolver  - ClassCastException occurred when processing request: [GET] /test2/home/list
java.lang.String cannot be cast to java.lang.Long. Stacktrace follows:
Message: java.lang.String cannot be cast to java.lang.Long
    Line | Method
->>  305 | doCall                 in org.grails.datastore.gorm.GormStaticApi$_withCriteria_closure11
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|    302 | execute                in org.grails.datastore.mapping.core.DatastoreUtils
|     37 | execute . . . . . . .  in org.grails.datastore.gorm.AbstractDatastoreApi
|    304 | withCriteria           in org.grails.datastore.gorm.GormStaticApi
|    128 | lookupObjectIdentities in grails.plugin.springsecurity.acl.jdbc.GormAclLookupStrategy
|    106 | doCall                 in grails.plugin.springsecurity.acl.jdbc.GormAclLookupStrategy$_readAclsById_closure1
|     78 | readAclsById . . . . . in grails.plugin.springsecurity.acl.jdbc.GormAclLookupStrategy
|    288 | readAclsById           in grails.plugin.springsecurity.acl.AclService
|    127 | list . . . . . . . . . in test2.HomeController
|    198 | doFilter               in grails.plugin.cache.web.filter.PageFragmentCachingFilter
|     63 | doFilter . . . . . . . in grails.plugin.cache.web.filter.AbstractFilter
|     53 | doFilter               in grails.plugin.springsecurity.web.filter.GrailsAnonymousAuthenticationFilter
|     62 | doFilter . . . . . . . in grails.plugin.springsecurity.web.authentication.logout.MutableLogoutFilter
|   1142 | runWorker              in java.util.concurrent.ThreadPoolExecutor
|    617 | run . . . . . . . . .  in java.util.concurrent.ThreadPoolExecutor$Worker
^    745 | run                    in java.lang.Thread

I created a demo project here: https://github.com/confile/Spring-Security-ACL-Bug

Reproduce it:

Edit: I found that when I shut down my mysql server and restart it then the error is gone. It might belong to some caching issues here.

Is there a way to catch this error, e.g., in case where no ACLs have been set before?

Note: This question is still unanswered.

1
I am not clear on the new steps - first you go to list when there are no company so empty list is returned, then you create twice (?) the company1. ok but you do not assign the ACL since it looks you have this part on addPerm method so even at this stage if you go back to list you'll face the issue - Frederic Henri
I corrected the steps. Sorry. Even if you go back to list and have no permissions it should return an empty list due to the filter. Could you reproduce the bug? - confile
looks like persistence issue, to reproduce I would now need mysql instead of H2 installed; will try to set up that. if you have no permission I'll expect to have the error as company has been saved - Frederic Henri
No there is no error when company being saved. After save you have permissions but after grails clean you do not. - confile
ok, I've installed mysql to reproduce as you and I cannot - it works correctly here. I login, create company and perm, its ok. I stop server and clean. run-app again, my data are still there (I verify from localhost:8080/test2/dbconsole) then I can successfully return to list, no error on server, no exception thrown. can you check you cal_entry table when you restart your server ? your data should still be there. - Frederic Henri

1 Answers

1
votes

The issue seems actually related to the way AclSid overrides the one in the plugin.

You will see the java.lang.String cannot be cast to java.lang.Long issue when the plugins class won somehow.

There is an easy fix in general you always should be running grails package after you do a grails clean also you need to make sure on your ci server you run the package step before you build your war.

I have seen this same issue since we use UUIDs and had to make the AclSid class has a string for the sid as well. I've had no issues in production or locally once we started to correctly run the package step.