使用 OAuth2 保护服务,JWT 令牌不起作用 Spring Cloud

Posted

技术标签:

【中文标题】使用 OAuth2 保护服务,JWT 令牌不起作用 Spring Cloud【英文标题】:Protecting the service using OAuth2, JWT token not working Spring cloud 【发布时间】:2020-07-28 16:49:48 【问题描述】:

我有一个微服务架构。我正在使用 OAuth2 保护服务并使用 JWT 令牌进行配置。我在保护此微服务中的服务时遇到问题。 我已经成功实现了授权服务器。我能够生成 JWT 令牌并访问授权服务器的受保护资源。

为了保护微服务,我做了以下事情:

    在我想使用 OAuth2 保护的微服务的 pom 文件中添加了依赖项:
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-security</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.security.oauth.boot</groupId>
            <artifactId>spring-security-oauth2-autoconfigure</artifactId>
            <version>2.1.2.RELEASE</version>
        </dependency>
    修改了boostrap应用如下:
@SpringBootApplication
@EnableResourceServer
public class Application 

            ...

    创建 JwtTokenConfiguration 如下:
    private String getPublicKeyAsString() 

        try 
            Resource resource = new ClassPathResource("publickey.pem");
//          return IOUtils.toString(oAuth2ConfigProperties.getJwt().getPublicKey().getInputStream(),
//                  StandardCharsets.UTF_8);
            String strPublicKey= ".....";
            String verifierKey = String.format("-----BEGIN CERTIFICATE-----\n%s\n-----END CERTIFICATE-----", strPublicKey);
                  //verifierKey = String.format("-----BEGIN PUBLIC KEY-----\n%s\n-----END PUBLIC KEY-----", strPublicKey);

            System.out.println(verifierKey);
            return verifierKey;
         catch (Exception e) 
            throw new RuntimeException(e);
        
    

    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() 
        JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
        jwtAccessTokenConverter.setVerifierKey(getPublicKeyAsString());
        return jwtAccessTokenConverter;
    

错误如下:

    ... 33 common frames omitted
Caused by: java.lang.IllegalStateException: For MAC signing you do not need to specify the verifier key separately, and if you do it must match the signing key
    at org.springframework.util.Assert.state(Assert.java:73) ~[spring-core-5.2.4.RELEASE.jar:5.2.4.RELEASE]
    at org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter.afterPropertiesSet(JwtAccessTokenConverter.java:318) ~[spring-security-oauth2-2.3.4.RELEASE.jar:na]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1855) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1792) ~[spring-beans-5.2.4.RELEASE.jar:5.2.4.RELEASE]
    ... 53 common frames omitted

oauthcer.jks 位于授权服务器中。我通过运行以下命令从 oauthcer.jks 生成了公众:

keytool -list -rfc --keystore oauth2cer.jks

我从运行命令得到的结果如下:

-----BEGIN CERTIFICATE-----
MIIDfDCCAmSgAwIBAgIJAM8UC/xKlIfwMA0GCSqG ...
-----END CERTIFICATE-----

我在 url 中测试了结果:https://8gwifi.org/PemParserFunctions.jsp,它工作正常。

我不知道为什么它不起作用。 我已经尝试了很多东西。我会向任何指南推荐。

【问题讨论】:

【参考方案1】:

我也遇到过类似的问题。您做错了什么是将证书传递给:jwtAccessTokenConverter.setVerifierKey(getPublicKeyAsString());。您需要传递公钥。

要解决此问题,您需要从 oauth2cer.jks 中提取公钥。执行以下命令提取公钥:

keytool -list -rfc --keystore oauth2cer.jks | openssl x509 -inform pem -pubkey -noout

执行上面的命令后会显示如下结果:

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAdfsdfsdaxzcCAQ8AMIIBCgKCAQEAvJXQdLvlF1d
hx+AAzmNpuD89XPFAcmrvCt7CTGzi0bd/3WzK8dP2clxnVFANh7mbu24U91jK9ZS
3rewr4534tgfdryt54ytry6uyr
-----END PUBLIC KEY-----

上面的结果需要传递给setVerifierKey方法。

【讨论】:

以上是关于使用 OAuth2 保护服务,JWT 令牌不起作用 Spring Cloud的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot + OAuth + JWT + MySQL 刷新令牌第二次不起作用

如何撤销 JWT 令牌?

quarkus 和 jwt 令牌、application.properties var 不起作用

Spring Cloud Feign OAuth2 请求拦截器不起作用

如何在单元测试SpringBoot中解析JWT令牌

mockmvc 模拟令牌不起作用并尝试在令牌库上进行验证