4

更新:この質問を、私が抱えている特定の問題に関するものに変更しました。これは、フィルターの単体テストが Grails 2.0 でサポートされるためです。ドキュメントが改善されることを願っています。

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.codehaus.groovy.grails.plugins.testing.GrailsMockHttpServletRequest@2914cca4

したがって、確かにモック リクエスト オブジェクトを使用しているようです。

では、質問です。

FiltersUnitTestCase を正しく使用してフィルターを実行していますか?

そしてそうならば:

この例外が発生するのはなぜですか?

4

1 に答える 1

1

そこにいるすべての人のためのデバッグのルールへのリマインダー:問題が発生している正確な行が見つかるまで、コードを削除し続けてください。行が問題の原因ではないことが明らかな場合でも。理由:時にはそれは実際には.

デバッグ作業の一環として、フィルターに次のコード行がありました。

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

これは次の行の直前にありました。

request.accessAllowed = true

この質問に貼り付けられたコードからそれを取り出して整理しようとしましたが、テストを実行するときにコメントアウトしようとしなかったようです。そのコードを調べて問題を見つけることができなかった人には申し訳ありません。あなたは正しかった、問題は私が提供したどのコードにもありませんでした。

したがって、または変数にアクセスしようとすると、ここで報告された例外が表示される可能性がありcontrollerNameactionNameます。

解決策は、またはを参照する可能性のあるフィルタを実行する前に、 FiltersUnitTestCaseで メソッドsetControllerName()とメソッドを使用することです。setActionName()controllerNameactionName

于 2011-10-10T03:18:34.153 に答える