You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Quarkus中IP认证时Sqlite查询触发BlockingOperationNotAllowedException问题

解决Quarkus中Sqlite阻塞查询导致的BlockingOperationNotAllowedException问题

完全可以通过Sqlite查询用户-IP映射信息来实现IP认证,核心是处理阻塞操作与Quarkus响应式线程池的冲突,以下是具体解决方案:

1. 用@Blocking标记认证方法

Quarkus的HttpAuthenticationMechanism默认在响应式线程池中执行,而Sqlite的JDBC操作属于阻塞IO,直接调用会触发BlockingOperationNotAllowedException。通过添加@Blocking注解,可让Quarkus将该方法调度到专门的阻塞线程池中执行,避免异常。

示例代码:

@ApplicationScoped
public class IpBasedAuthMechanism implements HttpAuthenticationMechanism {

    @Inject
    EntityManager em;

    @Override
    @Blocking // 关键注解,指定方法在阻塞线程池执行
    public Uni<AuthenticationMechanismOutcome> authenticate(RoutingContext context, IdentityProviderManager identityProviderManager) {
        String clientIp = context.request().remoteAddress().hostAddress();
        
        // 查询Sqlite中的用户-IP映射
        User ipUser = em.createQuery("SELECT u FROM User u WHERE u.ip = :clientIp", User.class)
                .setParameter("clientIp", clientIp)
                .getSingleResult();

        if (ipUser != null) {
            // 调用身份验证管理器完成认证流程
            return identityProviderManager.validate(AuthenticationRequest.of(ipUser.getUsername(), new Credential() {}))
                    .map(ValidationResult::getAuthenticationMechanismOutcome);
        }
        return Uni.createFrom().item(AuthenticationMechanismOutcome.NOT_AUTHENTICATED);
    }

    // 实现其他必要方法(如sendChallenge等)
}

2. 按需调整阻塞线程池配置(可选)

针对轻量低负载场景,Quarkus默认的阻塞线程池配置已足够。若需自定义线程数,可在application.properties中添加:

# 核心线程数
quarkus.thread-pool.core-threads=8
# 最大线程数
quarkus.thread-pool.max-threads=16

3. 替代方案:原生JDBC操作Sqlite

如果不想依赖JPA的EntityManager,也可以直接用原生JDBC配合@Blocking实现查询,逻辑更直观:

@ApplicationScoped
public class IpBasedAuthMechanism implements HttpAuthenticationMechanism {

    @Inject
    DataSource dataSource;

    @Override
    @Blocking
    public Uni<AuthenticationMechanismOutcome> authenticate(RoutingContext context, IdentityProviderManager identityProviderManager) {
        String clientIp = context.request().remoteAddress().hostAddress();
        String username = null;

        try (Connection conn = dataSource.getConnection()) {
            String sql = "SELECT username FROM user_ip_map WHERE ip_address = ?";
            try (PreparedStatement stmt = conn.prepareStatement(sql)) {
                stmt.setString(1, clientIp);
                ResultSet rs = stmt.executeQuery();
                if (rs.next()) {
                    username = rs.getString("username");
                }
            }
        } catch (SQLException e) {
            // 处理数据库查询异常
            e.printStackTrace();
        }

        if (username != null) {
            return identityProviderManager.validate(AuthenticationRequest.of(username, new Credential() {}))
                    .map(ValidationResult::getAuthenticationMechanismOutcome);
        }
        return Uni.createFrom().item(AuthenticationMechanismOutcome.NOT_AUTHENTICATED);
    }

    // 实现其他必要方法
}

注意事项

  • 确保已引入Quarkus的Sqlite扩展:quarkus-jdbc-sqlite,在pom.xml中添加依赖即可。
  • 由于部署在安全局域网且为低负载应用,阻塞操作不会引发性能问题,完全适配场景需求。

内容的提问来源于stack exchange,提问作者Alex T

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 16:22:34