当前位置: 首页 > 知识库问答 >
问题:

如何将if语句逻辑重写为web安全过滤器中的反应式方法?

卢英范
2023-03-14

我对project reactor和web flux非常陌生,我想将当前传统的阻塞安全过滤器改写为反应式过滤器,即:

当前筛选器如下所示:

@Component
@Slf4j
public class WhitelistingFilter extends OncePerRequestFilter {

  private static final String SECURITY_PROPERTIES = "security.properties";
  private final Properties securityProperties = readConfigurationFile(SECURITY_PROPERTIES);
  private final String whitelistingEnabled = securityProperties.getProperty("whitelisting.enabled", FALSE.toString());

  private final RedisTemplate<String, Object> whitelistingRedisTemplate;
  private final AwsCognitoIdTokenProcessor awsCognitoIdTokenProcessor;

  public WhitelistingFilter(
      @Qualifier("whitelistingRedisTemplate")
          RedisTemplate<String, Object> whitelistingRedisTemplate,
      AwsCognitoIdTokenProcessor awsCognitoIdTokenProcessor) {
    this.whitelistingRedisTemplate = whitelistingRedisTemplate;
    this.awsCognitoIdTokenProcessor = awsCognitoIdTokenProcessor;
  }

  @Override
  protected boolean shouldNotFilter(@NonNull HttpServletRequest request) {
    AntPathMatcher pathMatcher = new AntPathMatcher();
    return Stream.of(USER_LOGIN_URL, ADMIN_LOGIN_URL, SIGNUP_BY_ADMIN_URL, SIGNUP_URL, LOGOUT_URL)
            .anyMatch(p -> pathMatcher.match(p, request.getServletPath())) || whitelistingDisabled();
  }

  private boolean whitelistingDisabled() {
    return FALSE.toString().equalsIgnoreCase(whitelistingEnabled);
  }

  @Override
  protected void doFilterInternal(@NonNull HttpServletRequest httpServletRequest, @NonNull HttpServletResponse httpServletResponse, @NonNull FilterChain filterChain) {
    try {
      Authentication authentication = awsCognitoIdTokenProcessor.getAuthentication(httpServletRequest);
      Optional<String> username = Optional.ofNullable(authentication.getName());
      if (username.isPresent() && usernameWhitelisted(username.get())) {
        log.info("User with username: {} is present in whitelisting", username.get());
        filterChain.doFilter(httpServletRequest, httpServletResponse);
      } else {
        httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        log.error("Username: {} not whitelisted or empty", username.orElse(""));
      }

    } catch (Exception e) {
      logger.error("Error occurred while checking user in redis whitelisting", e);
      SecurityContextHolder.clearContext();
    }
  }

  private boolean usernameWhitelisted(String username) {
    return Boolean.TRUE.equals(whitelistingRedisTemplate.hasKey(WHITELISTING_PREFIX + username));
  }
}

新的、不完整的、被动的方法类如下所示:

@Component
@Slf4j
public class WhitelistingFilter implements WebFilter {

  private static final String SECURITY_PROPERTIES = "security.properties";
  public final List<String> whitelistedUrls =
      List.of(USER_LOGIN_URL, ADMIN_LOGIN_URL, SIGNUP_BY_ADMIN_URL, SIGNUP_URL, LOGOUT_URL);

  private final Properties securityProperties = readConfigurationFile(SECURITY_PROPERTIES);
  private final String whitelistingEnabled = securityProperties.getProperty("whitelisting.enabled", FALSE.toString());
  private final ReactiveRedisOperations<String, Object> whitelistingRedisTemplate;
  private final AuthenticationManager authenticationManager;

  public WhitelistingFilter(
      @Qualifier("reactiveWhitelistingRedisTemplate")
          ReactiveRedisOperations<String, Object> whitelistingRedisTemplate,
      AuthenticationManager authenticationManager) {
    this.whitelistingRedisTemplate = whitelistingRedisTemplate;
    this.authenticationManager = authenticationManager;
  }

  @Override
  public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {

    Mono<String> username =
        ReactiveSecurityContextHolder.getContext()
            .map(SecurityContext::getAuthentication)
            .map(Authentication::getName);
    //logic here
    
  }

  private Mono<Boolean> whitelistingDisabled() {
    return Mono.just(FALSE.toString().equalsIgnoreCase(whitelistingEnabled));
  }

  private Mono<Boolean> usernameWhitelisted(Mono<String> username) {
    return whitelistingRedisTemplate.hasKey(WHITELISTING_PREFIX + username);
  }
}

我更改了usernameWhitelist()whitelisting残疾人()方法以返回Mono的,但我无法弄清楚如何验证用户名是否已列入白名单并且在反应式方法中启用了白名单。我试图做某事

username.flatMap(u -> {
  if(two conditions here) 
})

但通过这种方法,我为if语句提供了Mono,这与Java语义相矛盾。对于如何重写代码并使其以反应式方式工作的建议,我将不胜感激。

共有1个答案

齐成和
2023-03-14

拥有一个反应流或管道并不意味着一切都需要反应,您可以将mono从布尔运算符中去掉

当您返回一个空类型的Mono并且由于您需要(?)日志记录,我想你也可以在这里抛出一个自定义异常,并使用doOnError在流/管道顶部捕获它,并在那里检查异常类型并具有相应的逻辑(如果您需要,请将msg传递给异常)

ReactiveSecurityContextHolder.getContext()
            .map(SecurityContext::getAuthentication)
            .map(Authentication::getName)
            .doOnNext(this::doBla)

public void doBla(String username) {
   if (!whitelistingDisabled() || !usernameWhitelisted(username)) {
      throw new TypeException(ms);
  }
}

仅供参考,doOnNext只有在您到达该部分时才会执行,这有点像java流中的一个窥视
doOnError还可以提取其功能,流更容易阅读,保持简单,不会添加太多内容

myStream
     ....otherOperators
     .filter(bla)
     ...
     .doOnError(e -> {
        if ( e instanceOf TypeException) {
           // do stuff 
        }
     }
 类似资料:
  • 问题内容: 在Python中,我们可以这样做: 有人可以指出我有关此功能的文档吗? 它是语言的实现细节或功能吗? 利用此功能是否很好? 问题答案: 在和 短路 ,请参见布尔操作文档: 表达式首先计算; 如果为假,则返回其值;否则,将求值并返回结果值。 表达式首先计算; 如果为true,则返回其值;否则,将求值并返回结果值。 注意如何,对,是 只有 当评估计算为一个真正的价值。相反,for ,仅当评

  • 有人能帮我找出为什么Instachat:Stick\u out\u舌头\u winking\u eye:'和'Docs To Go'的代码没有返回False吗™ 免费办公套房'?它们包含Unicode大于127的字符(分别为emoji和TM),因此从技术上讲,这两个字符都应该返回False。 我不明白为什么else条款在这里不起作用。 下面应该是我的代码的预期输出:True False 然而,实际

  • 我有以下python代码: 这里发生了什么?我无法理解这一点,因为不是布尔值。

  • 问题内容: 这是我的代码: 我在 IF 条件语句中遇到错误。 我究竟做错了什么? 问题答案: 您可能想要而不是。

  • 问题内容: 有没有像我在C ++中那样做的pythonic首选方式: 我真的很喜欢这种语法,它比在各处都有临时变量要干净得多。不太复杂的唯一其他方法是 我想我是在抱怨一个很时髦的问题。我只是想念以前的语法。 问题答案: 怎么样 或更实用

  • 我有两个问题。 ①当useState初始值真假时,if语句如何适应下面? 比如说。。 ②当if语句为true和false时,如何使setGoodBotton从React钩子和if语句适应下面? 例如…(这不是工作)