Я хочу написать простой аспект для включения фильтрации Hibernate на некоторых сервисах.Мне это нужно для реализации некоторых «правил видимости».Но я не знаю, как это сделать с WebFlux.ReactiveSecurityContextHolder.getContext()
ничего не возвращает, когда я называю это в @Around
аспекте.Я отладил код и обнаружил, что аутентификация начинается до выполнения Aspect и заканчивается после завершения Aspect.Кто-нибудь знает решение этой проблемы?Как я могу получить вход в систему пользователя от аспекта при использовании webflux?Мой аспект:
@Pointcut("execution(* com.shs.crm.dao.service.user.*.*(..))")
public void dataAccessOperation() {
logger.info("dataAccessOperation performed");
}
@Around("com.shs.aspect.DataSecurityAspect.dataAccessOperation()")
public Object doAccessCheck(ProceedingJoinPoint proceedingJoinPoint)
throws Throwable {
Object returnObject;
if (proceedingJoinPoint.getTarget() instanceof CrmUserService) {
try {
Long userId = customSecurityService.getCurrentUserId().toFuture().get();//here i have IllegalStateException
} catch (Exception noContext) {
logger.debug(
"No Security Context associated with current thread - assuming least access");
}
// Here i will enable filter
returnObject = proceedingJoinPoint.proceed();
} else {
// here i will disable filter
returnObject = proceedingJoinPoint.proceed();
}
return returnObject;
}
Сервис для получения текущего пользователя:
@Service
public class CustomSecurityService {
public Mono<Long> getCurrentUserId() {
return ReactiveSecurityContextHolder.getContext().switchIfEmpty(Mono.error(new IllegalStateException("ReactiveSecurityContext is empty")))
.map(SecurityContext::getAuthentication)
.map(Authentication::getName)
.map(Long::parseLong);
}
}
Безопасность:
@Component
public class SecurityContextRepository implements ServerSecurityContextRepository{
@Autowired
private AuthenticationManager authenticationManager;
@Override
public Mono<Void> save(ServerWebExchange swe, SecurityContext sc) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Mono<SecurityContext> load(ServerWebExchange swe) {
ServerHttpRequest request = swe.getRequest();
String authHeader = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
if (authHeader != null && authHeader.startsWith("Bearer ")) {
String authToken = authHeader.substring(7);
Authentication auth = new UsernamePasswordAuthenticationToken(authToken, authToken);
return this.authenticationManager.authenticate(auth).map((authentication) -> {
return new SecurityContextImpl(authentication);
});
} else {
return Mono.empty();
}
}
}
@Component
public class AuthenticationManager implements ReactiveAuthenticationManager {
@Autowired
private JWTUtil jwtUtil;
@Autowired
private CrmUserService userService;
@Override
public Mono<Authentication> authenticate(Authentication authentication) {
String authToken = authentication.getCredentials().toString();
Long userId;
try {
userId = jwtUtil.getUserIdFromToken(authToken);
} catch (Exception e) {
userId = null;
}
if (userId != null && jwtUtil.validateToken(authToken)) {
Map<String, Claim> claims = jwtUtil.getAllClaimsFromToken(authToken);
Set<Long> permissions = userService.getUserPermissionsIds(userId);
//List<Long> permissions = claims.get("permissions").asList(Long.class);
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
userId,
null,
permissions.stream().map( permission -> new SimpleGrantedAuthority(permission.toString())).collect(Collectors.toList())
);
return Mono.just(auth);
} else {
return Mono.empty();
}
}
List<String> getPermissionsNamesByIds(List<Long> ids){
return ids.stream().map(id -> {
CrmPermission.AvailablePermissions permission = (CrmPermission.AvailablePermissions)CrmPermission.AvailablePermissions.fromValue(id.intValue());
return permission.getCode();
}).collect(Collectors.toList());
}
}
Я могу получить текущего пользователя только с контроллера:
@RequestMapping(method = RequestMethod.GET)
public Mono<CrmUserDto> getAccount(Principal principal) {
return customSecurityService.getCurrentUserId().flatMap(userId -> {
CrmUser currentUser = userRepository.findOneByIdWithRoles(userId);
CrmUserDto userDTO = modelMapperService.map(currentUser, CrmUserDto.class);
return Mono.just(userDTO);
});
}