spring security全局方法安全保护切入点@EnableGlobalMethodSecurity

spring security全局方法安全保护切入点@EnableGlobalMethodSecurity,spring,spring-security,Spring,Spring Security,一个端口如何从 <sec:global-method-security secured-annotations="disabled"> <sec:protect-pointcut expression='execution(* x.y.z.end*(..))' access='...' /> ? 这里有一个类似的问题有一个解决办法。安全点信息保存在MethodSecurityMetadataSource实现中(然后由MethodInterceptor使用),因此

一个端口如何从

<sec:global-method-security secured-annotations="disabled">
    <sec:protect-pointcut expression='execution(* x.y.z.end*(..))' access='...' />
?


这里有一个类似的问题

有一个解决办法。安全点信息保存在
MethodSecurityMetadataSource
实现中(然后由
MethodInterceptor
使用),因此我们必须创建一个额外的
MethodSecurityMetadataSource
。正如spring论坛帖子中提到的,xml切入点配置保存在
MapBasedMethodSecurityMetadataSource
中,并由
ProtectPointcutPostProcessor
处理。我们还需要一个
ProtectPointcutPostProcessor
的实例。不幸的是,这个类是最终的,包是私有的,因此有两个选项:

  • 创建自己的类并复制/粘贴原始类的全部内容(我就是这么做的)
  • 使用反射更改类修饰符,并创建原始修饰符的实例(尚未这样做,因此不知道它是否可以正常工作)
  • 然后在您的上下文中创建以下bean:

    @Bean
    public Map<String, List<ConfigAttribute>> protectPointcutMap() {
        Map<String, List<ConfigAttribute>> map = new HashMap<>();
    
        // all the necessary rules go here
        map.put("execution(* your.package.service.*Service.*(..))", SecurityConfig.createList("ROLE_A", "ROLE_B"));
    
        return map;
    }
    
    @Bean
    public MethodSecurityMetadataSource mappedMethodSecurityMetadataSource() {
    
        // the key is not to provide the above map here. this class will be populated later by ProtectPointcutPostProcessor
        return new MapBasedMethodSecurityMetadataSource();
    }
    
    // it's either the original spring bean created with reflection or your own copy of it
    @Bean
    public ProtectPointcutPostProcessor pointcutProcessor() {
        ProtectPointcutPostProcessor pointcutProcessor = new ProtectPointcutPostProcessor((MapBasedMethodSecurityMetadataSource) mappedMethodSecurityMetadataSource());
        pointcutProcessor.setPointcutMap(protectPointcutMap());
        return pointcutProcessor;
    }
    
    它将把它放在列表的第一位,但这可能会导致一些问题

  • 如果希望保留其他源,但希望您的源是列表中的最后一个源,请重写以下方法:

    @Override
    protected MethodSecurityMetadataSource customMethodSecurityMetadataSource() {
        return mappedMethodSecurityMetadataSource();
    }
    
    @Override
    public MethodSecurityMetadataSource methodSecurityMetadataSource() {
        DelegatingMethodSecurityMetadataSource metadataSource = (DelegatingMethodSecurityMetadataSource) super.methodSecurityMetadataSource();
        metadataSource.getMethodSecurityMetadataSources().add(mappedMethodSecurityMetadataSource());
        return metadataSource;
    }
    
  • 如果您希望源代码是唯一的源代码(您不希望使用
    @Secured
    或任何其他注释),那么您可以覆盖相同的方法,只是使用不同的内容

    @Override
    public MethodSecurityMetadataSource methodSecurityMetadataSource() {
        return mappedMethodSecurityMetadataSource();
    }
    

  • 就这样!我希望它会有所帮助,因为我遵循了@marhewa注释,并且能够通过定义以下bean来使用类的Spring版本
    ProtectPointcutPostProcessor

      /**
       * Needed to use reflection because I couldn't find a way to instantiate a
       * ProtectPointcutPostProcessor via a BeanFactory or ApplicationContext. This bean will process
       * the AspectJ pointcut defined in the map; check all beans created by Spring; store the matches
       * in the MapBasedMethodSecurityMetadataSource bean so Spring can use it during its checks
       * 
       * @return
       * @throws Exception
       */
      @Bean(name = "protectPointcutPostProcessor")
      Object protectPointcutPostProcessor() throws Exception {
        Class<?> clazz =
            Class.forName("org.springframework.security.config.method.ProtectPointcutPostProcessor");
    
        Constructor<?> declaredConstructor =
            clazz.getDeclaredConstructor(MapBasedMethodSecurityMetadataSource.class);
        declaredConstructor.setAccessible(true);
        Object instance = declaredConstructor.newInstance(pointcutMethodMetadataSource());
        Method setPointcutMap = instance.getClass().getMethod("setPointcutMap", Map.class);
        setPointcutMap.setAccessible(true);
        setPointcutMap.invoke(instance, pointcuts());
    
        return instance;
      }
    
    /**
    *需要使用反射,因为我找不到实例化
    *通过BeanFactory或ApplicationContext保护PointCutPostProcessor。这个bean将处理
    *地图中定义的AspectJ切入点;检查Spring创建的所有bean;储存火柴
    *在MapbasedMethodSecurityMetadataSourcebean中,这样Spring就可以在其检查期间使用它
    * 
    *@返回
    *@抛出异常
    */
    @Bean(name=“protectPointcutPostProcessor”)
    对象protectPointcutPostProcessor()引发异常{
    课堂讨论=
    forName(“org.springframework.security.config.method.ProtectPointcutPostProcessor”);
    构造函数声明构造函数=
    getDeclaredConstructor(MapBasedMethodSecurityMetadataSource.class);
    declaredConstructor.setAccessible(true);
    对象实例=declaredConstructor.newInstance(pointcutMethodMetadataSource());
    方法setPointcutMap=instance.getClass().getMethod(“setPointcutMap”,Map.class);
    setPointcutMap.setAccessible(真);
    调用(实例,pointcuts());
    返回实例;
    }
    
    这样我就不需要复制这个Spring类的代码

    干杯

      /**
       * Needed to use reflection because I couldn't find a way to instantiate a
       * ProtectPointcutPostProcessor via a BeanFactory or ApplicationContext. This bean will process
       * the AspectJ pointcut defined in the map; check all beans created by Spring; store the matches
       * in the MapBasedMethodSecurityMetadataSource bean so Spring can use it during its checks
       * 
       * @return
       * @throws Exception
       */
      @Bean(name = "protectPointcutPostProcessor")
      Object protectPointcutPostProcessor() throws Exception {
        Class<?> clazz =
            Class.forName("org.springframework.security.config.method.ProtectPointcutPostProcessor");
    
        Constructor<?> declaredConstructor =
            clazz.getDeclaredConstructor(MapBasedMethodSecurityMetadataSource.class);
        declaredConstructor.setAccessible(true);
        Object instance = declaredConstructor.newInstance(pointcutMethodMetadataSource());
        Method setPointcutMap = instance.getClass().getMethod("setPointcutMap", Map.class);
        setPointcutMap.setAccessible(true);
        setPointcutMap.invoke(instance, pointcuts());
    
        return instance;
      }