### Description

I bumped into a bug where a connection id was suffixed with a whitespace e.g. "myconn ". When referencing the connection id "myconn" (without whitespace), you get a connection not found error.

To avoid such human errors, I suggest restricting the characters allowed for connection ids.

Some suggestions:
- There's an `airflow.utils.helpers.validate_key` function for validating the DAG id. Probably a good idea to reuse this.
- I believe variable ids are also not validated, would be good to check those too.

### Use case/motivation

_No response_

### Related issues

_No response_

### Are you willing to submit a PR?

- [X] Yes I am willing to submit a PR!

### Code of Conduct

- [X] I agree to follow this project's [Code of Conduct](https://github.com/apache/airflow/blob/main/CODE_OF_CONDUCT.md)

mock_pm_hooks.return_value = {
        "first": mock.MagicMock(connection_testable=True),
        "second": mock.MagicMock(connection_testable=False),
        "third": None,
    }
    assert ["first"] == ConnectionFormWidget().testable_connection_types
def test_process_form_invalid_extra_removed(admin_client):
    """
    Test that when an invalid json `extra` is passed in the form, it is removed and _not_
    saved over the existing extras.
    """
    conn_details = {"conn_id": "test_conn", "conn_type": "http"}
    conn = Connection(**conn_details, extra='{"foo": "bar"}')
    conn.id = 1
    with create_session() as session:
        session.add(conn)
    data = {**conn_details, "extra": "Invalid"}
    resp = admin_client.post("/connection/edit/1", data=data, follow_redirects=True)
    assert resp.status_code == 200
    with create_session() as session:
        conn = session.get(Connection, 1)
    assert conn.extra == '{"foo": "bar"}'