Spring Boot集成Axon框架启动报错:快照使用默认XStreamSerializer未指定安全上下文
问题:Axon Framework启动报错:未指定安全上下文的默认XStreamSerializer用于快照
错误信息
org.axonframework.common.AxonConfigurationException: A default XStreamSerializer is used for snapshots, without specifying the security context at org.axonframework.eventsourcing.eventstore.AbstractEventStorageEngine$Builder.validate(AbstractEventStorageEngine.java:369) ~[axon-eventsourcing-4.5.8.jar:4.5.8] at org.axonframework.eventsourcing.eventstore.BatchingEventStorageEngine$Builder.validate(BatchingEventStorageEngine.java:224) ~[axon-eventsourcing-4.5.8.jar:4.5.8] at org.axonframework.extensions.mongo.eventsourcing.eventstore.MongoEventStorageEngine$Builder.validate(MongoEventStorageEngine.java:286) ~[axon-mongo-4.4.jar:4.4] at org.axonframework.eventsourcing.eventstore.AbstractEventStorageEngine.<init>(AbstractEventStorageEngine.java:74) ~[axon-eventsourcing-4.5.8.jar:4.5.8] at org.axonframework.eventsourcing.eventstore.BatchingEventStorageEngine.<init>(BatchingEventStorageEngine.java:62) ~[axon-eventsourcing-4.5.8.jar:4.5.8] at org.axonframework.extensions.mongo.eventsourcing.eventstore.MongoEventStorageEngine.<init>(MongoEventStorageEngine.java:64) ~[axon-mongo-4.4.jar:4.4] at org.axonframework.extensions.mongo.eventsourcing.eventstore.MongoEventStorageEngine$Builder.build(MongoEventStorageEngine.java:275) ~[axon-mongo-4.4.jar:4.4] at com.example.demo.configuration.AxonConfig.eventStorageEngine(AxonConfig.java:70) ~[classes/:na] // 省略后续栈跟踪信息
当前AxonConfig配置
package com.example.demo.configuration; import com.mongodb.ServerAddress; import com.mongodb.client.MongoClient; import org.axonframework.eventhandling.tokenstore.TokenStore; import org.axonframework.eventsourcing.EventCountSnapshotTriggerDefinition; import org.axonframework.eventsourcing.SnapshotTriggerDefinition; import org.axonframework.eventsourcing.Snapshotter; import org.axonframework.eventsourcing.eventstore.EmbeddedEventStore; import org.axonframework.eventsourcing.eventstore.EventStorageEngine; import org.axonframework.eventsourcing.eventstore.EventStore; import org.axonframework.extensions.mongo.DefaultMongoTemplate; import org.axonframework.extensions.mongo.MongoTemplate; import org.axonframework.extensions.mongo.eventsourcing.eventstore.MongoEventStorageEngine; import org.axonframework.extensions.mongo.eventsourcing.eventstore.MongoFactory; import org.axonframework.extensions.mongo.eventsourcing.eventstore.MongoSettingsFactory; import org.axonframework.extensions.mongo.eventsourcing.tokenstore.MongoTokenStore; import org.axonframework.serialization.Serializer; import org.axonframework.spring.config.AxonConfiguration; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.List; @Configuration public class AxonConfig { @Value("${spring.data.mongodb.host:127.0.0.1}") private String mongoHost; @Value("${spring.data.mongodb.port:27017}") private int mongoPort; @Value("${spring.data.mongodb.database:user-api}") private String mongoDatabase; @Bean public MongoClient mongoClient() { MongoFactory mongoFactory = new MongoFactory(); MongoSettingsFactory mongoSettingsFactory = new MongoSettingsFactory(); mongoSettingsFactory.setMongoAddresses(List.of(new ServerAddress(mongoHost, mongoPort))); mongoFactory.setMongoClientSettings(mongoSettingsFactory.createMongoClientSettings()); return mongoFactory.createMongo(); } @Bean public MongoTemplate axonMongoTemplate() { return DefaultMongoTemplate.builder() .mongoDatabase(mongoClient(), mongoDatabase) .build(); } @Bean public TokenStore tokenStore(Serializer serializer) { return MongoTokenStore.builder() .mongoTemplate(axonMongoTemplate()) .serializer(serializer) .build(); } @Bean public EventStorageEngine eventStorageEngine() { return MongoEventStorageEngine.builder() .mongoTemplate( DefaultMongoTemplate.builder() .mongoDatabase(mongoClient()) .build() ) .build(); } @Bean public EmbeddedEventStore eventStore(AxonConfiguration configuration) { return EmbeddedEventStore.builder() .storageEngine(eventStorageEngine()) .messageMonitor(configuration.messageMonitor(EventStore.class, "eventStore")) .build(); } }
解决方案
错误原因
Axon Framework 4.5+版本强化了序列化安全校验,默认的XStreamSerializer未配置安全上下文(白名单)时,不能用于快照序列化,否则会触发安全风险校验错误。
修复步骤
- 复用已配置的MongoTemplate:原代码中
eventStorageEngine()方法重新创建了MongoTemplate,改为复用已定义的axonMongoTemplate()bean,避免重复实例化。 - 为快照序列化指定安全的Serializer:优先使用JacksonSerializer(无XStream的安全风险),若需使用XStream则必须配置允许的类/包白名单。
方案一:使用JacksonSerializer作为快照序列化器(推荐)
修改eventStorageEngine()方法,注入Axon默认提供的Serializer和JacksonSerializer:
@Bean public EventStorageEngine eventStorageEngine(Serializer defaultSerializer, Serializer jacksonSerializer) { return MongoEventStorageEngine.builder() .mongoTemplate(axonMongoTemplate()) .eventSerializer(defaultSerializer) // 事件使用默认序列化器 .snapshotSerializer(jacksonSerializer) // 快照使用JacksonSerializer .build(); }
方案二:配置XStreamSerializer安全上下文(不推荐,存在安全风险)
若坚持使用XStream,需配置允许的包白名单:
@Bean public Serializer snapshotSerializer() { return XStreamSerializer.builder() // 允许自己项目下的所有类 .allowTypesByWildcard("com.example.demo.**") // 可添加其他需要允许的框架类 .allowTypesByWildcard("org.axonframework.**") .build(); } @Bean public EventStorageEngine eventStorageEngine(Serializer defaultSerializer) { return MongoEventStorageEngine.builder() .mongoTemplate(axonMongoTemplate()) .eventSerializer(defaultSerializer) .snapshotSerializer(snapshotSerializer()) .build(); }
额外优化
原eventStore()方法无需修改,保持原样即可。
内容的提问来源于stack exchange,提问作者PAA
相关产品推荐
相关产品推荐

