1

根据教程https://blogs.sap.com/2017/07/18/step-7-with-sap-s4hana-cloud,我正在尝试启用spring security来保护我在基于Spring的SDK原型项目中的后端服务-sdk-secure-your-application-on-sap-cloud-platform-cloudfoundry/

在我本地启动应用程序后,会显示一条错误消息 - “未设置环境变量 VCAP_SERVICES”。以下是此错误的堆栈跟踪。

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfiguration': Unsatisfied dependency expressed through field 'tokenServices'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'resourceServerTokenServices' defined in class path resource [com/bosch/SecurityConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.oauth2.provider.token.ResourceServerTokenServices]: Factory method 'resourceServerTokenServices' threw exception; nested exception is java.lang.IllegalStateException: Environment variable VCAP_SERVICES not set
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:596)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:374)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1378)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:575)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:846)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:863)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:546)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:142)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:775)
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:397)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:316)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1260)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1248)
    at com.bosch.Application.main(Application.java:23)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'resourceServerTokenServices' defined in class path resource [com/bosch/SecurityConfig.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.oauth2.provider.token.ResourceServerTokenServices]: Factory method 'resourceServerTokenServices' threw exception; nested exception is java.lang.IllegalStateException: Environment variable VCAP_SERVICES not set
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:625)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:455)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1288)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1127)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:538)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498)
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
    at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:273)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.addCandidateEntry(DefaultListableBeanFactory.java:1455)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1419)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveMultipleBeans(DefaultListableBeanFactory.java:1338)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1197)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1166)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:593)
    ... 19 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.oauth2.provider.token.ResourceServerTokenServices]: Factory method 'resourceServerTokenServices' threw exception; nested exception is java.lang.IllegalStateException: Environment variable VCAP_SERVICES not set
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
    at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:620)
    ... 35 common frames omitted
Caused by: java.lang.IllegalStateException: Environment variable VCAP_SERVICES not set
    at com.sap.xs2.security.commons.SAPVcapServicesParser.parseVcapServices(SAPVcapServicesParser.java:42)
    at com.sap.xs2.security.commons.SAPVcapServicesParser.<init>(SAPVcapServicesParser.java:30)
    at com.sap.xs2.security.commons.SAPPropertyPlaceholderConfigurer.<init>(SAPPropertyPlaceholderConfigurer.java:35)
    at com.sap.xs2.security.commons.SAPOfflineTokenServicesCloud.<init>(SAPOfflineTokenServicesCloud.java:27)
    at com.bosch.SecurityConfig.resourceServerTokenServices(SecurityConfig.java:47)
    at com.bosch.SecurityConfig$$EnhancerBySpringCGLIB$$5e72219b.CGLIB$resourceServerTokenServices$1(<generated>)
    at com.bosch.SecurityConfig$$EnhancerBySpringCGLIB$$5e72219b$$FastClassBySpringCGLIB$$948b0fba.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:244)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:363)
    at com.bosch.SecurityConfig$$EnhancerBySpringCGLIB$$5e72219b.resourceServerTokenServices(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
    ... 36 common frames omitted

重现问题的步骤:</p>

  1. 基于 Spring 创建一个全新的 sdk 原型项目

  2. 取消注释掉 SecurityConfig.java 中的所有代码

  3. 导入所有安全库

  4. 在本地启动应用程序

该应用程序在 SCP Cloud Foundry 上运行良好。

我知道根本原因是应用程序将在 SecurityConfig.java 中初始化 bean 时读取环境变量 VCAP_SERVICES。但它在本地环境中找不到它。

如果我想在本地运行应用程序,有什么解决方法吗?

4

2 回答 2

2

更新:我刚刚发现我们之前有一个类似的问题和一个有用的答案:如何通过服务市场运行下载的 App Router


由于安全功能严重依赖绑定的 XSUAA 服务,以及您需要通过 AppRouter 访问您的应用程序这一事实,因此没有简单/推荐的方式来在本地启动安全应用程序。

于 2019-12-02T07:33:33.403 回答
1

我们广泛使用的一种选择是在本地使用一个脚本,该脚本设置 VCAP_SERVICES 环境变量,类似于 Cloud Foundry (cf env)。我假设,这将满足 SAPOfflineTokenServicesCloud bean 创建。

有了它,您可以在本地启动应用程序,但在应用程序受到保护时不测试您的 Web 应用程序。因为在这种情况下,您需要使用 Authorization 标头调用 Web 应用程序的端点,该标头需要包含“有效”访问令牌。如果令牌未过期并且使用与公共 RSA 密钥匹配的私有 RSA 密钥进行签名,则令牌被认为是有效的,该公共 RSA 密钥由 uaa 的 jwks 令牌端点提供,如下所述:https://docs .cloudfoundry.org/api/uaa/version/74.4.0/index.html#token-keys

您有以下选择:

这应该可以工作(我从未结合 SAP Cloud SDK 测试过该设置)。

于 2019-12-02T13:20:29.687 回答