草庐IT

java - Spring Security - 忽略请求参数规则的URL

coder 2024-03-07 原文

我有一个使用 Spring Security 的 Web 应用程序。它使用 <intercept-url ../>描述不同 url 的访问过滤器的元素。默认情况下,这不会考虑 url 的请求参数。我需要根据请求参数设置 url 的自定义安全规则。所以我做了以下事情:

1) 我创建了一个 bean 后处理器类,它将为 spring 安全机制启用请求参数选项:

<beans:beans>
    . . .
    <beans:bean class="MySecurityBeanPostProcessor">
        <beans:property name="stripQueryStringFromUrls" value="false" />
    </beans:bean>
    . . .
</beans:beans>

还有代码:

public class MySecurityBeanPostProcessor implements BeanPostProcessor {

    private Boolean stripQueryStringFromUrls = null;

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (bean instanceof DefaultFilterInvocationSecurityMetadataSource && stripQueryStringFromUrls != null) {
            ((DefaultFilterInvocationSecurityMetadataSource) bean)
                .setStripQueryStringFromUrls(stripQueryStringFromUrls.booleanValue());
        }
        return bean;
    }

    // code stripped for clarity
}

这应该设置 spring security 元数据源以考虑请求参数。我已经调试了上面的代码和 stripQueryStringFromUrls正在设置属性。

2) 在我的安全上下文 xml 中,我有以下定义:

<intercept-url pattern="/myUrl?param=value" access="!isAuthenticated() or hasRole('ROLE_GUEST')" />
<intercept-url pattern="/myUrl" filters="none" />
...
<intercept-url pattern="/**" access="isAuthenticated()" />

如您所见,仅当用户未通过身份验证或使用 guest 帐户时,我才需要访问具有指定参数的 url。另外,我为相同的 url 添加了一个规则,但没有任何参数,它没有过滤器。

据我所知,应该配置 spring security 以提供更具体的 url BEFORE 较不具体的 url,否则链将首先检测到更一般的规则,并且不会继续越具体。这就是为什么我希望带有参数的 url 更具体,因此拒绝经过身份验证的非访客用户访问。相反,下面定义的更一般的规则适用。 这是输出:

INFO [STDOUT] 186879 [http-0.0.0.0-8080-1] DEBUG org.springframework.security.web.FilterChainProxy - Candidate is: '/myUrl'; pattern is /myUrl; matched=true

INFO [STDOUT] 186879 [http-0.0.0.0-8080-1] DEBUG org.springframework.security.web.FilterChainProxy - /myUrl?param=value has an empty filter list

我还尝试删除没有参数的 url 规则。然后,过滤器没有让我的带有参数的 url 规则起作用,而是选择了 /**。模式并要求用户登录。 其输出是:

INFO [STDOUT] 73066 [http-0.0.0.0-8080-1] DEBUG org.springframework.security.web.FilterChainProxy - Candidate is: '/myUrl'; pattern is /**; matched=true

INFO [STDOUT] 73068 [http-0.0.0.0-8080-1] DEBUG org.springframework.security.web.FilterChainProxy - /myUrl?param=value at position 1 of 8 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'

该应用程序是用 Java 1.6 编写的,使用 Spring v3.0 并部署在 Linux 机器上的 JBoss v5.1.0-GA 上。我不知道为什么过滤器会按照我描述的方式运行。非常感谢您的帮助和建议。


编辑:

作为结论,我观察到的是 /myUrl?param=value过滤器从未被应用——就好像 security-context.xml 中的条目被忽略了一样。这符合我到目前为止观察到的行为。我也试过更换 filters="none"access="permitAll" ,切换到正则表达式(并相应地更改模式 - 例如 /myUrl?param=value 变为 \A/myUrl\?param=value\Z )并且在所有变体中我得到的行为都是相同的。


编辑 2:

此处描述的问题实际上是无效的。原因如下:存在问题的项目由于内部库冲突和不兼容而排除了一些spring包,而整个设置却以某种方式运行。我从来没有意识到这一点,实际上这种不纯的配置使整个问题都过时了。具体原因是 isAuthenticated() 和 isAnonymous() 方法的实现未按预期工作,因此此处提供的任何建议均无效。

最佳答案

在 Spring Security 3.0 中,这是(可以理解的)一个常见的混淆来源,因为使用 filters="none"将带有空过滤器列表的模式添加到 FilterChainProxy而使用 access属性将安全访问规则添加到 FilterSecurityInterceptor用于保护 URL。

匹配过程为:

  1. FilterChainProxy将请求与过滤器链匹配
  2. 如果过滤器链非空,请求将由 FilterSecurityInterceptor 检查

这两个类都维护一个单独的有序匹配器列表,它们确实按照您定义它们的顺序应用,但您需要了解在下面实际上配置了两个单独的 bean,它们没有直接连接。

在一个简单的命名空间应用程序中,<http> block 正在向 FilterChainProxy 添加单个过滤器链带图案 /** .任何filters="none"您添加的模式会将空过滤器链放在实际链之前。

这种情况在 Spring Security 3.1 中有了很大改善,因为您可以使用单独的 <http> 配置单独的过滤器链。 block ,它更直观地映射到 bean 级别实际发生的事情。 request-matching process也有很多改进,现在使用 RequestMatcher一切的接口(interface)。您也可以在配置 <http> 时使用它而不是模式。 block 。

因此,您最好的选择可能是升级。然后你可以实现一个 RequestMatcher它检查是否存在您要查找的参数,例如 MyParamRequestMatcher ,然后使用:

<http request-matcher-ref="myParamMatcher" security="none" />

<bean:bean id="myParamMatcher" class="MyParamRequestMatcher" />

<http>
    <!-- Define the default filter chain configuration here -->
</http>

请注意,使用 URL 模式匹配参数通常不是很安全,因为很容易通过重新排序 URL、添加虚假模式等方式绕过它。您的情况可能没问题,因为带有参数的版本允许不安全的访问,并且您的模式需要对其他情况进行身份验证。

如果您想继续使用 3.0,最好的选择是避免使用 filters="none ”(使用 isAnonymous() 代替)并且可能使用正则表达式匹配而不是 ant 路径,以便您可以更轻松地匹配查询字符串。我要再次重申,几乎可以肯定地绕过以这种方式定义的规则,所以不要依赖在它们上以获得更高的安全性,并确保您在默认情况下是安全的。


更新:

作为对我使用正则表达式匹配和 permitAll 的建议的测试,如果我像这样修改 Spring Security 的 3.0.x 分支中的“教程”示例应用程序:

<http use-expressions="true" path-type="regex">
    <intercept-url pattern="\A/secure/extreme/.*\Z" access="hasRole('ROLE_SUPERVISOR')"/>
    <intercept-url pattern="\A/secure/index.jsp\?param=value\Z" access="permitAll" />
    <intercept-url pattern="\A/secure/.*\Z" access="isAuthenticated()" />
    <intercept-url pattern="/.*" access="permitAll" />
    ...
</http>

然后我确实得到了预期的行为:

[DEBUG,FilterChainProxy] Candidate is: '/secure/index.jsp?param=value'; pattern is /.*; matched=true
[DEBUG,FilterChainProxy] /secure/index.jsp?param=value at position 1 of 12 in additional filter chain; firing Filter: 'ConcurrentSessionFilter'
...
[DEBUG,FilterChainProxy] /secure/index.jsp?param=value at position 11 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
[DEBUG,FilterChainProxy] /secure/index.jsp?param=value at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
[DEBUG,ExpressionBasedFilterInvocationSecurityMetadataSource] Candidate is: '/secure/index.jsp?param=value'; pattern is \A/secure/extreme/.*\Z; matched=false
[DEBUG,ExpressionBasedFilterInvocationSecurityMetadataSource] Candidate is: '/secure/index.jsp?param=value'; pattern is \A/secure/index.jsp\?param=value\Z; matched=true
[DEBUG,FilterSecurityInterceptor] Secure object: FilterInvocation: URL: /secure/index.jsp?param=value; Attributes: [permitAll]

显示 FilterChainProxy.* 下匹配其次是 FilterSecurityInterceptor将确切的 URL 与参数匹配。

关于java - Spring Security - 忽略请求参数规则的URL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8908052/

有关java - Spring Security - 忽略请求参数规则的URL的更多相关文章

  1. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  2. ruby - RSpec - 使用测试替身作为 block 参数 - 2

    我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

  3. ruby-on-rails - rails : save file from URL and save it to Amazon S3 - 2

    从给定URL下载文件并立即将其上传到AmazonS3的更直接的方法是什么(+将有关文件的一些信息保存到数据库中,例如名称、大小等)?现在,我既不使用Paperclip,也不使用Carrierwave。谢谢 最佳答案 简单明了:require'open-uri'require's3'amazon=S3::Service.new(access_key_id:'KEY',secret_access_key:'KEY')bucket=amazon.buckets.find('image_storage')url='http://www.ex

  4. ruby - 如何使用 Ruby aws/s3 Gem 生成安全 URL 以从 s3 下载文件 - 2

    我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A

  5. ruby-on-rails - Rails HTML 请求渲染 JSON - 2

    在我的Controller中,我通过以下方式在我的index方法中支持HTML和JSON:respond_todo|format|format.htmlformat.json{renderjson:@user}end在浏览器中拉起它时,它会自然地以HTML呈现。但是,当我对/user资源进行内容类型为application/json的curl调用时(因为它是索引方法),我仍然将HTML作为响应。如何获取JSON作为响应?我还需要说明什么? 最佳答案 您应该将.json附加到请求的url,提供的格式在routes.rb的路径中定义。这

  6. ruby - 如何在 Ruby 中拆分参数字符串 Bash 样式? - 2

    我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"

  7. ruby - 检查方法参数的类型 - 2

    我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)

  8. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  9. ruby-on-rails - 在默认方法参数中使用 .reverse_merge 或 .merge - 2

    两者都可以defsetup(options={})options.reverse_merge:size=>25,:velocity=>10end和defsetup(options={}){:size=>25,:velocity=>10}.merge(options)end在方法的参数中分配默认值。问题是:哪个更好?您更愿意使用哪一个?在性能、代码可读性或其他方面有什么不同吗?编辑:我无意中添加了bang(!)...并不是要询问nobang方法与bang方法之间的区别 最佳答案 我倾向于使用reverse_merge方法:option

  10. ruby-on-rails - 在 Rails 和 ActiveRecord 中查询时忽略某些字段 - 2

    我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr

随机推荐