2011-09-25 43 views
4

更新:我改变了这个问题是关于我遇到的具体问题。这是因为过滤器的单元测试将在Grails 2.0中得到支持,所以希望文档会更好。使用FiltersUnitTestCase来单元测试Shiro安全过滤器,IllegalStateException

我想为我设置的过滤器编写单元测试,在我的grails应用程序中实现Shiro安全。我正在使用Grails 1.3.7,并且无法为此特定项目使用2.0一段时间(如果有的话)。

我的过滤器背后的想法是我需要匿名访问数字或控制器/操作组合,但保护对其他人的访问。我也希望它失败,即如果您忘记明确允许访问,则禁止访问。

过滤器类

class SecurityFilters { 
    def filters = { 

     homeAccess(controller: "home", action: "*") { 
      before = { 

       // Allow all access 
       request.accessAllowed = true 
      } 
     } 

     serverAccess(controller: "server", action: "list") { 
      before = { 

       // Allow all access 
       request.accessAllowed = true 
      } 
     } 

     layerAccess(controller: "layer", action: "list|listBaseLayersAsJson|listNonBaseLayerAsJson|showLayerByItsId") { 
      before = { 

       // Allow all access 
       request.accessAllowed = true 
      } 
     } 

     all(uri: "/**") { 
      before = { 

       // Check if request has been allowed by another filter 
       if (request.accessAllowed) return true    

       // Ignore direct views (e.g. the default main index page). 
       if (!controllerName) return true 

       // Access control by convention. 
       accessControl(auth: false) 
      } 
     } 
    } 
} 

单元测试

import org.codehaus.groovy.grails.plugins.web.filters.FilterConfig 

class SecurityFiltersTests extends FiltersUnitTestCase { 

    protected void setUp() { 
     super.setUp() 
    } 

    protected void tearDown() { 
     super.tearDown() 
    } 

    void testHomeControllerFilter() { 

     checkFilter('homeAccess') 
    } 

    void testServerControllerFilter() { 

     checkFilter('serverAccess') 
    } 

    void testLayerControllerFilter() { 

     checkFilter('layerAccess') 
    } 

    void testAllFilter() { 

     assertTrue "Write tests", false 
    } 

    void checkFilter(String filterName) { 

     FilterConfig filter = initFilter(filterName) 
     assertNotNull filterName + " filter should exist", filter 
     assertExistsBefore(filterName) 

     assertEquals "accessAllowed should be null to start with", null, filter.request.accessAllowed 

     // Run filter 
     filter.before() 

     assertEquals "accessAllowed should be true now", true, filter.request.accessAllowed 
    } 
} 

例外

的问题是,当这些测试都跑我得到下面的异常:

No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request. 

java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request. 
    at grails.test.MockUtils$_addCommonWebProperties_closure32.doCall(MockUtils.groovy:316) 
    at shiro.SecurityFilters$_closure1_closure5_closure12.doCall(SecurityFilters.groovy:40) 
    at shiro.SecurityFilters$_closure1_closure5_closure12.doCall(SecurityFilters.groovy) 
    at shiro.SecurityFiltersTests.checkFilter(SecurityFiltersTests.groovy:92) 
    at shiro.SecurityFiltersTests$checkFilter.callCurrent(Unknown Source) 
    at shiro.SecurityFiltersTests.testLayerControllerFilter(SecurityFiltersTests.groovy:65) 

此外,我已经把在单元测试下面一行:

println "filter.request: " + filter.request 

打印出以下几点:

filter.request: org.code[email protected]2914cca4 

所以它肯定好像是用一个模拟请求对象。

所以,这些问题。

我是否正确使用FiltersUnitTestCase来执行我的过滤器?

而且,如果是这样:

为什么我遇到了这个例外?

回答

1

提醒所有人的调试规则:继续删除代码,直到找到问题的确切路线。即使很明显该线路不会引起问题。因为:有时它实际上是

由于我的调试工作的一部分,我的代码在我的过滤器下面一行:

println "controllerName = '${controllerName}', actionName = '${actionName}'" 

这是直接前行:

request.accessAllowed = true 

我采取了它的代码粘贴到这个问题,试图保持它的整洁,但显然我运行测试时没有尝试过评论它。很抱歉,任何查看该代码并找不到问题的人都可以。你是对的,问题不在我提供的任何代码中。

所以答案是如果您尝试访问controllerNameactionName变量,您可能会看到此处报告的异常。

的解决方案是执行该可能引用controllerNameactionName任何过滤器之前,使用中的FiltersUnitTestCase和setControllerName()setActionName()方法。