1

我正在使用MongoDB編寫自己的TokenStore(org.springframework.security.oauth2.provider.token.TokenStore)實現。將數據庫中的對象轉換/映射回Java對象似乎存在一些問題。Spring MongoDB映射OAuth2Authentication

任何人都有線索我怎麼能解決這個問題?

org.springframework.data.mapping.model.MappingInstantiationException: Failed to instantiate org.springframework.security.authentication.UsernamePasswordAuthenticationToken using constructor NO_CONSTRUCTOR with arguments 
    at org.springframework.data.convert.ReflectionEntityInstantiator.createInstance(ReflectionEntityInstantiator.java:64) ~[spring-data-commons-1.11.0.RELEASE.jar:na] 
    at org.springframework.data.convert.ClassGeneratingEntityInstantiator.createInstance(ClassGeneratingEntityInstantiator.java:83) ~[spring-data-commons-1.11.0.RELEASE.jar:na] 
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:251) ~[spring-data-mongodb-1.8.0.RELEASE.jar:na] 
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:231) ~[spring-data-mongodb-1.8.0.RELEASE.jar:na] 
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.readValue(MappingMongoConverter.java:1185) ~[spring-data-mongodb-1.8.0.RELEASE.jar:na] 
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.access$200(MappingMongoConverter.java:78) ~[spring-data-mongodb-1.8.0.RELEASE.jar:na] 

回答

1

您需要創建一個轉換器並將其註冊爲Spring Mongo不會爲您執行此操作。

創建一個轉換器

import com.erranda.abraham.entity.Person; 
import com.mongodb.DBObject; 

import org.springframework.core.convert.converter.Converter; 
import org.springframework.data.convert.ReadingConverter; 
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 
import org.springframework.security.core.Authentication; 
import org.springframework.security.core.GrantedAuthority; 
import org.springframework.security.core.authority.SimpleGrantedAuthority; 
import org.springframework.security.oauth2.provider.OAuth2Authentication; 
import org.springframework.security.oauth2.provider.OAuth2Request; 

import java.util.*; 

/** 
* @version 1.0 
* @author: Iain Porter 
* @since 23/05/2013 
*/ 
//Hackery to deserialize back into an OAuth2Authentication Object made necessary because Spring Mongo can't map clientAuthentication to authorizationRequest 
@ReadingConverter 
@SuppressWarnings("rawtypes") 
public class OAuth2AuthenticationReadConverter implements Converter<DBObject, OAuth2Authentication> { 

    @Override 
    @SuppressWarnings("unchecked") 
    public OAuth2Authentication convert(DBObject source) { 
     System.out.println(source); 
     DBObject storedRequest = (DBObject)source.get("storedRequest"); 

     OAuth2Request oAuth2Request = new OAuth2Request((Map<String, String>)storedRequest.get("requestParameters"), 
       (String)storedRequest.get("clientId"), null, true, new HashSet((List)storedRequest.get("scope")), 
       null, null, null, null); 
     DBObject userAuthorization = (DBObject)source.get("userAuthentication"); 
     Object principal = getPrincipalObject(userAuthorization.get("principal")); 

     Authentication userAuthentication = new UsernamePasswordAuthenticationToken(principal, 
       (String)userAuthorization.get("credentials"), getAuthorities((List) userAuthorization.get("authorities"))); 

     OAuth2Authentication authentication = new OAuth2Authentication(oAuth2Request, 
       userAuthentication); 
     return authentication; 
    } 

    private Object getPrincipalObject(Object principal) { 
     if(principal instanceof DBObject) { 
      DBObject principalDBObject = (DBObject)principal; 
      Person user = new Person (principalDBObject); 
      return user; 
     } else { 
      return principal; 
     } 
    } 

    private Collection<GrantedAuthority> getAuthorities(List<Map<String, String>> authorities) { 
     Set<GrantedAuthority> grantedAuthorities = new HashSet<GrantedAuthority>(authorities.size()); 
     for(Map<String, String> authority : authorities) { 
      grantedAuthorities.add(new SimpleGrantedAuthority(authority.get("role"))); 
     } 
     return grantedAuthorities; 
    } 

} 

然後,你需要沿着側您的MongoDB配置寄存器轉換器

import com.erranda.abraham.api.security.OAuth2AuthenticationReadConverter; 
import com.mongodb.Mongo; 

import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.beans.factory.annotation.Value; 
import org.springframework.context.ApplicationContext; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.core.convert.converter.Converter; 
import org.springframework.data.authentication.UserCredentials; 
import org.springframework.data.mongodb.MongoDbFactory; 
import org.springframework.data.mongodb.config.AbstractMongoConfiguration; 
import org.springframework.data.mongodb.core.MongoTemplate; 
import org.springframework.data.mongodb.core.SimpleMongoDbFactory; 
import org.springframework.data.mongodb.core.convert.CustomConversions; 
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; 
import org.springframework.util.StringUtils; 

import java.util.ArrayList; 
import java.util.List; 

@Configuration 
public class MongoDbConfiguration extends AbstractMongoConfiguration { 

    private static final Logger LOG = LoggerFactory.getLogger(MongoDbConfiguration.class); 
    private static final String MONGO_DB_SERVER = "mongo.db.server"; 
    private static final String MONGO_DB_PORT = "mongo.db.port"; 
    private static final String MONGO_DB_NAME = "mongo.db.name"; 
    private static final String MONGO_DB_LOGON = "mongo.db.logon"; 
    private static final String MONGO_DB_PASSWORD = "mongo.db.password"; 
    private static final String SPRING_PROFILES_ACTIVE = "spring.profiles.active"; 

    @Autowired 
    private ApplicationContext applicationContext; 

    @Value("${" + MONGO_DB_SERVER + "}") 
    private String mongoServer; 
    @Value("${" + MONGO_DB_PORT + "}") 
    private int mongoPort; 
    @Value("${" + MONGO_DB_NAME + "}") 
    private String mongoDBName; 
    @Value("${" + MONGO_DB_LOGON + "}") 
    private String mongoDbLogin; 
    @Value("${" + MONGO_DB_PASSWORD + "}") 
    private String mongoDbPassword; 

    @Override 
    protected String getDatabaseName() { 
     return mongoDBName; 
    } 

    @Override 
    @Bean 
    public Mongo mongo() throws Exception { 
     return new Mongo(mongoServer, mongoPort); 
    } 

    @Override 
    @Bean 
    public MongoTemplate mongoTemplate() throws Exception { 
     if (!StringUtils.isEmpty(mongoDbLogin)) { 
      LOG.info("Configuring mongoTemplate with credentials."); 
      MongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(mongo(), mongoDBName, new UserCredentials(mongoDbLogin, mongoDbPassword)); 
      return new MongoTemplate(mongoDbFactory, mappingMongoConverter()); 
     } else { 
      LOG.info("Configuring mongoTemplate without credentials."); 
      MongoDbFactory mongoDbFactory = new SimpleMongoDbFactory(mongo(), mongoDBName); 
      return new MongoTemplate(mongoDbFactory, mappingMongoConverter()); 
     } 
    } 


    @Override 
    @Bean 
    public CustomConversions customConversions() { 
     List<Converter<?, ?>> converterList = new ArrayList<Converter<?, ?>>(); 
     OAuth2AuthenticationReadConverter converter = new OAuth2AuthenticationReadConverter(); 
     converterList.add(converter); 
     return new CustomConversions(converterList); 
    } 



    private String getContextProperty(final String propertyKey) { 
     return applicationContext.getEnvironment().getProperty(propertyKey); 
    } 
} 

不要忘記標記爲正確的,如果你的作品。

基於https://github.com/iainporter/oauth2-provider

+0

感謝您的分享。實際上,我之前發現它,但改爲使用Spring Data JPA(SQL Server),因爲所有解決方法都是爲了適應MongoDB。 – Filip

+0

太好了。感謝標記。祝你的項目好運。 –