mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2025-01-30 23:09:44 +00:00
Merge pull request #929 from ganguera/ganguera/basic_auth
Added Basic Auth support for MITMWeb interface
This commit is contained in:
commit
bd68b4f678
@ -760,6 +760,21 @@ def mitmweb():
|
||||
action="store_true", dest="wdebug",
|
||||
help="Turn on mitmweb debugging"
|
||||
)
|
||||
group.add_argument(
|
||||
"--wsingleuser",
|
||||
action="store", dest="wsingleuser", type=str,
|
||||
metavar="USER",
|
||||
help="""
|
||||
Allows access to a a single user, specified in the form
|
||||
username:password.
|
||||
"""
|
||||
)
|
||||
group.add_argument(
|
||||
"--whtpasswd",
|
||||
action="store", dest="whtpasswd", type=str,
|
||||
metavar="PATH",
|
||||
help="Allow access to users specified in an Apache htpasswd file."
|
||||
)
|
||||
|
||||
common_options(parser)
|
||||
group = parser.add_argument_group(
|
||||
|
@ -125,6 +125,9 @@ def mitmweb(args=None): # pragma: no cover
|
||||
web_options.wdebug = options.wdebug
|
||||
web_options.wiface = options.wiface
|
||||
web_options.wport = options.wport
|
||||
web_options.wsingleuser = options.wsingleuser
|
||||
web_options.whtpasswd = options.whtpasswd
|
||||
web_options.process_web_options(parser)
|
||||
|
||||
server = get_server(web_options.no_server, proxy_config)
|
||||
|
||||
|
@ -3,6 +3,8 @@ import collections
|
||||
import tornado.ioloop
|
||||
import tornado.httpserver
|
||||
|
||||
from netlib.http import authentication
|
||||
|
||||
from .. import controller, flow
|
||||
from . import app
|
||||
|
||||
@ -113,6 +115,9 @@ class Options(object):
|
||||
"wdebug",
|
||||
"wport",
|
||||
"wiface",
|
||||
"wauthenticator",
|
||||
"wsingleuser",
|
||||
"whtpasswd",
|
||||
]
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@ -122,13 +127,30 @@ class Options(object):
|
||||
if not hasattr(self, i):
|
||||
setattr(self, i, None)
|
||||
|
||||
def process_web_options(self, parser):
|
||||
if self.wsingleuser or self.whtpasswd:
|
||||
if self.wsingleuser:
|
||||
if len(self.wsingleuser.split(':')) != 2:
|
||||
return parser.error(
|
||||
"Invalid single-user specification. Please use the format username:password"
|
||||
)
|
||||
username, password = self.wsingleuser.split(':')
|
||||
self.wauthenticator = authentication.PassManSingleUser(username, password)
|
||||
elif self.whtpasswd:
|
||||
try:
|
||||
self.wauthenticator = authentication.PassManHtpasswd(self.whtpasswd)
|
||||
except ValueError as v:
|
||||
return parser.error(v.message)
|
||||
else:
|
||||
self.wauthenticator = None
|
||||
|
||||
|
||||
class WebMaster(flow.FlowMaster):
|
||||
|
||||
def __init__(self, server, options):
|
||||
self.options = options
|
||||
super(WebMaster, self).__init__(server, WebState())
|
||||
self.app = app.Application(self, self.options.wdebug)
|
||||
self.app = app.Application(self, self.options.wdebug, self.options.wauthenticator)
|
||||
if options.rfile:
|
||||
try:
|
||||
self.load_flows_file(options.rfile)
|
||||
|
@ -4,6 +4,7 @@ import tornado.web
|
||||
import tornado.websocket
|
||||
import logging
|
||||
import json
|
||||
import base64
|
||||
|
||||
from netlib.http import CONTENT_MISSING
|
||||
from .. import version, filt
|
||||
@ -40,7 +41,28 @@ class APIError(tornado.web.HTTPError):
|
||||
pass
|
||||
|
||||
|
||||
class RequestHandler(tornado.web.RequestHandler):
|
||||
class BasicAuth(object):
|
||||
def set_auth_headers(self):
|
||||
self.set_status(401)
|
||||
self.set_header('WWW-Authenticate', 'Basic realm=MITMWeb')
|
||||
self._transforms = []
|
||||
self.finish()
|
||||
|
||||
def prepare(self):
|
||||
wauthenticator = self.application.settings['wauthenticator']
|
||||
if wauthenticator:
|
||||
auth_header = self.request.headers.get('Authorization')
|
||||
if auth_header is None or not auth_header.startswith('Basic '):
|
||||
self.set_auth_headers()
|
||||
else:
|
||||
self.auth_decoded = base64.decodestring(auth_header[6:])
|
||||
self.username, self.password = self.auth_decoded.split(':', 2)
|
||||
if not wauthenticator.test(self.username, self.password):
|
||||
self.set_auth_headers()
|
||||
raise APIError(401, "Invalid username or password.")
|
||||
|
||||
|
||||
class RequestHandler(BasicAuth, tornado.web.RequestHandler):
|
||||
|
||||
def set_default_headers(self):
|
||||
super(RequestHandler, self).set_default_headers()
|
||||
@ -100,7 +122,7 @@ class FiltHelp(RequestHandler):
|
||||
))
|
||||
|
||||
|
||||
class WebSocketEventBroadcaster(tornado.websocket.WebSocketHandler):
|
||||
class WebSocketEventBroadcaster(BasicAuth, tornado.websocket.WebSocketHandler):
|
||||
# raise an error if inherited class doesn't specify its own instance.
|
||||
connections = None
|
||||
|
||||
@ -284,7 +306,7 @@ class Settings(RequestHandler):
|
||||
|
||||
class Application(tornado.web.Application):
|
||||
|
||||
def __init__(self, master, debug):
|
||||
def __init__(self, master, debug, wauthenticator):
|
||||
self.master = master
|
||||
handlers = [
|
||||
(r"/", IndexHandler),
|
||||
@ -308,5 +330,6 @@ class Application(tornado.web.Application):
|
||||
xsrf_cookies=True,
|
||||
cookie_secret=os.urandom(256),
|
||||
debug=debug,
|
||||
wauthenticator=wauthenticator,
|
||||
)
|
||||
super(Application, self).__init__(handlers, **settings)
|
||||
|
Loading…
Reference in New Issue
Block a user