mirror of
https://github.com/wassname/flask-security.git
synced 2026-08-11 11:18:40 +08:00
Merge pull request #73 from apahomov/multiple-auth-mechanisms
Multiple auth mechanisms
This commit is contained in:
@@ -48,6 +48,8 @@ def _check_token():
|
||||
args_key = _security.token_authentication_key
|
||||
header_token = request.headers.get(header_key, None)
|
||||
token = request.args.get(args_key, header_token)
|
||||
if request.json:
|
||||
token = request.json.get(args_key, token)
|
||||
serializer = _security.remember_token_serializer
|
||||
|
||||
try:
|
||||
@@ -113,6 +115,36 @@ def auth_token_required(fn):
|
||||
return decorated
|
||||
|
||||
|
||||
def auth_required(*auth_methods):
|
||||
"""
|
||||
Decorator that protects enpoints through multiple mechanisms
|
||||
Example::
|
||||
|
||||
@app.route('/dashboard')
|
||||
@auth_required('token', 'session')
|
||||
def dashboard():
|
||||
return 'Dashboard'
|
||||
|
||||
:param auth_methods: Specified mechanisms.
|
||||
"""
|
||||
login_mechanisms = {
|
||||
'token': lambda: _check_token(),
|
||||
'basic': lambda: _check_http_auth(),
|
||||
'session': lambda: current_user.is_authenticated()
|
||||
}
|
||||
|
||||
def wrapper(fn):
|
||||
@wraps(fn)
|
||||
def decorated_view(*args, **kwargs):
|
||||
mechanisms = [login_mechanisms.get(method) for method in auth_methods]
|
||||
for mechanism in mechanisms:
|
||||
if mechanism and mechanism():
|
||||
return fn(*args, **kwargs)
|
||||
return _get_unauthorized_response()
|
||||
return decorated_view
|
||||
return wrapper
|
||||
|
||||
|
||||
def roles_required(*roles):
|
||||
"""Decorator which specifies that a user must have all the specified roles.
|
||||
Example::
|
||||
|
||||
@@ -169,6 +169,24 @@ class DefaultSecurityTests(SecurityTest):
|
||||
self.assertEquals('Basic realm="My Realm"',
|
||||
r.headers['WWW-Authenticate'])
|
||||
|
||||
def test_multi_auth_basic(self):
|
||||
r = self._get('/multi_auth', headers={
|
||||
'Authorization': 'Basic ' + base64.b64encode("joe@lp.com:password")
|
||||
})
|
||||
self.assertIn('Basic', r.data)
|
||||
|
||||
def test_multi_auth_token(self):
|
||||
r = self.json_authenticate()
|
||||
data = json.loads(r.data)
|
||||
token = data['response']['user']['authentication_token']
|
||||
r = self._get('/multi_auth?auth_token=' + token)
|
||||
self.assertIn('Token', r.data)
|
||||
|
||||
def test_multi_auth_session(self):
|
||||
self.authenticate()
|
||||
r = self._get('/multi_auth')
|
||||
self.assertIn('Session', r.data)
|
||||
|
||||
def test_user_deleted_during_session_reverts_to_anonymous_user(self):
|
||||
self.authenticate()
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ from flask import Flask, render_template, current_app
|
||||
from flask.ext.mail import Mail
|
||||
from flask.ext.security import login_required, roles_required, roles_accepted
|
||||
from flask.ext.security.decorators import http_auth_required, \
|
||||
auth_token_required
|
||||
auth_token_required, auth_required
|
||||
from flask.ext.security.utils import encrypt_password
|
||||
from werkzeug.local import LocalProxy
|
||||
|
||||
@@ -50,6 +50,11 @@ def create_app(config):
|
||||
def token():
|
||||
return render_template('index.html', content='Token Authentication')
|
||||
|
||||
@app.route('/multi_auth')
|
||||
@auth_required('session', 'token', 'basic')
|
||||
def multi_auth():
|
||||
return render_template('index.html', content='Session, Token, Basic auth')
|
||||
|
||||
@app.route('/post_logout')
|
||||
def post_logout():
|
||||
return render_template('index.html', content='Post Logout')
|
||||
|
||||
Reference in New Issue
Block a user