Windows 小记 5 -- 判断账户是否是管理员账户

判断账户是否位于管理员用户组的方法有:

net localgroup Administrators "账户名" /add

如果返回“操作成功完成”,则表明之前不是管理员账户。那么再调用 /del 删除添加的管理员。

如果返回 “\n发生系统错误 1378。\n指定的帐户名已是此组的成员。\n” 则表明已经位于管理员用户组。

那么怎么通过编程实现更加准确快速的检测呢?

本地账户:

#include <windows.h>
#include <lm.h>
#include <iostream>

#pragma comment(lib, "Netapi32.lib")

bool IsAccountAdministrator(const std::wstring& userName) {
    LPLOCALGROUP_USERS_INFO_0 groupInfo = NULL;
    DWORD entriesRead = 0;
    DWORD totalEntries = 0;

    // 使用 NetUserGetLocalGroups 获取本地用户组信息
    NET_API_STATUS status = NetUserGetLocalGroups(
        NULL, // 本地计算机
        userName.c_str(),
        0,    // 信息级别 0
        LG_INCLUDE_INDIRECT, // 包含间接组成员关系
        (LPBYTE*)&groupInfo,
        MAX_PREFERRED_LENGTH,
        &entriesRead,
        &totalEntries
    );

    if (status == NERR_Success) {
        for (DWORD i = 0; i < entriesRead; i++) {
            // 检查用户是否属于 "Administrators" 组
            if (_wcsicmp(groupInfo[i].lgrui0_name, L"Administrators") == 0) {
                NetApiBufferFree(groupInfo);
                return true; // 用户属于管理员组
            }
        }
        NetApiBufferFree(groupInfo);
    }
    else {
        std::wcerr << L"Failed to get local groups, error code: " << status << std::endl;
    }
    return false; // 用户不属于管理员组
}

int main() {
    std::wstring userName = L"XXXXXXXX"; // 替换为要检查的用户名

    if (IsAccountAdministrator(userName)) {
        std::wcout << userName << L" is an administrator." << std::endl;
    }
    else {
        std::wcout << userName << L" is not an administrator." << std::endl;
    }

    return 0;
}

域用户(针对间接或者嵌套用户组,最佳的获取方式是通过令牌SID,如果用户账户已经登陆,则可以通过进程句柄获取令牌,否则,则需要通过凭据登陆获取令牌)

#include <windows.h>
#include <sddl.h>
#include <iostream>
#include <tchar.h>

bool IsSpecifiedUserAdmin(const std::wstring& userName, const std::wstring& domainName, const std::wstring& password) {
    HANDLE tokenHandle = NULL;
    DWORD size = 0;
    PTOKEN_GROUPS tokenGroups = NULL;
    SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY;
    PSID adminGroup = NULL;
    bool isAdmin = false;

    // 尝试使用提供的用户名和密码登录
    if (!LogonUser(userName.c_str(), domainName.c_str(), password.c_str(),
        LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, &tokenHandle)) {
        std::wcerr << L"Failed to log on user: " << GetLastError() << std::endl;
        return false;
    }

    // 获取用户令牌中的组信息
    if (!GetTokenInformation(tokenHandle, TokenGroups, NULL, 0, &size) &&
        GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
        std::cerr << "Failed to get token information size." << std::endl;
        CloseHandle(tokenHandle);
        return false;
    }

    tokenGroups = (PTOKEN_GROUPS)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
    if (tokenGroups == NULL) {
        std::cerr << "Failed to allocate memory for token groups." << std::endl;
        CloseHandle(tokenHandle);
        return false;
    }

    if (!GetTokenInformation(tokenHandle, TokenGroups, tokenGroups, size, &size)) {
        std::cerr << "Failed to get token information." << std::endl;
        HeapFree(GetProcessHeap(), 0, tokenGroups);
        CloseHandle(tokenHandle);
        return false;
    }

    // 创建管理员组 SID
    if (!AllocateAndInitializeSid(&ntAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
        DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &adminGroup)) {
        std::cerr << "Failed to initialize SID." << std::endl;
        HeapFree(GetProcessHeap(), 0, tokenGroups);
        CloseHandle(tokenHandle);
        return false;
    }

    // 检查是否属于管理员组
    for (DWORD i = 0; i < tokenGroups->GroupCount; i++) {
        if (EqualSid(adminGroup, tokenGroups->Groups[i].Sid)) {
            isAdmin = true;
            break;
        }
    }

    // 清理
    FreeSid(adminGroup);
    HeapFree(GetProcessHeap(), 0, tokenGroups);
    CloseHandle(tokenHandle);

    return isAdmin;
}

int main() {
    // 替换为要检测的用户名、域和密码
    std::wstring userName = L"TestUser";
    std::wstring domainName = L"."; // 本地计算机使用 "."
    std::wstring password = L"UserPassword";

    if (IsSpecifiedUserAdmin(userName, domainName, password)) {
        std::wcout << L"The specified user is an administrator." << std::endl;
    }
    else {
        std::wcout << L"The specified user is not an administrator." << std::endl;
    }

    return 0;
}

下面代码未测试域用户等复杂情况。 

添加/删除目标用户到管理员用户组:

#include <windows.h>
#include <lm.h>
#include <iostream>

#pragma comment(lib, "Netapi32.lib")

bool AddUserToGroup(const std::wstring& userName) {
    LOCALGROUP_MEMBERS_INFO_3 memberInfo;
    memberInfo.lgrmi3_domainandname = const_cast<wchar_t*>(userName.c_str());

    NET_API_STATUS status = NetLocalGroupAddMembers(NULL, L"Administrators", 3, (LPBYTE)&memberInfo, 1);
    if (status == NERR_Success) {
        std::wcout << L"User " << userName << L" added to Administrators group." << std::endl;
        return true;
    }
    else {
        std::wcerr << L"Failed to add user to Administrators group, error code: " << status << std::endl;
        return false;
    }
}

bool RemoveUserFromGroup(const std::wstring& userName) {
    LOCALGROUP_MEMBERS_INFO_3 memberInfo;
    memberInfo.lgrmi3_domainandname = const_cast<wchar_t*>(userName.c_str());

    NET_API_STATUS status = NetLocalGroupDelMembers(NULL, L"Administrators", 3, (LPBYTE)&memberInfo, 1);
    if (status == NERR_Success) {
        std::wcout << L"User " << userName << L" removed from Administrators group." << std::endl;
        return true;
    }
    else {
        std::wcerr << L"Failed to remove user from Administrators group, error code: " << status << std::endl;
        return false;
    }
}

int main() {
    std::wstring userName = L"XXXXX";  // 设置需要操作的用户名

    // 添加用户到管理员组
    AddUserToGroup(userName);

    system("pause");

    // 从管理员组移除用户
    RemoveUserFromGroup(userName);

    return 0;
}

可以通过 net localgroup Administrators 进行验证。

此外需要注意,当账户没有启用时,可能是无法创建和登陆管理员用户的。所以我们也可以查询管理员用户组中用户的状态,使用下面的代码:

#include <windows.h>
#include <lm.h>
#include <iostream>

#pragma comment(lib, "Netapi32.lib")

void CheckAdministratorsGroup(bool showAllUsers) {
    LOCALGROUP_MEMBERS_INFO_1* groupMembers = NULL;
    DWORD entriesRead = 0;
    DWORD totalEntries = 0;
    DWORD_PTR resumeHandle = 0;
    NET_API_STATUS status;

    // 获取 Administrators 组的成员列表
    status = NetLocalGroupGetMembers(
        NULL, // 本地计算机
        L"Administrators", // 组名
        1, // 信息级别
        (LPBYTE*)&groupMembers, // 输出缓冲区
        MAX_PREFERRED_LENGTH, // 缓冲区大小
        &entriesRead, // 读取的条目数
        &totalEntries, // 总条目数
        &resumeHandle // 分页句柄
    );

    if (status != NERR_Success) {
        std::cerr << "Failed to get group members. Error code: " << status << std::endl;
        return;
    }

    bool hasEnabledUser = false;

    // 遍历组成员
    for (DWORD i = 0; i < entriesRead; ++i) {
        USER_INFO_1* userInfo = NULL;

        // 获取每个成员的用户信息
        status = NetUserGetInfo(NULL, groupMembers[i].lgrmi1_name, 1, (LPBYTE*)&userInfo);
        if (status == NERR_Success) {
            // 检查用户是否被禁用
            bool isUserEnabled = !(userInfo->usri1_flags & UF_ACCOUNTDISABLE);

            if (isUserEnabled) {
                hasEnabledUser = true;
            }

            // 如果开关参数为 true,显示每个用户的状态
            if (showAllUsers) {
                std::wcout << L"User: " << groupMembers[i].lgrmi1_name
                    << L" - Status: " << (isUserEnabled ? L"Enabled" : L"Disabled") << std::endl;
            }

            NetApiBufferFree(userInfo);
        }
    }

    NetApiBufferFree(groupMembers);

    // 如果不显示所有用户,仅报告是否有启用的用户
    if (!showAllUsers) {
        if (hasEnabledUser) {
            std::cout << "The Administrators group has at least one enabled user." << std::endl;
        }
        else {
            std::cout << "No enabled user found in the Administrators group." << std::endl;
        }
    }
}

int main() {
    bool showAllUsers = true; // 设置为 true 以显示所有用户及其状态
    CheckAdministratorsGroup(showAllUsers);
    return 0;
}

添加或者删除本地用户(出于一些原因,不提供凭据验证过程代码):

#include <windows.h>
#include <lm.h>
#include <iostream>
#include <string>
#include <tchar.h>
#include <strsafe.h>

#pragma comment(lib, "Netapi32.lib")
#pragma comment(lib, "Advapi32.lib")

// 添加本地用户
bool AddLocalUser(const std::wstring& userName, const std::wstring& password) {
    USER_INFO_1 userInfo;
    ZeroMemory(&userInfo, sizeof(userInfo));

    userInfo.usri1_name = const_cast<wchar_t*>(userName.c_str());
    userInfo.usri1_password = const_cast<wchar_t*>(password.c_str());
    userInfo.usri1_priv = USER_PRIV_USER; // 普通用户权限
    userInfo.usri1_home_dir = NULL;
    userInfo.usri1_comment = NULL;
    userInfo.usri1_flags = UF_SCRIPT | UF_DONT_EXPIRE_PASSWD; // 用户必须使用脚本,密码永不过期
    userInfo.usri1_script_path = NULL;

    DWORD error = 0;
    NET_API_STATUS status = NetUserAdd(NULL, 1, (LPBYTE)&userInfo, &error);

    if (status == NERR_Success) {
        std::wcout << L"User " << userName << L" added successfully." << std::endl;
        return true;
    }
    else {
        std::wcerr << L"Failed to add user. Error code: " << status << std::endl;
        return false;
    }
}

// 删除本地用户
bool DeleteLocalUser(const std::wstring& userName) {
    NET_API_STATUS status = NetUserDel(NULL, userName.c_str());

    if (status == NERR_Success) {
        std::wcout << L"User " << userName << L" deleted successfully." << std::endl;
        return true;
    }
    else {
        std::wcerr << L"Failed to delete user. Error code: " << status << std::endl;
        return false;
    }
}

// 验证用户凭据
bool AuthenticateUser() {
    return true;   // 出于安全考虑,此处代码不提供给大家
}

int main() {
    std::wstring userName;
    std::wcout << L"Enter the username to add or delete: ";
    std::getline(std::wcin, userName);

    // 验证用户凭据
    std::wcout << L"Please authenticate to proceed." << std::endl;
    if (!AuthenticateUser()) {
        std::wcerr << L"Failed to authenticate user." << std::endl;
        return 1;
    }

    std::wcout << L"Do you want to (a)dd or (d)elete the user? (a/d): ";
    wchar_t action;
    std::wcin >> action;

    if (action == L'a' || action == L'A') {
        std::wstring password;
        std::wcout << L"Enter the password for the new user: ";
        std::wcin.ignore(); // 清除输入缓冲区
        std::getline(std::wcin, password);
        AddLocalUser(userName, password);
    }
    else if (action == L'd' || action == L'D') {
        DeleteLocalUser(userName);
    }
    else {
        std::wcout << L"Invalid action selected." << std::endl;
    }

    return 0;
}

凭据验证模式:

带有凭据验证和询问的安全操作


文章出处链接:[https://blog.youkuaiyun.com/qq_59075481/article/details/143821835].

### Kettle Scheduler 配置方法及最佳实践 Kettle Scheduler 是一款基于 Spring、Spring MVC 和 BeetlSQL 的调度监控平台,用于管理和调度由 Kettle 客户端创建的作业 (Job) 和转换 (Transformation)[^1]。以下是关于 Kettle Scheduler 的配置方法和最佳实践: #### 1. 环境准备 在开始配置之前,确保以下环境已正确安装并运行: - Java JDK 8 或更高版本。 - Maven 构建工具(如果需要从源码编译)。 - 数据库支持:MySQL 或其他兼容数据库。 - Tomcat 或其他支持 Servlet 的应用服务器。 #### 2. 下载与部署 可以从项目地址下载 Kettle Scheduler 的代码或直接获取预构建的 WAR 文件[^1]。将 WAR 文件放置到 Tomcat 的 `webapps` 目录下,并确保 Tomcat 的配置文件中包含以下内容以支持热加载和调试功能[^2]: ```xml <Context path="/kettle-scheduler" docBase="kettle-scheduler" reloadable="true" debug="0" privileged="true"> </Context> ``` #### 3. 数据库配置 编辑 `application.properties` 文件,配置数据库连接信息。例如: ```properties spring.datasource.url=jdbc:mysql://localhost:3306/kettle_scheduler?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC spring.datasource.username=root spring.datasource.password=your_password spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver ``` 确保数据库已初始化,可以参考项目文档中的 SQL 脚本完成表结构的创建[^1]。 #### 4. Quartz 配置 Quartz 是 Kettle Scheduler 中的核心调度组件。可以通过修改 `quartz.properties` 文件调整调度器的行为。例如: ```properties org.quartz.threadPool.threadCount=10 org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate ``` #### 5. Kettle API 集成 Kettle Scheduler 使用 Kettle 提供的 API 来执行 Job 和 Transformation。确保项目的依赖中包含 Kettle 的相关 JAR 包。例如,在 `pom.xml` 中添加以下依赖项: ```xml <dependency> <groupId>pentaho-kettle</groupId> <artifactId>kettle-engine</artifactId> <version>9.1.0.0-324</version> </dependency> ``` #### 6. 启动与访问 启动 Tomcat 并通过浏览器访问 Kettle Scheduler 的管理界面。默认路径为 `http://localhost:8080/kettle-scheduler`。登录后即可进行作业和转换的调度与监控。 #### 7. 最佳实践 - **性能优化**:根据实际需求调整 Quartz 的线程池大小,避免因线程不足导致任务积压[^1]。 - **日志管理**:启用详细的日志记录以便排查问题,同时定期清理过期日志以节省存储空间。 - **安全性**:配置 HTTPS 访问以保护敏感数据传输,并使用强密码策略加强用户账户的安全性。 - **备份机制**:定期备份数据库和 Kettle 文件,防止数据丢失。 ```python # 示例:通过 Python 调用 Kettle API 执行一个简单的转换 from subprocess import Popen, PIPE command = [ "pan.bat", "-file=/path/to/your/transformation.ktr", "-level=Basic" ] process = Popen(command, stdout=PIPE, stderr=PIPE) stdout, stderr = process.communicate() if process.returncode == 0: print("Transformation executed successfully.") else: print(f"Error occurred: {stderr.decode('utf-8')}") ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

涟幽516

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值