使用Spring安全插件进行文件扩展名内容协商?

时间:2011-12-15 19:47:55

标签: spring grails groovy annotations spring-security

我正在尝试使用最新的Spring安全插件来获取grails,但是我遇到了一点点。

我有一个使用此方法的控制器:

@Secured(['ROLE_USER'])
def query = {
}

当我点击http://localhost:8080/myApp/myController/query时,系统会根据需要提示您进行授权。但是,我需要通过文件扩展名进行内容类型协商。使用

grails.mime.file.extensions=true

我可以使用相同的UrlMappings并通过.../myApp/myController/query.js?params=blah访问我的控制器方法。 但是,系统不会提示我进行身份验证,并且请求会自动执行或失败,具体取决于我设置grails.plugins.springsecurity.rejectIfNoRule

的方式

如何使用spring security plugin进行文件类型协商?

2 个答案:

答案 0 :(得分:0)

关闭grails.mime.file.extensions并添加此过滤器:

class FileExtensionContentNegotiationFilters {
    final static String DEFAULT_FORMAT = "js"
    def filters = {
        all(controller: '*', action: '*') {
            before = {
                addFormatToRequestByFileExtension(request)
            }
            after = {
            }
            afterView = {
            }
        }
    }

    protected addFormatToRequestByFileExtension(def request) {
        String suffix = getSuffixFromPath(request.forwardURI)
        String extension = FilenameUtils.getExtension(suffix)

        if (extension.isEmpty()) {
            request[GrailsApplicationAttributes.CONTENT_FORMAT] = DEFAULT_FORMAT
        }
        else {
            request[GrailsApplicationAttributes.CONTENT_FORMAT] = extension
        }
    }

    protected String getSuffixFromPath(String pathWithoutParams) {
        int lastSlash = pathWithoutParams.lastIndexOf("/")

        if (lastSlash < 0) {
            return ""
        }

        return pathWithoutParams.substring(lastSlash + 1)
    }
}

答案 1 :(得分:-1)

上述解决方案对我不起作用。当我请求带扩展名的网址时,会生成404响应。

我提供了另一种解决方案,无需关闭grails.mime.file.extensions,也不需要额外的过滤器。相反,它是对插件类org.codehaus.groovy.grails.plugins.springsecurity.AnnotationFilterInvocationDefinition的修改。您需要做的是编辑方法determineUrl,如下所示(查看注释以确定更改):

@Override
protected String determineUrl(final FilterInvocation filterInvocation) {
    HttpServletRequest request = filterInvocation.getHttpRequest();
    HttpServletResponse response = filterInvocation.getHttpResponse();

    GrailsWebRequest existingRequest = WebUtils.retrieveGrailsWebRequest();

    String requestUrl = request.getRequestURI().substring(request.getContextPath().length());

    /** The following 2 lines were added */
    int indexOfPeriod = requestUrl.indexOf('.');
    String requestUrlForMatching = (indexOfPeriod != -1) ? requestUrl.substring(0, indexOfPeriod) : requestUrl;

    String url = null;
    try {
        GrailsWebRequest grailsRequest = new GrailsWebRequest(request, response,
                ServletContextHolder.getServletContext());
        WebUtils.storeGrailsWebRequest(grailsRequest);

        Map<String, Object> savedParams = copyParams(grailsRequest);

        /* Use requestUrlForMatching instead of requestUrl */
        for (UrlMappingInfo mapping : _urlMappingsHolder.matchAll(requestUrlForMatching)) {
            configureMapping(mapping, grailsRequest, savedParams);

            url = findGrailsUrl(mapping);
            if (url != null) {
                break;
            }
        }
    }
    finally {
        if (existingRequest == null) {
            WebUtils.clearGrailsWebRequest();
        }
        else {
            WebUtils.storeGrailsWebRequest(existingRequest);
        }
    }

    if (!StringUtils.hasLength(url)) {
        // probably css/js/image
        url = requestUrl;
    }

    return lowercaseAndStripQuerystring(url);
}

问题是,带有扩展名的网址与使用UrlMappings方法的UrlMappingsHolder.matchAll中的任何网址都不匹配。因此,解决方案是在查找匹配之前省略扩展。通过此更改,一切都按预期工作。

我还创建了一个拉取请求,其中包含https://github.com/grails-plugins/grails-spring-security-core/pull/24

处的修复程序

您可以在https://github.com/arcesino/grails-spring-security-core/commit/19f87168ec4422b4fe06cc6914adeb1bae4b8752

看到更改

使用1.2.7.3版本进行测试