Spring Security 5提供ReactiveSecurityContextHolder
to fetch the SecurityContext
from a Reactive context,但是当我想实现AuditorAware
并自动获得试听时,但它不起作用。 目前我找不到Reactive
的AuditorAware
变体。
@Bean
public AuditorAware<Username> auditor() {
return () -> ReactiveSecurityContextHolder.getContext()
.map(SecurityContext::getAuthentication)
.log()
.filter(a -> a != null && a.isAuthenticated())
.map(Authentication::getPrincipal)
.cast(UserDetails.class)
.map(auth -> new Username(auth.getName()))
.switchIfEmpty(Mono.empty())
.blockOptional();
}
我在我的启动@EnableMongoAuduting
课程中添加了Application
。
在Mongo文档类上。我添加了试听相关的注释。
@CreatedDate
private LocalDateTime createdDate;
@CreatedBy
private Username author;
当我添加帖子时,已填充createdDate,但作者为空。
{"id":"5a49ccdb9222971f40a4ada1","title":"my first post","content":"content of my first post","createdDate":"2018-01-01T13:53:31.234","author":null}
完整代码为here,基于Spring Boot 2.0.0.M7。
答案 0 :(得分:1)
我正在发布另一个解决方案,该解决方案的输入ID可以支持更新操作:
@Component
@RequiredArgsConstructor
public class AuditCallback implements ReactiveBeforeConvertCallback<AuditableEntity> {
private final ReactiveMongoTemplate mongoTemplate;
private Mono<?> exists(Object id, Class<?> entityClass) {
if (id == null) {
return Mono.empty();
}
return mongoTemplate.findById(id, entityClass);
}
@Override
public Publisher<AuditableEntity> onBeforeConvert(AuditableEntity entity, String collection) {
var securityContext = ReactiveSecurityContextHolder.getContext();
return securityContext
.zipWith(exists(entity.getId(), entity.getClass()))
.map(tuple2 -> {
var auditableEntity = (AuditableEntity) tuple2.getT2();
auditableEntity.setLastModifiedBy(tuple2.getT1().getAuthentication().getName());
auditableEntity.setLastModifiedDate(Instant.now());
return auditableEntity;
})
.switchIfEmpty(Mono.zip(securityContext, Mono.just(entity))
.map(tuple2 -> {
var auditableEntity = (AuditableEntity) tuple2.getT2();
String principal = tuple2.getT1().getAuthentication().getName();
Instant now = Instant.now();
auditableEntity.setLastModifiedBy(principal);
auditableEntity.setCreatedBy(principal);
auditableEntity.setLastModifiedDate(now);
auditableEntity.setCreatedDate(now);
return auditableEntity;
}));
}
}
答案 1 :(得分:0)
在提供正式的反应性 AuditAware之前,还有另一种方法可以通过特定于Spring Data Mongo的ReactiveBeforeConvertCallback
来实现。
@EnableMongoAuditing
ReactiveBeforeConvertCallback
,在这里我为需要审核的实体使用PersistentEntity
接口。public class PersistentEntityCallback implements ReactiveBeforeConvertCallback<PersistentEntity> {
@Override
public Publisher<PersistentEntity> onBeforeConvert(PersistentEntity entity, String collection) {
var user = ReactiveSecurityContextHolder.getContext()
.map(SecurityContext::getAuthentication)
.filter(it -> it != null && it.isAuthenticated())
.map(Authentication::getPrincipal)
.cast(UserDetails.class)
.map(userDetails -> new Username(userDetails.getUsername()))
.switchIfEmpty(Mono.empty());
var currentTime = LocalDateTime.now();
if (entity.getId() == null) {
entity.setCreatedDate(currentTime);
}
entity.setLastModifiedDate(currentTime);
return user
.map(u -> {
if (entity.getId() == null) {
entity.setCreatedBy(u);
}
entity.setLastModifiedBy(u);
return entity;
}
)
.defaultIfEmpty(entity);
}
}
检查完整的代码here。
答案 2 :(得分:-2)
要填充createdBy属性,您需要将auditorAware bean与注释链接@EnableMongoAuditing
在MongoConfig类中,定义你的bean:
@Bean(name = "auditorAware")
public AuditorAware<String> auditor() {
....
}
并在注释中使用它:
@Configuration
@EnableMongoAuditing(auditorAwareRef="auditorAware")
class MongoConfig {
....
}