MST
星途 面试题库

面试题:Rust控制台程序用户交互的优化与安全设计

假设你正在开发一个具有敏感信息交互的Rust控制台程序,例如用户需要输入密码。在实现用户输入交互时,如何防止密码明文显示在终端上?同时,设计一套机制来对用户输入进行严格的安全验证,防止注入攻击等安全威胁,阐述你的设计思路并给出关键代码示例。
27.6万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试

防止密码明文显示在终端上

在Rust中,可以使用std::io::Writestd::io::Read特性结合termios库(在Unix系统上)或者windows库(在Windows系统上)来实现隐藏用户输入。对于跨平台方案,可以使用console库。

  1. 使用console
    • 首先在Cargo.toml中添加依赖:
    console = "0.15"
    
    • 然后在代码中使用:
    use console::Term;
    
    fn main() {
        let term = Term::stdout();
        term.write_str("Enter password: ").unwrap();
        let password = term.read_password().unwrap();
        println!("\nPassword entered: {}", password);
    }
    

安全验证防止注入攻击

  1. 输入验证思路

    • 对于密码等敏感信息,验证长度是否合理。例如,密码长度可以设置一个合理的范围,比如8到128字符之间。
    • 检查输入中是否包含恶意字符。对于密码,可以只允许字母、数字和一些特定的安全符号(如_, -等)。
    • 对于可能用于SQL查询等场景的输入,要使用参数化查询而不是字符串拼接,以防止SQL注入。
  2. 关键代码示例(密码验证)

    use std::str::Chars;
    
    fn validate_password(password: &str) -> bool {
        // 验证长度
        if password.len() < 8 || password.len() > 128 {
            return false;
        }
        let valid_chars: Vec<char> = ('a'..='z').chain(('A'..='Z')).chain(('0'..='9')).chain(['_', '-']).collect();
        let chars: Chars<'_> = password.chars();
        for c in chars {
            if!valid_chars.contains(&c) {
                return false;
            }
        }
        true
    }
    

    可以在获取到密码后调用这个函数进行验证:

    fn main() {
        let term = Term::stdout();
        term.write_str("Enter password: ").unwrap();
        let password = term.read_password().unwrap();
        if validate_password(&password) {
            println!("Password is valid.");
        } else {
            println!("Password is invalid.");
        }
    }
    
  3. 防止SQL注入示例(假设使用rusqlite库)

    • 首先在Cargo.toml中添加依赖:
    rusqlite = "0.28"
    
    • 然后在代码中使用参数化查询:
    use rusqlite::{Connection, params};
    
    fn main() {
        let conn = Connection::open("test.db").expect("Failed to open database");
        let username = "test_user";
        let password = "test_password";
        let mut stmt = conn.prepare("SELECT * FROM users WHERE username =? AND password =?").expect("Failed to prepare statement");
        let rows = stmt.query(params![username, password]).expect("Failed to query database");
        for row in rows {
            println!("User found: {:?}", row);
        }
    }
    

通过以上方法,可以有效地防止密码明文显示和一些常见的安全威胁。