Regex to catch what user has put in text box

hi all,

this is a small snippet from my python flask-wtf code

class PasswordForm(FlaskForm):
    un = StringField('Username', [InputRequired(message='please enter your Username')])
    op = PasswordField('Current Password', [InputRequired(message='please enter your current password')])
    np = PasswordField('New Password', [InputRequired(message='please enter your new password'), EqualTo('cnp', message='must match confirm new password'), Length(min=12), Regexp('.*[a-z]', message='must contain one lower case'), Regexp('.*[A-Z]', message='must contain one upper case'), Regexp('.*[0-9]', message='must contain one number'), Regexp('.*[\¬\!\"\£\$\%\^\&\*\(\)\_\+\`\-\=\{\}\:\@\~\<\>\?\[\]\;\'\#\,\.\/\\\|]', message='must contain one special character')])
    cnp = PasswordField('Confirm New Password')

i want to make another regex in the “np” to catch “un” and if it contains there username to not allow it

there username is

firstname.lastname

so if they type in either there firstname and or lastname it wont allow it

is this easy to do please

thanks,
rob

I don’t know, and I think it isn’t… but more importantly, it’s not a good thing to do. Most of your password rules here are completely unnecessary. You’ve set a minimum password length of 12, which is really the only rule you need (other than, of course, that the New and Confirm fields have to match). Demanding “one upper case, one lower case, one number, one special” doesn’t do as much for security as people think it does, and it adds a LOT of frustration (especially when you put a “special character” in and it still doesn’t work).

Important references:

https://neal.fun/password-game/

3 Likes

Firstly, never role your own home brew password library. This is just asking to be hacked, to leak your users’ data, and get a GDPR fine, possibly tanking the entire business.

There must be some sort of standard password library for Flask out there, that’s been battle tested in the wild.

So assuming you want to learn how to become a password library developer, and have already studied lots of existing password handling libraries:

The necessary logic is the negation of the logic used by the others. A match must not occur for this first name / user name regex, where as a match must occur for the regexes for mandatory upper case / lower case / digit / special characters.

Therefore I’d use a CustomValidator:

https://wtforms.readthedocs.io/en/2.3.x/validators/#custom-validators

I can’t think of a simple way to use a regex to enforce something not being included. Normally my ignorance proves nothing, but I would argue not being able to think of a simple one, is a fine reason not to write a regex (making the code more understandable, robust and maintainable).

So if for some reason you’ve still decided you’re not only going to role your own password library, you’re also going to write a complicated regex instead of simple Python code (user_name.lower() in password.lower()), assuming you have the luxury of writing proper python code instead of being constrained by a framework’s automagick, then the differences between re.match, re.search and re.fullmatch are important.

I think the key is a Negative Look Ahead Assertion:

But even if you try r'(?!.*abc.*)' instead of r'(?!abc)', I can’t make re.search fail, when the user named “abc” surrounds their name by other characters:

>>> p2 = r'(?!.*abc.*)'
>>> not re.match(p, 'abc')
True
>>> not re.search(p, '__abc')
False
>>> not re.fullmatch(p, '__abc')
True

but re.search is possibly the way Flask-WTF implmented its RegEx validator.

1 Like