Skip to content

Instantly share code, notes, and snippets.

@mauler
Forked from fxsjy/SimpleAuthServer.py
Last active April 10, 2024 16:46
Show Gist options
  • Star 25 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save mauler/593caee043f5fe4623732b4db5145a82 to your computer and use it in GitHub Desktop.
Save mauler/593caee043f5fe4623732b4db5145a82 to your computer and use it in GitHub Desktop.
Python3 http.server supporting basic HTTP Auth (username/password)
# Extended python -m http.serve with --username and --password parameters for
# basic auth, based on https://gist.github.com/fxsjy/5465353
from functools import partial
from http.server import SimpleHTTPRequestHandler, test
import base64
import os
class AuthHTTPRequestHandler(SimpleHTTPRequestHandler):
""" Main class to present webpages and authentication. """
def __init__(self, *args, **kwargs):
username = kwargs.pop("username")
password = kwargs.pop("password")
self._auth = base64.b64encode(f"{username}:{password}".encode()).decode()
super().__init__(*args, **kwargs)
def do_HEAD(self):
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
def do_AUTHHEAD(self):
self.send_response(401)
self.send_header("WWW-Authenticate", 'Basic realm="Test"')
self.send_header("Content-type", "text/html")
self.end_headers()
def do_GET(self):
""" Present frontpage with user authentication. """
if self.headers.get("Authorization") == None:
self.do_AUTHHEAD()
self.wfile.write(b"no auth header received")
elif self.headers.get("Authorization") == "Basic " + self._auth:
SimpleHTTPRequestHandler.do_GET(self)
else:
self.do_AUTHHEAD()
self.wfile.write(self.headers.get("Authorization").encode())
self.wfile.write(b"not authenticated")
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--cgi", action="store_true", help="Run as CGI Server")
parser.add_argument(
"--bind",
"-b",
metavar="ADDRESS",
default="127.0.0.1",
help="Specify alternate bind address " "[default: all interfaces]",
)
parser.add_argument(
"--directory",
"-d",
default=os.getcwd(),
help="Specify alternative directory " "[default:current directory]",
)
parser.add_argument(
"port",
action="store",
default=8000,
type=int,
nargs="?",
help="Specify alternate port [default: 8000]",
)
parser.add_argument("--username", "-u", metavar="USERNAME")
parser.add_argument("--password", "-p", metavar="PASSWORD")
args = parser.parse_args()
handler_class = partial(
AuthHTTPRequestHandler,
username=args.username,
password=args.password,
directory=args.directory,
)
test(HandlerClass=handler_class, port=args.port, bind=args.bind)
@ebrahimiali
Copy link

Is it possible to support POST in this server too?

@thevickypedia
Copy link

Is there a way I can have this script do a timeout or close the connection?
I basically need a re-auth after a set timeout or a logout button which can terminate the session.

@mauler
Copy link
Author

mauler commented Jul 7, 2021 via email

@thevickypedia
Copy link

I think u can set something on the do_GET method. First add this to init self.timeouts = {} and on do_GET always record the first time someone (use remote address) send the Authentication header on the request (a valid one). So if it is expired, try to enforce the auth using do_AUTHHEAD Em seg., 5 de jul. de 2021 às 00:17, Vignesh Rao @.> escreveu:

@.
* commented on this gist. ------------------------------ Is there a way I can have this script do a timeout or close the connection? I basically need a re-auth after a set timeout or a logout button which can terminate the session. — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://gist.github.com/593caee043f5fe4623732b4db5145a82#gistcomment-3802275, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABZLZQVQUU3QYCKECEF4LTTWDFWBANCNFSM4JP3SNPA .

Thanks for the response, I think I figured my way out.
I'm setting the Authorization header to None at the first visit and also at given intervals so the remaining code keeps flowing.

self.headers.replace_header('Authorization', None)

@nikodemusk
Copy link

Really useful, thank you. I use it instead of password protect a directory with Nginx for a service.

@RobertNissan
Copy link

pero al iniciar la sesión en el navegador cual es el nombre de usuario y la contraseña ?

@wgetnz
Copy link

wgetnz commented Feb 11, 2023

当使用其他方法如PUT POST等,密码保护会失效

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment