Edgewall Software

Ticket #540: filter.py

File filter.py, 3.4 KB (added by dkhizh@…, 10 months ago)

Modified TracHTTPAuth 1.1 filter.py file

Line 
1from trac.core import *
2from trac.config import ListOption
3from trac.web.api import IRequestFilter, RequestDone, IAuthenticator
4from trac.web.chrome import INavigationContributor
5
6try: 
7    from base64 import b64decode 
8except ImportError: 
9    from base64 import decodestring as b64decode
10
11from acct_mgr.api import AccountManager
12
13__all__ = ['HTTPAuthFilter']
14
15class HTTPAuthFilter(Component):
16    """Request filter and handler to provide HTTP authentication."""
17   
18    paths = ListOption('httpauth', 'paths', default='/blog', doc='Paths to force HTTP authentication on.')
19   
20    formats = ListOption('httpauth', 'formats', default='rss', doc='Request formats to force HTTP authentication on')
21   
22    noredirectpaths = ListOption('httpauth', 'noredirectpaths', default='/login, /reset_password, /register, /chrome', doc='Paths excluded from redirection to login')
23   
24    implements(IRequestFilter, IAuthenticator)
25
26    # IRequestFilter methods
27    def pre_process_request(self, req, handler):
28        # proceed if user is already authenticated
29        if (req.authname and req.authname != 'anonymous'):
30            return handler
31        # test if HTTP Authentication is applicable
32        check = False
33        for path in self.paths:
34            if req.path_info.startswith(path):
35                check = True
36                break
37        if req.args.get('format') in self.formats:
38            check = True
39        if check:
40            if not self._check_password(req):
41                self.log.info('HTTPAuthFilter: No/bad authentication data given, returing 403')
42                return self
43            else:
44                return handle
45        else:
46            # check if paths are excluded from login, or redirect to login page
47            for path in self.noredirectpaths:
48                if req.path_info.startswith(path):
49                    check = True
50                    break
51            if check:
52                return handler
53            else:
54                self.log.debug('Redirecting anonymous request to /login')
55                req.redirect(req.href.login() + '?referer=' + req.abs_href(req.path_info))
56                return []
57       
58    def post_process_request(self, req, template, content_type):
59        return template, content_type
60
61    # IRequestHandler methods (sort of)       
62    def process_request(self, req):
63        if req.session:
64            req.session.save() # Just in case
65       
66        req.send_response(401)
67        req.send_header('WWW-Authenticate', 'Basic realm="Control Panel"')
68        req.send_header('Content-Type', 'text/plain')
69        req.send_header('Pragma', 'no-cache')
70        req.send_header('Cache-control', 'no-cache')
71        req.send_header('Expires', 'Fri, 01 Jan 1999 00:00:00 GMT')
72        req.end_headers()
73       
74        if req.method != 'HEAD':
75            req.write('Authentication required')
76        raise RequestDone
77
78    # IAuthenticator methods
79    def authenticate(self, req):
80        user = self._check_password(req)
81        if user:
82            self.log.debug('HTTPAuthFilter: Authentication okay for %s', user)
83            return user
84           
85    # Internal methods
86    def _check_password(self, req):
87        header = req.get_header('Authorization')
88        if header:
89            token = header.split()[1]
90            user, passwd = b64decode(token).split(':', 1)
91            if AccountManager(self.env).check_password(user, passwd):
92                return user