【问题标题】:Spring MongoDB mapping OAuth2AuthenticationSpring MongoDB 映射 OAuth2Authentication
【发布时间】:2015-11-21 06:03:25
【问题描述】:

我正在使用 MongoDB 编写自己的 TokenStore (org.springframework.security.oauth2.provider.token.TokenStore) 实现。将数据库中的对象转换/映射回 Java 对象似乎存在一些问题。

有人知道我该如何解决这个问题吗?

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]

【问题讨论】:

    标签: spring-security spring-security-oauth2 spring-mongo spring-mongodb


    【解决方案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

    【讨论】:

    • 感谢分享。实际上我之前发现了这个,但改为使用 Spring Data JPA (SQL Server),因为所有解决方法都可以应对 MongoDB。
    • 太棒了。感谢您的标记。祝你的项目好运。
    猜你喜欢
    • 1970-01-01
    • 2017-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-13
    • 2017-09-17
    • 2016-12-29
    • 2018-06-21
    相关资源
    最近更新 更多