I have an python cgi script that handles login, this is because my website is three (school) websites combined and before my website can be used the data needs to be extracted from those websites. This extraction takes 2 minutes so I want to make a fancy (semi-fake) loading screen.
My register code ends with:
import subprocess
token = "".join(random.choice(
string.ascii_lowercase + string.digits + string.ascii_uppercase)
for _ in range(5)) #generate 5 random characters
#run initScript
subprocess.Popen("python {}/python/initUser.py {} {}".format(
os.getcwd(), uid,token), shell=True, stdin=None, stdout=None, stderr=None,
close_fds=True)
print "Content-type: text/html"
print "Location: registerLoading.php?token={}".format(token)
print
sys.exit(0)
With the subprocess line stolen from: Run Process and Don't Wait
But the subprocess line is still blocking and I can't figure out why.
I'm developing on ubuntu 16.04, and it's going to run on an raspbarry pi 3 (that explains the loading time)
close_fds
has no effect on stdout. You want devnull file handles (subprocess.DEVNULL
in Python 3.3+), so that that the stdout of this script is closed with the call to exit
:
subprocess.Popen(
["python", "python/initUser.py", uid, token],
stdin=None, stdout=open(os.devnull, 'wb'), stderr=open(os.devnull, 'wb'))
Note that I also replaced the shell command with a list form. This makes the code safe against command injection - previously, every user could run arbitrary shell commands on your webserver.
In addition, you may also want to beef up the security of the token. 5 characters can be brute-forced, but much more importantly, random.choice
is not cryptographically secure. Use random.SystemRandom().choice
instead, or the much more modern secrets.token_urlsafe
in Python 3.6+.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With