Spring OAuth2集成MongoDB报错:无类型转换器问题求助
Hey Kris, let's work through that frustrating conversion error you're seeing when trying to fetch an OAuth token. That "No converter found..." message usually pops up when Spring can't properly translate the data stored in MongoDB back into the OAuth2Authentication object it needs. Here are the most likely fixes based on your tech stack:
1. Fix Dependency Version Compatibility First
Looking at your dependencies, you're using Spring Boot 1.5.4 but Spring Security 3.2.7—these versions don't play well together. Spring Boot 1.5.x is designed to work with Spring Security 4.x, not 3.x. This mismatch can cause all sorts of serialization/deserialization weirdness.
Update your Spring Security dependencies to a version compatible with Spring Boot 1.5.4. If you're using Maven, replace your Spring Security entries with either:
- The Spring Boot starter (which handles versioning automatically):
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>
Or explicitly use a compatible 4.x version:
<dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> <version>4.2.13.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>4.2.13.RELEASE</version> </dependency>
2. Add Custom MongoDB Converters for OAuth2 Objects
If version fixes don't resolve it, the problem is likely that Spring Data MongoDB is storing OAuth2Authentication as a BasicDBObject but can't convert it back. You'll need to define custom converters to handle serialization and deserialization between these types.
Create a MongoDB configuration class with these converters:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.security.oauth2.provider.OAuth2Authentication; import org.springframework.security.oauth2.provider.OAuth2Request; import java.util.Map; @Configuration public class MongoOAuth2Config { @Bean public MappingMongoConverter mappingMongoConverter(MongoMappingContext context) { MappingMongoConverter converter = new MappingMongoConverter(null, context); converter.setCustomConversions(new org.springframework.data.mongodb.core.convert.CustomConversions( java.util.Arrays.asList( new OAuth2AuthenticationReadConverter(), new OAuth2AuthenticationWriteConverter(), new OAuth2RequestReadConverter(), new OAuth2RequestWriteConverter() ) )); return converter; } // Convert from BasicDBObject to OAuth2Authentication static class OAuth2AuthenticationReadConverter implements org.springframework.core.convert.converter.Converter<com.mongodb.BasicDBObject, OAuth2Authentication> { @Override public OAuth2Authentication convert(com.mongodb.BasicDBObject source) { OAuth2Request oauth2Request = new OAuth2Request( (Map<String, String>) source.get("oauth2Request"), source.getString("clientId"), null, true, null, null, null, null, null ); // If your tokens include user auth details, add deserialization logic here return new OAuth2Authentication(oauth2Request, null); } } // Convert from OAuth2Authentication to BasicDBObject static class OAuth2AuthenticationWriteConverter implements org.springframework.core.convert.converter.Converter<OAuth2Authentication, com.mongodb.BasicDBObject> { @Override public com.mongodb.BasicDBObject convert(OAuth2Authentication source) { com.mongodb.BasicDBObject dbObject = new com.mongodb.BasicDBObject(); dbObject.put("clientId", source.getOAuth2Request().getClientId()); dbObject.put("oauth2Request", source.getOAuth2Request().getRequestParameters()); // Add other fields from OAuth2Authentication that you need to store return dbObject; } } // Converters for OAuth2Request (required since it's part of OAuth2Authentication) static class OAuth2RequestReadConverter implements org.springframework.core.convert.converter.Converter<com.mongodb.BasicDBObject, OAuth2Request> { @Override public OAuth2Request convert(com.mongodb.BasicDBObject source) { return new OAuth2Request( (Map<String, String>) source.get("requestParameters"), source.getString("clientId"), null, source.getBoolean("approved"), null, null, null, null, null ); } } static class OAuth2RequestWriteConverter implements org.springframework.core.convert.converter.Converter<OAuth2Request, com.mongodb.BasicDBObject> { @Override public com.mongodb.BasicDBObject convert(OAuth2Request source) { com.mongodb.BasicDBObject dbObject = new com.mongodb.BasicDBObject(); dbObject.put("clientId", source.getClientId()); dbObject.put("requestParameters", source.getRequestParameters()); dbObject.put("approved", source.isApproved()); return dbObject; } } }
Note: Adjust the converter logic to match any additional fields you store in your OAuth2 tokens (like user authentication details).
3. Verify Your TokenStore Configuration
If you're using MongoTokenStore, make sure it's using your custom converters. You can create a custom TokenStore bean to ensure this:
import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.security.oauth2.provider.token.store.MongoTokenStore; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class OAuth2Config { @Bean public MongoTokenStore tokenStore(MongoOperations mongoOperations) { return new MongoTokenStore(mongoOperations); // If you need more control, extend MongoTokenStore and override read/write methods } }
Start with the version compatibility fix—it's the quickest and most common solution for this kind of issue. If that doesn't work, add the custom converters to handle the object mapping properly.
内容的提问来源于stack exchange,提问作者chiku

