当前位置: 首页 > 知识库问答 >
问题:

Spring Boot OAuth2资源服务器:库如何在没有公钥的情况下验证JWT令牌?

寇桐
2023-03-14

我有以下Spring启动应用程序与最小的配置

应用性质

server.port=8081
spring.security.oauth2.resourceserver.jwt.issuer-uri = http://localhost:8080/auth/realms/master

pom.xml

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.nurgasemetey</groupId>
    <artifactId>springboot-keycloak</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-keycloak</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
        </dependency>

控制器

@RestController
@RequestMapping("/users")
public class UsersController {
    @GetMapping("/status/check")
    public String status(@AuthenticationPrincipal Jwt principal) {
        return "working";
    }
}

Spring Boot Oauth2似乎不使用公钥,正如我在代码中看到的:

OAuth2ResourceServerProperties

/**
         * JSON Web Key URI to use to verify the JWT token.
         */
        private String jwkSetUri;

        /**
         * JSON Web Algorithm used for verifying the digital signatures.
         */
        private String jwsAlgorithm = "RS256";

        /**
         * URI that can either be an OpenID Connect discovery endpoint or an OAuth 2.0
         * Authorization Server Metadata endpoint defined by RFC 8414.
         */
        private String issuerUri;

        /**
         * Location of the file containing the public key used to verify a JWT.
         */
        private Resource publicKeyLocation;

但是,我没有给公共密钥位置,但应用程序可以验证没有公钥。

在引擎盖下,它使用JwtIssuerValidatorJwtTimestampValidator验证器。

另一方面,使用Express-jwt,需要公钥进行离线验证

const express = require('express');
const jwt = require('express-jwt');
const app = express();
const secret = 'secret';
const fs = require('fs');
var publicKey = fs.readFileSync('public.pub');


app.get('/protected', jwt({ secret: publicKey, algorithms: ['RS256'] }), (req, res) => {
  res.send('protected');
})
app.listen(3000, () => console.log('server started'));

Spring Boot Oauth如何在没有公钥的情况下进行验证?

共有1个答案

冷善
2023-03-14

自我回答。

首先,似乎http://localhost:8080/auth/realms/master公开了公钥。如本文所述,在KeyCloak中生成JWT令牌,并获取公钥以在第三方平台上验证JWT令牌-堆栈溢出,以及@Thomas Kāsene对此问题的评论

其次,我挖掘了Spring引导oauth2代码,并在

ReactiveOAuth2ResourceServerJwkConfiguration

@Bean
        @Conditional(IssuerUriCondition.class)
        ReactiveJwtDecoder jwtDecoderByIssuerUri() {
            return ReactiveJwtDecoders.fromIssuerLocation(this.properties.getIssuerUri());
        }

JwtDecoderProviderConfigurationUtils

private static Map<String, Object> getConfiguration(String issuer, URI... uris) {
        String errorMessage = "Unable to resolve the Configuration with the provided Issuer of " +
                "\"" + issuer + "\"";
        for (URI uri : uris) {
            try {
                RequestEntity<Void> request = RequestEntity.get(uri).build();
                ResponseEntity<Map<String, Object>> response = rest.exchange(request, typeReference);
                Map<String, Object> configuration = response.getBody();

                if (configuration.get("jwks_uri") == null) {
                    throw new IllegalArgumentException("The public JWK set URI must not be null");
                }

                return configuration;
            } catch (IllegalArgumentException e) {
                throw e;
            } catch (RuntimeException e) {
                if (!(e instanceof HttpClientErrorException &&
                        ((HttpClientErrorException) e).getStatusCode().is4xxClientError())) {
                    throw new IllegalArgumentException(errorMessage, e);
                }
                // else try another endpoint
            }
        }
        throw new IllegalArgumentException(errorMessage);
    }

它似乎从应用程序中给定的颁发者uri获取公钥。属性。获取后,它使用获取的公钥验证jwt令牌。

来测试

关闭您的jwt提供程序,在我的情况下keyCloak并运行Spring引导应用程序,然后它会给出

Caused by: java.lang.IllegalArgumentException: Unable to resolve the Configuration with the provided Issuer of "http://localhost:8080/auth/realms/master"

 类似资料:
  • “laravel/框架”:“5.7.*” “tymon/jwt认证”:“开发人员开发” 我正在尝试创建一个添加了自定义声明的JWT令牌,而不使用auth(这意味着我不希望从凭据创建令牌)。这是为了创建不需要登录的令牌,例如忘记/重置密码等。 使用Tymon/JWTAuth(https://github.com/tymondesigns/jwt-auth)由于最新的Laravel存在问题,因此建议加

  • 我有一个JWT安全令牌,需要通过jwksendpoint进行验证。jwks中的数据如下所示: 我尝试了一个第三方api,但它看起来依赖于x5c密钥,这在我的案例中不存在。 我的代码是: 如何在没有x5c的情况下通过jwks验证JWT?

  • 当客户端请求资源服务器使用OAuth2.0访问令牌获取受保护的资源时,该服务器如何验证该令牌?OAuth 2.0刷新令牌协议?

  • 我有一个Spring boot项目,它有使用kafka进行日志记录的依赖项。我无法摆脱所述依赖项,因为我的逻辑需要来自该依赖项的代码 我已尝试禁用自动配置 我尝试通过bean配置将missingTopicsFatal设置为false 但很明显,设置已经是假的,因为我的应用程序运行时没有失败,只是tomcat不想打开侦听端口 应用程序启动,但spring拒绝打开侦听端口,并继续使用错误进行循环 在本

  • 问题内容: 我试图将配置(例如URLs / etc)放入资源文件夹中,以供实用程序类使用。但是,我不想从任何地方的活动中传递上下文。我希望能够通过路径名(似乎使用assess /是为此用途设计的)来访问资源,而无需使用上下文来访问资源。 在这种特殊情况下,我希望单例实例化时在配置中使用某些东西。除了实例化期间的那一次之外,它不需要任何资源。因此,每次调用getInstance()时都必须传递Con

  • 问题内容: 我想问一下我是否可以在没有安装Web服务器的情况下运行php。我是否必须像CGI一样使用php并通过命令行运行我的页面?如果是这样,我必须通过安装php选择哪些步骤?我是说偏好设置为CGI以及该步骤之后的组件? 我安装了php 5.3.3,但似乎无法正常工作,我收到几则消息,提示缺少php5ts.dll,当我将该文件放在ext文件夹中时,会出现其他错误消息。是否需要使用任何配置文件或步