如何以编程方式检查某个 URL 是不是需要使用 Spring Security 进行身份验证?

Posted

技术标签:

【中文标题】如何以编程方式检查某个 URL 是不是需要使用 Spring Security 进行身份验证?【英文标题】:How to programmatically check if a certain URL needs authentication with Spring Security?如何以编程方式检查某个 URL 是否需要使用 Spring Security 进行身份验证? 【发布时间】:2014-08-13 16:03:23 【问题描述】:

有没有办法使用 Spring Security (v 3.1.x) 以编程方式获取某个 URL 的授权规则

我的意思是...假设我设置:

<security:intercept-url pattern="/**" access="isAuthenticated()" />

在我的配置中。

在处理/internal/** 路径的控制器中,我想知道我是否需要身份验证才能访问某个路径。像这样的方法:

boolean isAuthenticationRequired(String ulr);

可能有用。

我可以通过SecurityContextHolder获得这些信息吗?

UPDATE四处搜索,似乎关键可能是SecurityMetadataSource...

【问题讨论】:

这不是您问题的答案,而是可能对您有所帮助的提示。尝试在身份验证期间引发异常。分析堆栈跟踪并找到执行身份验证的代码。环顾四周,您将看到所需的 API。祝你好运。 @AlexR 感谢您的建议。 没问题。祝你好运。找到解决方案后,请发布“正确”的自我答案。 @AlexR 我希望能找到它... :D 【参考方案1】:

如果您使用基于模式的配置,我认为这是获取 SecurityMetadataSource 和规则的唯一(也是丑陋的)方法:

@Autowired
private ApplicationContext applicationContext;

public void someMethod()
    FilterSecurityInterceptor fsi = applicationContext.getBean(org.springframework.security.web.access.intercept.FilterSecurityInterceptor.class);
    FilterInvocationSecurityMetadataSource sms = fsi.getSecurityMetadataSource();

    try 
        Field field = sms.getClass().getDeclaredField("requestMap");
        field.setAccessible(true);
        Map<RequestMatcher, Collection<ConfigAttribute>> requestMap = (Map<RequestMatcher, Collection<ConfigAttribute>>)field.get(sms);
        Set<Entry<RequestMatcher, Collection<ConfigAttribute>>> entrySet = requestMap.entrySet();
        for (Entry<RequestMatcher, Collection<ConfigAttribute>> entry : entrySet) 
            AntPathRequestMatcher path = (AntPathRequestMatcher)entry.getKey();                     
            System.out.println(path.getPattern());
                            //prints sthg like /action/index
            Collection<ConfigAttribute> roles = entry.getValue();
            System.out.println(roles);
                            //[ROLE_USER,ROLE_ADMIN]
        
     catch (Exception e) 
        //TODO
        e.printStackTrace();
    

使用它,您可以轻松地编写实用程序服务来检查 URL。

替代方案更简洁,但最终更冗长:如果您不使用基于模式的配置,则可以更轻松地访问包含映射的 bean (interceptedUrls):

<bean id="fsi" class="org.springframework.security.web.access.intercept.FilterSecurityInterceptor">
    <property name="authenticationManager" ref="authenticationManager"/>
    <property name="accessDecisionManager" ref="httpRequestAccessDecisionManager"/>
    <property name="securityMetadataSource" ref="interceptedUrls"/>
</bean>


<sec:filter-invocation-definition-source id="interceptedUrls">       
    <sec:intercept-url pattern="/action/login" access="ROLE_ANONYMOUS"/>
    <sec:intercept-url pattern="/action/passwordReset" access="ROLE_ANONYMOUS"/>        

    <sec:intercept-url pattern="/action/index" access="ROLE_ADMIN"/>
    ...

希望这会有所帮助!

【讨论】:

+1 我会避免反思,但我认为这可能是一个好的(丑陋的)建议。谢谢。

以上是关于如何以编程方式检查某个 URL 是不是需要使用 Spring Security 进行身份验证?的主要内容,如果未能解决你的问题,请参考以下文章

C#:如何以编程方式检查 Web 服务是不是已启动并正在运行?

如何检查 CComBSTR 是不是以某个前缀开头?

如何使用 c# 检查 OpenOffice 是不是以编程方式安装

如何以编程方式检查 iOS 应用程序中是不是存在键盘?

如何检查java中是不是存在某个.txt文件[重复]

如何以编程方式检查系统上是不是安装了 SQL Server Management Studio?