无法从Spring Aspect中的ReactiveSecurityContextHolder中撤回登录的用户

时间:2019-03-27 15:11:22

标签: java spring spring-security spring-aop spring-webflux

我想写一些简单的方面来在某些服务上启用休眠过滤。我需要它来实现一些“可见性规则”。 但是我不知道如何使用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);
        });
    }

0 个答案:

没有答案