如何确定使用 Spring Security 访问 URL 需要哪些角色?

Posted

技术标签:

【中文标题】如何确定使用 Spring Security 访问 URL 需要哪些角色?【英文标题】:How can I determine what roles are required to access a URL with Spring Security? 【发布时间】:2010-10-02 00:30:25 【问题描述】:

我正在使用 Spring Security 来保护 webapp。 URL 的保护方式如下:

<security:http entry-point-ref="authenticationEntryPoint">
  <security:intercept-url pattern="/" access="ROLE_ANONYMOUS" />
  <security:intercept-url pattern="/assets/**/*" access="ROLE_ANONYMOUS" />
  ...
  <security:intercept-url pattern="/**" access="ROLE_USER" />
  <security:anonymous granted-authority="ROLE_ANONYMOUS" />
</security:http>

我有一个过滤器需要在某些情况下将用户重定向到一个特殊页面。但是,该页面需要资产目录中的图像和 CSS 文件,不幸的是,这些文件也会被重定向到该特殊页面。我不希望过滤器手动检查每个 URL 模式,因为我的实际 URL 配置要长得多,而且我还希望允许其他页面。

有没有办法从给定页面的过滤器中确定需要哪些角色?如果不需要 ROLE_ANONYMOUS,我可以选择不重定向。

【问题讨论】:

【参考方案1】:

假设您使用的是 Spring Security 3,该信息的来源(为特定路径配置的属性/角色)是注入到 FilterSecurityInterceptor 中的 FilterInvocationSecurityMetadataSource。因此,如果您有特定的 URL,则可以通过将 FilterInvocation(从请求和响应创建)传递给 FilterInvocationSecurityMetadataSource 的 getAttributes() 方法来查询配置的属性。

获取对命名空间创建的内部 bean 的引用可能有点棘手。假设您有自己的 bean(或 bean)要从中进行调用,您可以通过将 BeanPostProcessor 添加到应用程序上下文中来将其注入到它们中,其实现方式如下:

public class FilterSecurityMDSExtractor implements BeanPostProcessor, BeanFactoryAware 
    private ConfigurableListableBeanFactory bf;

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException 
        if (bean instanceof FilterInvocationSecurityMetadataSource) 
            // Get your own bean from the BeanFactory here and inject the SecurityMetadataSource into it
        
        return bean;
    

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException 
        return bean;
        

    public void setBeanFactory(BeanFactory beanFactory) throws BeansException 
        this.bf = (ConfigurableListableBeanFactory)beanFactory;
       

请注意,Spring Security 会在上下文中自动注册一个 WebInvocationPrivilegeEvaluator,它可用于检查用户是否能够在不实际调用特定 URL 的情况下调用它。这很相似,因为它查询 SecurityMetadataSource,但不完全是您在此处所追求的。

【讨论】:

【参考方案2】:

不要忘记,在决定是否允许访问时实际发生的情况是 URL 和现有身份验证通过一系列 AccessDecisionVoters 传递,其中一个默认值是 RoleVoter。此投票者检查所请求资源的配置,如果需要特定角色,如果现有身份验证没有该角色,则将拒绝该请求。

因此,对于解决方案 - 您可以在角色投票者之前添加其他投票者。每个选民必须返回 GRANT、DENY 或 ABSTAIN,并且只有在返回 ABSTAIN 时才会继续处理后续的选民。因此,您可以编写自己的自定义投票器(如果可行,也可以重用现有的投票器),在角色投票器之前触发它,并无条件地授予对您所指资源的任何请求的访问权限。

我在当前项目中做过类似的事情,其中​​某些特定于应用程序的临时属性可以让某人访问通常他们无法访问的资源,并且作为一种方法效果很好。

【讨论】:

这是个好主意,但它并没有完全让我明白。问题是,无论用户是否有权访问,过滤器都会启动并重定向到特殊页面。我需要一些方法让过滤器知道它什么时候不应该重定向,并且知道 URL 所需的角色可以做到这一点。

以上是关于如何确定使用 Spring Security 访问 URL 需要哪些角色?的主要内容,如果未能解决你的问题,请参考以下文章

Spring security - 允许导航但保护某些页面

Spring Security中登录后如何访问资源?

如何提供访问权限(Spring Security)[关闭]

如何允许使用 Spring Security 访问特定的 React 哈希路由?

如何使用spring security根据角色限制对html页面的访问?

如何使用 Spring boot keycloak 适配器 + spring security 强制更新 oAuth 令牌(访问令牌 + 刷新令牌)。?