Spring Boot OAuth2 手动创建新的 JWT 令牌

Posted

技术标签:

【中文标题】Spring Boot OAuth2 手动创建新的 JWT 令牌【英文标题】:Spring Boot OAuth2 manually create new JWT token 【发布时间】:2017-06-02 00:13:57 【问题描述】:

在我的 Spring Boot 应用程序中,我已经使用 JWT 令牌配置了 Spring OAuth2 服务器。

我还添加了 Spring Social 配置,以便能够通过 Twitter、Facebook 等各种社交网络对用户进行身份验证。

这是我的SpringSocial 配置:

@Configuration
@EnableSocial
public class SocialConfig extends SocialConfigurerAdapter 

    @Bean
    public ProviderSignInController providerSignInController(ConnectionFactoryLocator connectionFactoryLocator, UsersConnectionRepository usersConnectionRepository) 
        return new ProviderSignInController(connectionFactoryLocator, usersConnectionRepository, new SimpleSignInAdapter(authTokenServices, "client_id", userService));
    

...


另外,根据人们的回答 Integrate Spring Security OAuth2 and Spring Social 我已经实现了 SimpleSignInAdapter 以处理与 3rdparty 社交网络的成功身份验证:

public class SimpleSignInAdapter implements SignInAdapter 

    final static Logger logger = LoggerFactory.getLogger(SimpleSignInAdapter.class);

    public static final String REDIRECT_PATH_BASE = "/#/login";
    public static final String FIELD_TOKEN = "access_token";
    public static final String FIELD_EXPIRATION_SECS = "expires_in";

    private final AuthorizationServerTokenServices authTokenServices;
    private final String localClientId;
    private final UserService userService;

    public SimpleSignInAdapter(AuthorizationServerTokenServices authTokenServices, String localClientId, UserService userService)
        this.authTokenServices = authTokenServices;
        this.localClientId = localClientId;
        this.userService = userService;
    

    @Override
    public String signIn(String userId, Connection<?> connection, NativeWebRequest request) 

        UserDetails userDetails = loadUserById(Long.parseLong(userId));

        OAuth2AccessToken oauth2Token = authTokenServices.createAccessToken(convertAuthentication(userDetails)); 
        String redirectUrl = new StringBuilder(REDIRECT_PATH_BASE)
            .append("?").append(FIELD_TOKEN).append("=")
            .append(encode(oauth2Token.getValue()))
            .append("&").append(FIELD_EXPIRATION_SECS).append("=")
            .append(oauth2Token.getExpiresIn())
            .toString();    

        return redirectUrl;
    

    private OAuth2Authentication convertAuthentication(UserDetails userDetails) 
        OAuth2Request request = new OAuth2Request(null, localClientId, null, true, null, null, null, null, null);
        return new OAuth2Authentication(request, new UsernamePasswordAuthenticationToken(userDetails, "N/A", userDetails.getAuthorities()));
    

    private String encode(String in) 
        String res = in;
        try 
            res = UriUtils.encode(in, "UTF-8");
         catch(UnsupportedEncodingException e)
            logger.error("ERROR: unsupported encoding: " + "UTF-8", e);
        
        return res;
    

    public UserDetails loadUserById(Long id) throws UsernameNotFoundException 
        User user = userService.findUserById(id);
        if (user == null) 
            throw new UsernameNotFoundException("User " + id + " not found.");
        

        Set<Permission> permissions = userService.getUserPermissions(user);
        return new DBUserDetails(user, permissions);
    


除一件事外,一切正常 - 以下代码行生成普通的 OAuth2 访问令牌:

OAuth2AccessToken oauth2Token = authTokenServices.createAccessToken(convertAuthentication(userDetails));

但我需要创建 JWT 令牌。

如何创建或将此令牌转换为基于 JWT 的?我想我可以为此目的使用JwtAccessTokenConverter 类,但目前不知道如何。

【问题讨论】:

【参考方案1】:

经过调试我找到了解决办法:

private final TokenEnhancer tokenEnhancer;

...
OAuth2Authentication authentication = convertAuthentication(userDetails);
OAuth2AccessToken accessToken = authTokenServices.createAccessToken(authentication); 
accessToken = tokenEnhancer.enhance(accessToken, authentication);

【讨论】:

【参考方案2】:

在我想要自己的自定义 JWT 令牌之后,这对我有用。

DefaultTokenServices service = new DefaultTokenServices(); 
    service.setTokenStore(jwtAccessTokenConverter);
    service.setTokenEnhancer(jwtAccessTokenConverter);
    OAuth2AccessToken token = service.createAccessToken(authentication);

自动装配 jwtAccessTokenConverter

@Autowired
private JwtAccessTokenConverter jwtAccessTokenConverter;

【讨论】:

以上是关于Spring Boot OAuth2 手动创建新的 JWT 令牌的主要内容,如果未能解决你的问题,请参考以下文章

创建隐式JWT时的Spring Boot OAuth2?

Webflux - Spring Boot - 具有 http 代理支持的 oAuth2 客户端

Spring Boot OAuth2 - 无法从令牌获取用户详细信息

Spring boot 2.0.3 + 安全 + Oauth2 自动配置

带有 Spring Boot REST 应用程序的 OAuth2 - 无法使用令牌访问资源

如何在 Spring Boot 中实现 oAuth2 和 JWT 身份验证? [关闭]