为什么 OAuth2 身份验证服务器 returns 401 错误与 jdbc 数据源?

Why does OAuth2 authentication server returns 401 error with jdbc datasource?

我正在使用 JWT 实现 OAUTH2 身份验证服务器。 如果我使用 inMemory () 令牌,我可以正常访问。 但是,如果我使用 jdbc(数据源),它总是 returns 错误 401。有人能帮忙吗?

我的 AuthorizationServerConfigurerAdapter

@Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(tokenStore()).authenticationManager(authenticationManager)
                .tokenEnhancer(jwtAccessTokenConverter()).userDetailsService(userDetailsService)
                .requestFactory(customOauth2RequestFactory.requestFactory());

    }

我的tokenStore

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

还有我的 jwtAccessTokenConverter

@Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        var converteToken = new CustomToken();
        converteToken.setKeyPair(new KeyStoreKeyFactory(new ClassPathResource("jwt.jks"), "password".toCharArray())
                .getKeyPair("jwt"));
        return converteToken;
    }

我的 CustomToken extends extends JwtAccessTokenConverter

    @Override
        public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
            var user = userRepository.findByLogin(authentication.getName());
            Map<String, Object> additionalInformation = new HashMap<>() {{

            put("idFuncionario", usuario.getIdFuncionario());
            put("idEmpresa", usuario.getIdEmpresa());
            put("perfis", usuario.descricaoPerfil());
            put("login", usuario.getLogin());
        }};
        var defaultOAuth2AccessToken = new DefaultOAuth2AccessToken(accessToken);
        defaultOAuth2AccessToken.setAdditionalInformation(additionalInformation);
        return super.enhance(defaultOAuth2AccessToken, authentication);
    }

现在,我的 JDBC 在 AuthorizationServerConfigurerAdapter

@Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.jdbc(dataSource).passwordEncoder(passwordEncoder());
    }

我的 CustomFactory 扩展了 DefaultOAuth2RequestFactory

@Override
    public TokenRequest createTokenRequest(Map<String, String> requestParameters, ClientDetails authenticatedClient) {
        if (requestParameters.get("grant_type").equals("refresh_token")) {
            var authentication = tokenStore.readAuthenticationForRefreshToken(tokenStore.readRefreshToken(requestParameters
                    .get("refresh_token")));
            SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(
                    authentication.getName(), null, userDetailsService.loadUserByUsername(authentication.getName())
                    .getAuthorities()));
        }
        return super.createTokenRequest(requestParameters, authenticatedClient);
    }

还有我的 JWT 实体

@Entity
@Table(name = "oauth_client_details")
public class OAuthClientDetails extends AbstractEntity {

    private String clientId;
    private String clientSecret;
    private String resourceIds;
    private String scope;
    private String authorizedGrantTypes;
    private String webServerRedirectUri;
    private String authorities;
    private Integer accessTokenValidity;
    private Integer refreshTokenValidity;
    private String additionalInformation;
    private String autoapprove;

    contructor / geters / seters

我的解决方案:

我在扩展 AuthorizationServerConfigurerAdapter

的 class 中创建了这个方法
 @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.withClientDetails(clientService);
    }

而这项服务:

@Service
public class ClientService implements ClientDetailsService {

    @Autowired
    private ClienteRepository clienteRepository;

    @Override
    public ClientDetails loadClientByClientId(String clientId) throws ClientRegistrationException {

        var cliente = clienteRepository.findById(clientId);


        var clienteDetail = new ClienteDetalhes(
                cliente.get().getClientId(),
                String.join(",", cliente.get().getResourceIds()),
                cliente.get().getClientSecret(),
                String.join(",", cliente.get().getScope()),
                String.join(",", cliente.get().getAuthorizedGrantTypes()),
                String.join(",", cliente.get().getRegisteredRedirectUri()),
                null,
                cliente.get().getAccessTokenValiditySeconds(),
                cliente.get().getRefreshTokenValiditySeconds(),
                cliente.get().getAutoApproveScope(),
                null);
        return clienteDetail;

    }
}

还有这个实体

@Getter
@Setter
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Table(schema = "cliente")
public class ClienteDetalhes implements Serializable, ClientDetails {

    private static final ObjectMapper mapper = new ObjectMapper();

    @Id
    @Column(nullable = false, unique = true)
    private String clientId;
    private String resourceIds;
    private String clientSecret;
    private String scope;
    @Column(nullable = false)
    private String authorizedGrantTypes;
    private String registeredRedirectUri;
    private String authorities;
    @Column(nullable = false)
    private Integer accessTokenValiditySeconds;
    @Column(nullable = false)
    private Integer refreshTokenValiditySeconds;
    private String autoApproveScope;
    private String additionalInformation;

    @Override
    public boolean isSecretRequired() {
        return !StringUtils.isEmpty(this.clientSecret);
    }

    @Override
    public boolean isAutoApprove(String scope) {
        return false;
    }

    @Override
    public Map<String, Object> getAdditionalInformation() {
        try {
            return mapper.readValue(this.additionalInformation, Map.class);
        } catch (IOException e) {
            return new HashMap<>();
        }
    }

    @Override
    public Collection<GrantedAuthority> getAuthorities() {
        Set<String> set = StringUtils.commaDelimitedListToSet(this.authorities);
        Set<GrantedAuthority> result = new HashSet<>();
        set.forEach(authority -> result.add(new GrantedAuthority() {
            @Override
            public String getAuthority() {
                return authority;
            }
        }));
        return result;
    }

    @Override
    public Set<String> getRegisteredRedirectUri() {
        return StringUtils.commaDelimitedListToSet(this.registeredRedirectUri);
    }

    @Override
    public Set<String> getAuthorizedGrantTypes() {
        return StringUtils.commaDelimitedListToSet(this.authorizedGrantTypes);
    }

    @Override
    public boolean isScoped() {
        return this.getScope().size() > 0;
    }

    @Override
    public Set<String> getScope() {
        return StringUtils.commaDelimitedListToSet(this.scope);
    }

    @Override
    public Set<String> getResourceIds() {
        if (StringUtils.isEmpty(this.resourceIds)) {
            return new HashSet<>();
        } else {
            return StringUtils.commaDelimitedListToSet(this.resourceIds);
        }
    }

}

现在一切正常!