How to allow users to login protected flask-rest-a

2019-03-15 03:40发布

Guys If My Question is not clear please comment below.

Basic HTTP Authentication for REST API in flask+angularjs

I just want to login to the flask-rest-api in angularjs, I don't know how to send the login info (username and password)to flask-rest-api. In this app There is one table after successfully login and it will load the data. Here we are not using any data-base but username and password is hard-coded in rest-server code. and username="admin" and password="1234". When can modify, update, addNewData. I took this from this blog, here they are using in knockout, I am trying to in Angularjs

Login form

<div id="login" class="modal hide fade" tabindex="=1" role="dialog" aria-labelledby="loginLabel" aria-hidden="true">
        <div class="modal-header">
            <h3 id="loginLabel">Sign In</h3>
        </div>
        <div class="modal-body">
            <form class="form-horizontal">
                <div class="control-group">
                    <label class="control-label" for="inputUsername">Username</label>
                    <div class="controls">
                        <input ng-model="username" type="text" id="inputUsername" placeholder="Username">
                    </div>
                </div>
                <div class="control-group">
                    <label class="control-label" for="inputPassword">Password</label>
                    <div class="controls">
                        <input ng-model="password" type="password" id="inputPassword" placeholder="Password">
                    </div>
                </div>
            </form>
        </div>
        <div class="modal-footer">
            <button ng-click="submitData(username, password)" class="btn btn-primary" data-dismiss="modal" aria-hidden="true">Sign In</button>
        </div>
    </div>

HTML Code Which call Login Model

<div class="navbar">
      <div class="navbar-inner">
        <a class="btn" data-toggle="modal" data-target="#login">Login</a>
      </div>
</div>

AngulurJS code

<script>

                    var app = angular.module('myApp', []);
                    app.controller('tasksCtrl', function($scope, $http) {
                        $scope.submitData=function(username, password){
                            var config={
                               params:{
                                   username:username, password:password
                               }
                            };
                        };
                        //$http.get("data.json")
                        $http.get("/todo/api/v1.0/tasks")
                        .success(function(response) {
                            console.log(response.tasks)
                            $scope.tasks = response.tasks;
                        });

                        $scope.editTask = function(task) {
                            $scope.selectedTask = task;
                        };
                        $scope.removeRow = function(task) {
                            $scope.tasks.splice(task, 1);
                        };
                        $scope.addNewTask = function() {
                            //$scope.tasks.push({title :$scope.task1,description: $scope.description1});
                            $scope.tasks.push({title: $scope.task1, description: $scope.description1});
                            $scope.task1 = '';
                            $scope.description1 = '';
                            //   $scope.tasks.push('dhsh');
                        };
                    });    
        </script>

REST-API-SERVER

import six
from flask import Flask, jsonify, abort, request, make_response, url_for, render_template 
from flask.ext.httpauth import HTTPBasicAuth

app = Flask(__name__, static_url_path="")
auth = HTTPBasicAuth()


@auth.get_password
def get_password(username):
    if username == 'admin':
        return '1234'
    return None


@auth.error_handler
def unauthorized():
    return make_response(jsonify({'error': 'Unauthorized access'}), 403)


@app.errorhandler(400)
def bad_request(error):
    return make_response(jsonify({'error': 'Bad request'}), 400)


@app.errorhandler(404)
def not_found(error):
    return make_response(jsonify({'error': 'Not found'}), 404)


tasks = [
    {
        'id': 1,
        'title': u'Buy groceries',
        'description': u'Milk, Cheese, Pizza, Fruit, Tylenol',
        'done': False
    },
    {
        'id': 2,
        'title': u'Learn Python',
        'description': u'Need to find a good Python tutorial on the web',
        'done': False
    }
]


def make_public_task(task):
    new_task = {}
    for field in task:
        if field == 'id':
            new_task['uri'] = url_for('get_task', task_id=task['id'],
                                      _external=True)
        else:
            new_task[field] = task[field]
    return new_task

@app.route('/')
@auth.login_required
def index():
   return render_template('index.html')

@app.route('/todo/api/v1.0/tasks', methods=['GET'])
@auth.login_required
def get_tasks():
    return jsonify({'tasks': [make_public_task(task) for task in tasks]})


@app.route('/todo/api/v1.0/tasks/<int:task_id>', methods=['GET'])
@auth.login_required
def get_task(task_id):
    task = [task for task in tasks if task['id'] == task_id]
    if len(task) == 0:
        abort(404)
    return jsonify({'task': make_public_task(task[0])})


@app.route('/todo/api/v1.0/tasks', methods=['POST'])
@auth.login_required
def create_task():
    if not request.json or 'title' not in request.json:
        abort(400)
    task = {
        'id': tasks[-1]['id'] + 1,
        'title': request.json['title'],
        'description': request.json.get('description', ""),
        'done': False
    }
    tasks.append(task)
    return jsonify({'task': make_public_task(task)}), 201


@app.route('/todo/api/v1.0/tasks/<int:task_id>', methods=['PUT'])
@auth.login_required
def update_task(task_id):
    task = [task for task in tasks if task['id'] == task_id]
    if len(task) == 0:
        abort(404)
    if not request.json:
        abort(400)
    if 'title' in request.json and \
            not isinstance(request.json['title'], six.string_types):
        abort(400)
    if 'description' in request.json and \
            not isinstance(request.json['description'], six.string_types):
        abort(400)
    if 'done' in request.json and type(request.json['done']) is not bool:
        abort(400)
    task[0]['title'] = request.json.get('title', task[0]['title'])
    task[0]['description'] = request.json.get('description',
                                              task[0]['description'])
    task[0]['done'] = request.json.get('done', task[0]['done'])
    return jsonify({'task': make_public_task(task[0])})


@app.route('/todo/api/v1.0/tasks/<int:task_id>', methods=['DELETE'])
@auth.login_required
def delete_task(task_id):
    task = [task for task in tasks if task['id'] == task_id]
    if len(task) == 0:
        abort(404)
    tasks.remove(task[0])
    return jsonify({'result': True})


if __name__ == '__main__':
    app.run(debug=True)

2条回答
Melony?
2楼-- · 2019-03-15 03:57

You could try the simplest, least secure way of doing this, which is to pass the login information like this:

username:password@yoursite.com

If you try it with any website it attempts to log in using whatever you provided. It might work in your environment.

As mentioned in the above article, you should really set up a Auth Service, which requires you to log in on the front end. It looks like you are not using routing, or angular-ui-router. With routing you can redirect people to the login route, before allowing them to access any of the other routes. This question has the answer I used to set up this behavior. And here's the example which shows certain routes are only accessible when authenticated.

查看更多
等我变得足够好
3楼-- · 2019-03-15 03:58

The way you make basic authentication from client side is by supplying Authorization: Basic <encoded username:password> header in HTTP request.

encoded username:password is done in specific manner described below:

  1. Username and password are combined into a string "username:password"
  2. The resulting string is then encoded using the RFC2045-MIME variant of Base64, except not limited to 76 char/line[9]

So modify your rest calls to include above header in your Angularjs code or find a library to do that.

as @Boris mentioned in comments above, see this link http://jasonwatmore.com/post/2014/05/26/AngularJS-Basic-HTTP-Authentication-Example.aspx it has nice Angular service written to do just what you want

查看更多
登录 后发表回答