Java Spring安全oauth2.0(无效令牌不包含资源id(oauth2资源))

Java Spring安全oauth2.0(无效令牌不包含资源id(oauth2资源)),java,spring,spring-boot,spring-security,oauth-2.0,Java,Spring,Spring Boot,Spring Security,Oauth 2.0,我使用springboot和springrest编写了一个简单的restapi后端。 端点将被各种第三方应用程序使用,并按预期工作 现在我想使用spring安全性和OAUTH 2.0保护这些端点 我计划使用外部OAuth 2.0授权服务器,这样我的rest api后端(spring boot应用程序)将充当资源服务器,并通过调用外部授权服务器的令牌内省端点来验证访问令牌 每当客户机应用程序在授权标头中使用访问令牌(使用客户端凭据授权类型从外部authz服务器获得的不透明承载令牌)调用myapi端

我使用
springboot
springrest
编写了一个简单的restapi后端。 端点将被各种第三方应用程序使用,并按预期工作

现在我想使用spring安全性和OAUTH 2.0保护这些端点

我计划使用外部
OAuth 2.0
授权服务器,这样我的
rest api后端
(spring boot应用程序)将充当资源服务器,并通过调用外部授权服务器的令牌内省端点来验证访问令牌

每当客户机应用程序在授权标头中使用访问令牌(使用客户端凭据授权类型从外部authz服务器获得的不透明承载令牌)调用my
api端点时,Spring总是抛出以下错误:

{
    "error": "access_denied",
    "error_description": "Invalid token does not contain resource id (oauth2-resource)"
}
在做了一些研究之后,通过以下方式将调用应用程序的客户端ID设置为资源ID解决了此问题:

 public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.tokenServices(tokenService());
         resources.resourceId("5ght-6117-fdc6-8787-9017-20c784a9c03a");
        //  super.configure(resources);
    }
Spring似乎根据资源ID中设置的值验证来自令牌内省响应的
aud
声明

我不能完全理解这一点,为什么春天会这样

作为一个资源服务器,它应该简单地检查访问令牌是否有效,是否具有正确的作用域等

是Spring维护了一个允许客户端的白名单吗

在我的例子中,有多个客户端应用程序将访问
restapi后端
,那么如何存储它们的多个客户端id呢

pom.xml


4.0.0
org.springframework.boot
spring启动程序父级
2.2.2.1发布
com.example
弹簧安全性试验
0.0.1-快照
弹簧安全性试验
SpringBoot的演示项目
1.8
org.springframework.boot
弹簧启动安全
org.springframework.security.oauth.boot
spring-security-oauth2-autoconfigure
2.2.2.1发布
org.springframework.boot
SpringBootStarterWeb
org.springframework.boot
弹簧靴开发工具
运行时
真的
org.springframework.boot
弹簧起动试验
测试
org.junit.vintage
朱尼特老式发动机
org.springframework.security
弹簧安全性试验
测试
org.springframework.boot
springbootmaven插件

PS:我已经检查了许多关于这个主题的其他类似问题,但是找不到我在这里提出的问题的答案。

当客户端与身份提供者进行身份验证时,它可以选择包含资源标识符。在标识提供程序上配置客户机时,通常可以选择需要资源标识符(如果客户机不提供资源标识符,则认证将失败),或者可以选择指定该客户机的默认值

您正在构建一个资源服务器,并且可以为其分配任何标识符,只要该标识符对于标识提供程序是唯一的。我通常使用我的服务的URL作为资源标识符。有时,当我希望跨不同URL使用相同的资源标识符时(就像我在开发、QA和生产环境之间使用的那样),我会创建一个URN(例如,URN:uuid:01234567-89ab-cdef-0123-456789abcdef),但只有一个标识提供程序

resources.resourceId(null); // Disabled since Microsoft does not support resource ids.
这听起来像是您的身份提供者在未提供访问群体时使用了访问群体,这是一个合理的默认设置,因为在您的情况下,您的资源服务既是访问群体又是资源。然而,情况并非总是如此

考虑一下Facebook希望访问你的Gmail联系人的情况。在这种情况下,Gmail是资源,Facebook是受众。作为身份提供商,谷歌将询问用户是否希望允许Facebook访问他的联系人。如果用户授予访问权限(这种情况只发生一次),谷歌将提供令牌。否则,身份验证将失败

范围是一个不同的概念。资源提供者可以决定将资源中的可用数据分成多个子部分;每个小节都有一个名称(或范围)。在我们上面的例子中,Gmail可以将联系人的数据分为姓名、家庭地址、电话号码、电子邮件地址、twitter句柄等。当用户授予Facebook访问其联系人列表的权限时,他可以将Facebooks的访问权限限制为仅访问姓名和电子邮件地址,从而禁止访问联系人的家庭地址、电话号码和twitter提要。由资源提供者(即您的服务)来实施此约束

通过在上面的代码中将值设置为null,可以禁用Spring对资源标识符的验证。这就是当Azure Active Directory是我的身份提供者时我所使用的

resources.resourceId(null); // Disabled since Microsoft does not support resource ids.

当客户端与身份提供者进行身份验证时,它可以选择包括资源标识符。在标识提供程序上配置客户机时,通常可以选择需要资源标识符(如果客户机不提供资源标识符,则认证将失败),或者可以选择指定该客户机的默认值

您正在构建一个资源服务器,并且可以为其分配任何标识符,只要该标识符对于标识提供程序是唯一的。我通常使用我的服务的URL作为资源标识符。有时,当我希望在不同的URL上使用相同的资源标识符时(就像我在开发人员、QA和管理员之间使用的一样),我会创建一个URN(例如,URN:uuid:01234567-89ab-cdef-0123-456789abcdef)