Usage of Special Characters in Passwords
TDengine user passwords must meet the following rules:
- The username must not exceed 23 bytes.
- The password length must be between 8 and 255 characters.
- The range of password characters:
- Uppercase letters:
A-Z - Lowercase letters:
a-z - Numbers:
0-9 - Special characters:
! @ # $ % ^ & * ( ) - _ + = [ ] { } : ; > < ? | ~ , .
- Uppercase letters:
- When strong passwords are enabled (
enableStrongPassword/ SQLEnableStrongPassword, enabled by default), the password must contain at least three of the following categories: uppercase letters, lowercase letters, numbers, and special characters. When disabled, there are no restrictions on character types. For details, see Users.
Usage Guide for Special Characters in Different Components
Take the username user1 and password Ab1!@#$%^&*()-_+=[]{} as an example.
CREATE USER user1 PASS 'Ab1!@#$%^&*()-_+=[]{}';
- taos shell
- taosdump
- Benchmark
- taosX
- Java
- Python
- Go
- Rust
- Node.js
- C#
- C
- REST
- ODBC
In the taos shell, note the following:
- If the
-pparameter is used without a password, you will be prompted to enter a password, and any acceptable characters can be entered. - If the
-pparameter is used with a password, and the password contains special characters, single quotes must be used.
Login with user user1:
taos -u user1 -p'Ab1!@#$%^&*()-_+=[]{}'
taos -u user1 -pAb1\!\@\#\$\%\^\&\*\(\)\-\_\+\=\[\]\{\}
In taosdump, note the following:
- If the
-pparameter is used without a password, you will be prompted to enter a password, and any acceptable characters can be entered. - If the
-pparameter is used with a password, and the password contains special characters, single quotes or escaping must be used.
Backup database test with user user1:
taosdump -u user1 -p'Ab1!@#$%^&*()-_+=[]{}' -D test
taosdump -u user1 -pAb1\!\@\#\$\%\^\&\*\(\)\-\_\+\=\[\]\{\} -D test
In taosBenchmark, note the following:
- If the
-pparameter is used without a password, you will be prompted to enter a password, and any acceptable characters can be entered. - If the
-pparameter is used with a password, and the password contains special characters, single quotes or escaping must be used.
Example of data write test with user user1:
taosBenchmark -u user1 -p'Ab1!@#$%^&*()-_+=[]{}' -d test -y
When using taosBenchmark -f <JSON>, there are no additional restrictions on the password in the JSON file.
taosX uses DSN to represent TDengine connections, in the format (taos|tmq)[+ws]://<user>:<pass>@<ip>:<port>, where <pass> can contain special characters, for example: taos+ws://user1:Ab1!@#$%^&*()-_+=[]{}@192.168.10.10:6041.
Export data with user user1:
taosx -f 'taos://user1:Ab1!@#$%^&*()-_+=[]{}@localhost:6030?query=select * from test.t1' \
-t 'csv:./test.csv'
Note: If the password can be URL-decoded, the URL-decoded result is used as the password. For example, taos+ws://user1:Ab1%21%40%23%24%25%5E%26%2A%28%29-_%2B%3D%5B%5D%7B%7D@localhost:6041 is equivalent to taos+ws://user1:Ab1!@#$%^&*()-_+=[]{}@localhost:6041.
No special handling is required in taosExplorer; use it directly.
When using passwords that contain special characters in JDBC, the password must be URL-encoded, as shown below:
package com.taosdata.example;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import com.taosdata.jdbc.TSDBDriver;
public class JdbcPassDemo {
public static void main(String[] args) throws Exception {
String password = "Ab1!@#$%^&*()-_+=[]{}";
String encodedPassword = URLEncoder.encode(password, StandardCharsets.UTF_8.toString());
String jdbcUrl = "jdbc:TAOS-WS://localhost:6041?varcharAsString=true";
Properties connProps = new Properties();
connProps.setProperty(TSDBDriver.PROPERTY_KEY_USER, "user1");
connProps.setProperty(TSDBDriver.PROPERTY_KEY_PASSWORD, encodedPassword);
connProps.setProperty(TSDBDriver.PROPERTY_KEY_ENABLE_AUTO_RECONNECT, "true");
connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
connProps.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
try (Connection conn = DriverManager.getConnection(jdbcUrl, connProps)) {
System.out.println("Connected to " + jdbcUrl + " successfully.");
// you can use the connection for execute SQL here
} catch (Exception ex) {
// please refer to the JDBC specifications for detailed exceptions info
System.out.printf("Failed to connect to %s, %sErrMessage: %s%n",
jdbcUrl,
ex instanceof SQLException ? "ErrCode: " + ((SQLException) ex).getErrorCode() + ", " : "",
ex.getMessage());
// Print stack trace for context in examples. Use logging in production.
ex.printStackTrace();
throw ex;
}
}
}
No special handling is required for passwords that contain special characters in Python, as shown below:
import taos
import taosws
def create_connection():
host = "localhost"
port = 6030
return taos.connect(
user="user1",
password="Ab1!@#$%^&*()-_+=[]{}",
host=host,
port=port,
)
def create_ws_connection():
host = "localhost"
port = 6041
return taosws.connect(
user="user1",
password="Ab1!@#$%^&*()-_+=[]{}",
host=host,
port=port,
)
def show_databases(conn):
cursor = conn.cursor()
cursor.execute("SHOW DATABASES")
print(cursor.fetchall())
cursor.close()
if __name__ == "__main__":
print("Connect with native protocol")
conn = create_connection()
show_databases(conn)
print("Connect with websocket protocol")
conn = create_ws_connection()
show_databases(conn)
Starting from v3.6.0, the Go connector supports passwords that contain special characters; URL-encode the password when using it.
package main
import (
"database/sql"
"fmt"
"log"
"net/url"
_ "github.com/taosdata/driver-go/v3/taosWS"
)
func main() {
var user = "user1"
var password = "Ab1!@#$%^&*()-_+=[]{}"
var encodedPassword = url.QueryEscape(password)
var taosDSN = user + ":" + encodedPassword + "@ws(localhost:6041)/"
taos, err := sql.Open("taosWS", taosDSN)
if err != nil {
log.Fatalln("Failed to connect to " + taosDSN + "; ErrMessage: " + err.Error())
}
fmt.Println("Connected to " + taosDSN + " successfully.")
defer taos.Close()
}
The Rust connector uses DSN to represent TDengine connections, in the format (taos|tmq)[+ws]://<user>:<pass>@<ip>:<port>, where <pass> can contain special characters, for example: taos+ws://user1:Ab1!@#$%^&*()-_+=[]{}@192.168.10.10:6041.
let dsn = "taos+ws://user1:Ab1!@#$%^&*()-_+=[]{}@localhost:6041";
let connection = TaosBuilder::from_dsn(&dsn)?.build().await?;
Starting from v3.1.5, the Node.js connector supports passwords that contain special characters; no special handling is required.
const taos = require("@tdengine/websocket");
let dsn = 'ws://localhost:6041';
async function createConnect() {
try {
let conf = new taos.WSConfig(dsn);
conf.setUser('user1');
conf.setPwd('Ab1!@#$%^&*()-_+=[]{}');
conf.setDb('test');
conn = await taos.sqlConnect(conf);
console.log("Connected to " + dsn + " successfully.");
return conn;
} catch (err) {
console.log("Connection failed with code: " + err.code + ", message: " + err.message);
throw err;
}
}
createConnect()
When using passwords in C#, note that connection strings do not support semicolons (semicolons are delimiters). In this case, construct a ConnectionStringBuilder without a password, then set the username and password.
As shown below:
var builder = new ConnectionStringBuilder("host=localhost;port=6030");
builder.Username = "user1";
builder.Password = "Ab1!@#$%^&*()-_+=[]{}";
using (var client = DbDriver.Open(builder)){}
There are no additional restrictions on passwords in C.
TAOS *taos = taos_connect("localhost", "user1", "Ab1!@#$%^&*()-_+=[]{}", NULL, 6030);
When using passwords in the REST API, note the following:
- Passwords use Basic Auth, in the format
Authorization: Basic base64(<user>:<pass>). - Passwords containing colons
:are not supported.
The following two methods are equivalent:
curl -u'user1:Ab1!@#$%^&*()-_+=[]{}' \
-d 'show databases' http://localhost:6041/rest/sql
curl -H 'Authorization: Basic dXNlcjE6QWIxIUAjJCVeJiooKS1fKz1bXXt9' \
-d 'show databases' http://localhost:6041/rest/sql
The ODBC connector supports passwords that contain special characters; no special handling is required. As shown below:
#include <stdio.h>
#include <stdlib.h>
#include <sql.h>
#include <sqlext.h>
int test_user_connect(const char *dsn, const char *uid, const char *pwd) {
SQLHENV env = SQL_NULL_HENV;
SQLHDBC dbc = SQL_NULL_HDBC;
SQLHSTMT stmt = SQL_NULL_HSTMT;
SQLRETURN sr = SQL_SUCCESS;
sr = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env);
if (sr != SQL_SUCCESS && sr != SQL_SUCCESS_WITH_INFO)
goto end;
sr = SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, (void *)SQL_OV_ODBC3, 0);
if (sr != SQL_SUCCESS && sr != SQL_SUCCESS_WITH_INFO)
goto end;
sr = SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc);
if (sr != SQL_SUCCESS && sr != SQL_SUCCESS_WITH_INFO)
goto end;
sr = SQLConnect(dbc, (SQLCHAR *)dsn, SQL_NTS, (SQLCHAR *)uid, SQL_NTS, (SQLCHAR *)pwd, SQL_NTS);
if (sr != SQL_SUCCESS && sr != SQL_SUCCESS_WITH_INFO)
goto end;
sr = SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt);
if (sr != SQL_SUCCESS && sr != SQL_SUCCESS_WITH_INFO)
goto end;
sr = SQLExecDirect(stmt, (SQLCHAR *)"SHOW DATABASES", SQL_NTS);
if (sr != SQL_SUCCESS && sr != SQL_SUCCESS_WITH_INFO)
goto end;
end:
if (stmt != SQL_NULL_HSTMT) {
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
stmt = SQL_NULL_HSTMT;
}
if (dbc != SQL_NULL_HDBC) {
SQLDisconnect(dbc);
SQLFreeHandle(SQL_HANDLE_DBC, dbc);
dbc = SQL_NULL_HDBC;
}
if (env != SQL_NULL_HENV) {
SQLFreeHandle(SQL_HANDLE_ENV, env);
env = SQL_NULL_HENV;
}
return (sr == SQL_SUCCESS || sr == SQL_SUCCESS_WITH_INFO) ? 0 : -1;
}
int main() {
int result = test_user_connect("TAOS_ODBC_WS_DSN", "user1", "Ab1!@#$%^&*()-_+=[]{}");
printf("test case test_user_connect %s\n", !result ? "pass" : "failed");
return 0;
}