You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by br...@apache.org on 2014/10/17 16:15:26 UTC
[4/4] git commit: [#7732] make SSLMiddleware generic and usable
[#7732] make SSLMiddleware generic and usable
Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/67e7a846
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/67e7a846
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/67e7a846
Branch: refs/heads/master
Commit: 67e7a84616c715badba0b53b0d0c775df0c28495
Parents: 10472d1
Author: Dave Brondsema <db...@slashdotmedia.com>
Authored: Fri Oct 3 03:12:03 2014 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Fri Oct 17 14:14:41 2014 +0000
----------------------------------------------------------------------
Allura/allura/config/middleware.py | 8 ++++----
Allura/allura/controllers/root.py | 5 ++++-
Allura/allura/lib/custom_middleware.py | 13 +++++--------
Allura/allura/lib/plugin.py | 8 +++++++-
Allura/development.ini | 16 ++++++++++++++--
ForgeWiki/forgewiki/tests/functional/test_root.py | 17 +++++++++--------
6 files changed, 43 insertions(+), 24 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/allura/blob/67e7a846/Allura/allura/config/middleware.py
----------------------------------------------------------------------
diff --git a/Allura/allura/config/middleware.py b/Allura/allura/config/middleware.py
index 91a3575..ab0d400 100644
--- a/Allura/allura/config/middleware.py
+++ b/Allura/allura/config/middleware.py
@@ -144,11 +144,11 @@ def _make_core_app(root, global_conf, full_stack=True, **app_conf):
app = CSRFMiddleware(app, '_session_id')
# Setup the allura SOPs
app = allura_globals_middleware(app)
- # Ensure https for logged in users, http for anonymous ones
- if (asbool(app_conf.get('auth.method', 'local') == 'sfx')
- and config.get('override_root') != 'task'):
+ # Ensure http and https used per config
+ if config.get('override_root') != 'task':
app = SSLMiddleware(app, app_conf.get('no_redirect.pattern'),
- app_conf.get('force_ssl.pattern'))
+ app_conf.get('force_ssl.pattern'),
+ app_conf.get('force_ssl.logged_in'))
# Setup resource manager, widget context SOP
app = ew.WidgetMiddleware(
app,
http://git-wip-us.apache.org/repos/asf/allura/blob/67e7a846/Allura/allura/controllers/root.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/root.py b/Allura/allura/controllers/root.py
index f354872..e588d45 100644
--- a/Allura/allura/controllers/root.py
+++ b/Allura/allura/controllers/root.py
@@ -20,10 +20,11 @@
"""Main Controller"""
import logging
-from tg import expose, request, config
+from tg import expose, request, config, session
from tg.decorators import with_trailing_slash
from tg.flash import TGFlash
from pylons import tmpl_context as c
+from paste.deploy.converters import asbool
from allura.app import SitemapEntry
from allura.lib.base import WsgiDispatchController
@@ -89,6 +90,8 @@ class RootController(WsgiDispatchController):
'Did you run `paster setup-app` to create the database?')
if not c.user.is_anonymous():
c.user.track_active(request)
+ if asbool(config.get('force_ssl.logged_in')):
+ session.secure = True
def _cleanup_request(self):
pass
http://git-wip-us.apache.org/repos/asf/allura/blob/67e7a846/Allura/allura/lib/custom_middleware.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/custom_middleware.py b/Allura/allura/lib/custom_middleware.py
index 981c602..1116b45 100644
--- a/Allura/allura/lib/custom_middleware.py
+++ b/Allura/allura/lib/custom_middleware.py
@@ -151,7 +151,7 @@ class SSLMiddleware(object):
'Verify the https/http schema is correct'
- def __init__(self, app, no_redirect_pattern=None, force_ssl_pattern=None):
+ def __init__(self, app, no_redirect_pattern=None, force_ssl_pattern=None, force_ssl_logged_in=False):
self.app = app
if no_redirect_pattern:
self._no_redirect_re = re.compile(no_redirect_pattern)
@@ -161,6 +161,7 @@ class SSLMiddleware(object):
self._force_ssl_re = re.compile(force_ssl_pattern)
else:
self._force_ssl_re = re.compile('$$$')
+ self._force_ssl_logged_in = force_ssl_logged_in
def __call__(self, environ, start_response):
req = Request(environ)
@@ -174,13 +175,9 @@ class SSLMiddleware(object):
resp = exc.HTTPNotFound()
secure = req.url.startswith('https://')
srv_path = req.url.split('://', 1)[-1]
- # This SFUSER check is SourceForge-specific (to require all logged-in users to use https)
- # BUT has the additional affect of not forcing SSL for regular Allura instances
- # This is important for local development, at least. When we remove SFUSER (perhaps by requiring SSL everywhere),
- # we can use `no_redirect.pattern = .` for local development to work
- # without SSL
- force_ssl = req.cookies.get(
- 'SFUSER') or self._force_ssl_re.match(environ['PATH_INFO'])
+ # allura-loggedin is a non-secure cookie as a flag to know that the user has a session over on https
+ force_ssl = (self._force_ssl_logged_in and req.cookies.get('allura-loggedin')) \
+ or self._force_ssl_re.match(environ['PATH_INFO'])
if not secure and force_ssl:
resp = exc.HTTPFound(location='https://' + srv_path)
elif secure and not force_ssl:
http://git-wip-us.apache.org/repos/asf/allura/blob/67e7a846/Allura/allura/lib/plugin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index e15e4c0..f1c9c3c 100644
--- a/Allura/allura/lib/plugin.py
+++ b/Allura/allura/lib/plugin.py
@@ -41,7 +41,7 @@ except ImportError:
ldap = modlist = None
import pkg_resources
import tg
-from tg import config, request, redirect
+from tg import config, request, redirect, response
from pylons import tmpl_context as c, app_globals as g
from webob import exc
from bson.tz_util import FixedOffset
@@ -157,6 +157,11 @@ class AuthenticationProvider(object):
g.zarkov_event('login', user=user)
g.statsUpdater.addUserLogin(user)
user.track_login(self.request)
+ # set a non-secure cookie with same expiration as session,
+ # so an http request can know if there is a related session on https
+ response.set_cookie('allura-loggedin', value='true',
+ expires=None if self.session['login_expires'] is True else self.session['login_expires'],
+ secure=False, httponly=True)
return user
except exc.HTTPUnauthorized:
self.logout()
@@ -167,6 +172,7 @@ class AuthenticationProvider(object):
self.session['username'] = None
self.session['pwd-expired'] = False
self.session.save()
+ response.delete_cookie('allura-loggedin')
def validate_password(self, user, password):
'''Check that provided password matches actual user password
http://git-wip-us.apache.org/repos/asf/allura/blob/67e7a846/Allura/development.ini
----------------------------------------------------------------------
diff --git a/Allura/development.ini b/Allura/development.ini
index 1ecaefc..75cded3 100644
--- a/Allura/development.ini
+++ b/Allura/development.ini
@@ -60,6 +60,8 @@ cache_dir = %(here)s/data
beaker.session.key = allura
beaker.session.type = cookie
beaker.session.httponly = true
+; set this to true if you use HTTPS. If you use force_ssl.logged_in, this will be set automatically when logged in and not when not.
+beaker.session.secure = false
; CHANGE THIS VALUE FOR YOUR SITE
beaker.session.validate_key = 714bfe3612c42390726f
@@ -73,7 +75,7 @@ show_export_control = false
# auth.method = ldap
auth.method = local
-auth.remember_for = 365
+auth.remember_for = 365 ; in days, for the "remember me" checkbox on login
# auth.login_url = /auth/
# auth.logout_url = /auth/logout
# auth.login_fragment_url = /auth/login_fragment
@@ -132,7 +134,17 @@ user_prefs_storage.ldap.fields.display_name = cn
# search.project.additional_display_fields = private, url, title
# search.user.additional_display_fields = email_addresses
-# Set the locations of some static resources
+; To make all pages use ssl: (also set beaker.session.secure above)
+; force_ssl.pattern = .
+; To use ssl if and only if a user is logged in:
+; force_ssl.logged_in = true
+; If you set force_ssl.logged_in, you probably want some URLs to be ssl when logged out:
+; force_ssl.pattern = ^/auth|^/[a-z0-9-]+/import_project/ ; import_project uses a login overlay
+; And to permit some URLs to be accessed over http anyway:
+; no_redirect.pattern = ^/nf/\d+/_(ew|static)_/|^/rest/|^/nf/tool_icon_css|^/auth/refresh_repo
+
+
+# Set the locations of some static resources. ("ew" stands for EasyWidgets library)
# script_name is the path that is handled by the application
# url_base is the prefix that references to the static resources should have
no_redirect.pattern = ^/nf/\d+/_(ew|static)_/.*|^/rest/.*
http://git-wip-us.apache.org/repos/asf/allura/blob/67e7a846/ForgeWiki/forgewiki/tests/functional/test_root.py
----------------------------------------------------------------------
diff --git a/ForgeWiki/forgewiki/tests/functional/test_root.py b/ForgeWiki/forgewiki/tests/functional/test_root.py
index 0ad3cc2..f5f49e6 100644
--- a/ForgeWiki/forgewiki/tests/functional/test_root.py
+++ b/ForgeWiki/forgewiki/tests/functional/test_root.py
@@ -53,11 +53,12 @@ class TestRootController(TestController):
pass
def test_root_index(self):
- r = self.app.get('/wiki/tést/').follow()
- assert 'tést' in r
+ page_url = h.urlquote(u'/wiki/tést/')
+ r = self.app.get(page_url).follow()
+ assert u'tést' in r
assert 'Create Page' in r
# No 'Create Page' button if user doesn't have 'create' perm
- r = self.app.get('/wiki/tést/',
+ r = self.app.get(page_url,
extra_environ=dict(username='*anonymous')).follow()
assert 'Create Page' not in r
@@ -74,13 +75,13 @@ class TestRootController(TestController):
assert 'Browse Pages' in response
def test_root_new_page(self):
- response = self.app.get('/wiki/new_page?title=tést')
- assert 'tést' in response
+ response = self.app.get('/wiki/new_page?title=' + h.urlquote(u'tést'))
+ assert u'tést' in response
def test_root_new_search(self):
- self.app.get('/wiki/tést/')
- response = self.app.get('/wiki/search?q=tést')
- assert 'Search wiki: tést' in response
+ self.app.get(h.urlquote(u'/wiki/tést/'))
+ response = self.app.get('/wiki/search?q=' + h.urlquote(u'tést'))
+ assert u'Search wiki: tést' in response
def test_feed(self):
for ext in ['', '.rss', '.atom']: