yeg
2026-09-28 b9edba7f696b2175cc74f111891d9051ce5e9c31
battery-device-neware/src/main/java/com/battery/device/neware/NewareMysqlAdapterFactory.java
@@ -1,5 +1,7 @@
package com.battery.device.neware;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import com.battery.device.api.DeviceAdapter;
import com.battery.device.api.DeviceAdapterException;
@@ -21,6 +23,8 @@
    public static final String PASSWORD_ENV_OPTION = "passwordEnv";
    private static final String DEFAULT_DATABASE = "bts63";
    private static final String READ_ONLY_USER = "visitor";
    /** 现场已知的全权限账号;写进交付配置就等于把误写风险带进现场。 */
    private static final List<String> FULL_PRIVILEGE_USERS = List.of("btsserver", "root");
    @Override
    public String adapterType()
@@ -32,7 +36,7 @@
    public DeviceAdapter create(AdapterInstanceConfig config)
    {
        String database = option(config.sourceConfig(), DATABASE_OPTION, DEFAULT_DATABASE);
        String user = option(config.sourceConfig(), USER_OPTION, READ_ONLY_USER);
        String user = readOnlyUser(config.sourceConfig());
        String password = credential(option(config.sourceConfig(), PASSWORD_ENV_OPTION,
                NewareMysqlAdapter.DEFAULT_PASSWORD_ENV));
        SingleConnectionVendorDataSource source = new SingleConnectionVendorDataSource(
@@ -40,6 +44,20 @@
        return NewareMysqlAdapter.create(config, source);
    }
    /**
     * 解析厂商库账号:默认取现场取得的服务端只读账号,已知的全权限账号一律拒绝。
     *
     * <p>准入只按账号名拦已知的全权限账号(那不是"写一次就回不去"的能力),
     * 真正的只读边界仍是服务端授权与语句白名单两层;这一层只是不把误配写进交付配置。
     */
    static String readOnlyUser(Map<String, String> sourceConfig)
    {
        String user = option(sourceConfig, USER_OPTION, READ_ONLY_USER);
        if (FULL_PRIVILEGE_USERS.contains(user.toLowerCase(Locale.ROOT)))
            throw new DeviceAdapterException("厂商数据源只允许只读账号,拒绝全权限账号:" + user);
        return user;
    }
    /** 只读账号口令;启动参数优先于环境变量,便于本机排查而不必改环境。 */
    static String credential(String variableName)
    {