Spring Security OAuth2 中的 JwtAccessTokenConverter

介绍

JwtAccessTokenConverter 是 Spring Security OAuth2 中的一个类,用于处理 JWT(JSON Web Token)的生成和验证。它在授权服务器和资源服务器之间起着关键作用,确保令牌的完整性和真实性。

JwtAccessTokenConverter 的角色和作用

在授权服务器中

  • JwtAccessTokenConverter 用于生成和签名 JWT。
  • 授权服务器使用私钥对 JWT 进行签名,以确保令牌的完整性和真实性。

在资源服务器中

  • JwtAccessTokenConverter 用于验证和解码 JWT。
  • 资源服务器使用公钥验证 JWT 的签名,以确保令牌未被篡改,并从中提取相关的声明(claims)。

JwtAccessTokenConverter 的具体功能

  1. 令牌转换(Token Conversion)

    • 将 OAuth2 访问令牌转换为 JWT。
    • 将 JWT 解码为 OAuth2 访问令牌。
  2. 签名和验证(Signing and Verification)

    • 在授权服务器中使用私钥对 JWT 进行签名。
    • 在资源服务器中使用公钥验证 JWT 的签名。

授权服务器、资源服务器和 JwtAccessTokenConverter 之间的关系

授权服务器

授权服务器负责认证用户并颁发令牌。配置授权服务器时,会使用 JwtAccessTokenConverter 来生成和签名 JWT。示例配置如下:

import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;

import java.security.KeyPair;

@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(accessTokenConverter());
    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        KeyPair keyPair = new KeyStoreKeyFactory(
            new ClassPathResource("cxs-jwt.jks"), "cxs123".toCharArray())
            .getKeyPair("cxs-jwt");
        converter.setKeyPair(keyPair);
        return converter;
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        endpoints.tokenStore(tokenStore()).accessTokenConverter(accessTokenConverter());
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
    }
}

资源服务器

资源服务器保护资源,并在每个请求中验证 JWT 的有效性。配置资源服务器时,也会使用 JwtAccessTokenConverter 来验证 JWT 的签名。示例配置如下

import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.oauth2.provider.token.TokenStore;

import java.io.IOException;
import java.nio.charset.Charset;

public class ResourceConfig extends ResourceServerConfigurerAdapter {

    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(jwtAccessTokenConverter());
    }

    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter();
        ClassPathResource resource = new ClassPathResource("jwt-publicKey.txt");
        try {
            String publicKey = FileUtil.readString(resource.getFile(), Charset.defaultCharset());
            jwtAccessTokenConverter.setVerifierKey(publicKey);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return jwtAccessTokenConverter;
    }

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.tokenStore(tokenStore());
    }
}

工作流程

  1. 客户端请求令牌

    • 客户端(如 Web 应用或移动应用)向授权服务器请求访问令牌。
    • 授权服务器认证客户端身份,并生成 JWT。
    • JwtAccessTokenConverter 使用私钥对 JWT 进行签名。
    • 签名后的 JWT 返回给客户端。
  2. 客户端请求受保护资源

    • 客户端使用 JWT 请求资源服务器的受保护资源。
    • 资源服务器接收到 JWT,并使用 JwtAccessTokenConverter 进行解码和签名验证。
    • JwtAccessTokenConverter 使用公钥验证 JWT 的签名。
    • 如果签名验证通过,资源服务器允许访问受保护资源;如果验证失败,拒绝访问。

具体方法解释

configure(AuthorizationServerEndpointsConfigurer endpoints)

@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
    endpoints.tokenStore(tokenStore()).accessTokenConverter(accessTokenConverter());
}
  • tokenStore(tokenStore())

    • 指定用于存储令牌的策略。在这里使用 JwtTokenStore
    • JwtTokenStore 是一个 TokenStore 的实现,用于存储 JWT。
  • accessTokenConverter(accessTokenConverter())

    • 指定用于访问令牌转换的策略。在这里使用 JwtAccessTokenConverter
    • JwtAccessTokenConverter 用于将 OAuth2 访问令牌转换为 JWT,并在授权服务器中使用私钥对 JWT 进行签名。

configure(AuthorizationServerSecurityConfigurer security)

@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
    security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
}

这段代码的作用是配置授权服务器的安全性,具体包括以下两方面:

  1. tokenKeyAccess("permitAll()")

    • 允许所有人访问令牌密钥端点。
    • 通常,这个端点提供的是公钥,客户端和资源服务器可以通过这个端点获取公钥,用于验证 JWT 的签名。
    • 公开访问公钥是安全的,因为公钥仅用于验证签名,而不能用于生成签名。
  2. checkTokenAccess("isAuthenticated()")

    • 要求对令牌检查的访问需要身份验证。
    • 这意味着只有经过认证的客户端才能访问检查令牌的端点,确保只有合法的客户端可以进行令牌验证请求。

运行流程

  1. 令牌生成和存储

    • 客户端请求令牌时,授权服务器使用 JwtAccessTokenConverter 生成 JWT,并存储在 JwtTokenStore 中。
  2. 公钥访问

    • 客户端或资源服务器可以访问 /oauth/token_key 端点获取公钥,用于验证 JWT 的签名。
  3. 令牌检查

    • 客户端或资源服务器可以访问 /oauth/check_token 端点检查令牌的有效性,但必须经过身份验证才能访问该端点。

总结

  • configure(AuthorizationServerEndpointsConfigurer endpoints) 配置了授权服务器的端点,指定了如何存储和转换令牌。
  • configure(AuthorizationServerSecurityConfigurer security) 配置了授权服务器的安全性,定义了公钥访问和令牌检查的访问规则。

这些配置确保了授权服务器能够安全地生成和管理 JWT,并提供必要的端点供客户端和资源服务器访问。

  • 26
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Security OAuth2 Authorization Server可以通过Token增强器(Token Enhancer)来为授权后返回的Access Token添加额外的信息。Token增强器是一个接口,它接收一个Access Token并返回一个增强后的Access Token。在Authorization Server配置类,可以通过调用tokenEnhancer()方法来设置Token增强器,示例代码如下: ```java @Configuration @EnableAuthorizationServer public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private AuthenticationManager authenticationManager; @Autowired private UserDetailsService userDetailsService; @Autowired private DataSource dataSource; @Bean public TokenStore tokenStore() { return new JdbcTokenStore(dataSource); } @Bean public JwtAccessTokenConverter accessTokenConverter() { JwtAccessTokenConverter converter = new JwtAccessTokenConverter(); converter.setSigningKey("123456"); return converter; } @Bean public TokenEnhancer tokenEnhancer() { return new CustomTokenEnhancer(); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.jdbc(dataSource); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.authenticationManager(authenticationManager) .userDetailsService(userDetailsService) .tokenStore(tokenStore()) .accessTokenConverter(accessTokenConverter()) .tokenEnhancer(tokenEnhancer()); } @Override public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception { oauthServer.tokenKeyAccess("permitAll()") .checkTokenAccess("isAuthenticated()") .allowFormAuthenticationForClients(); } } ``` 在上面的代码,CustomTokenEnhancer是一个自定义的Token增强器,它可以在Access Token添加额外的信息。示例代码如下: ```java public class CustomTokenEnhancer implements TokenEnhancer { @Override public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) { Map<String, Object> additionalInfo = new HashMap<>(); additionalInfo.put("organization", authentication.getName() + "@test.com"); ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo); return accessToken; } } ``` 在上面的代码,我们向Access Token添加了一个名为“organization”的信息,它的值为当前用户的用户名加上@test.com。这种方式可以为Access Token添加任何我们需要的信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值