Categorías
Python

Enfriar Nuevas funciones en Python 3.8

 

Tabla de Contenidos

  • Introducción
  • construcción del Acceso APIUser RegistrationUser LoginUser Salir
  • Registro de Usuario
  • usuario Iniciar sesión
  • usuario Salir
  • El desarrollo de las RoutingTemplates del lado ServiceClient angular AppAuthentication y ControllersRoute ChangesProtect ciertas rutas
  • autenticación Servicio
  • Servicio de autenticación del lado del cliente

  • enrutamiento plantillas y los controladores de área
  • Cambios
  • proteger ciertos Rutas
  • Persistente sesión
  • Conclusión
  • registro de usuario
  • usuario Iniciar sesión
  • usuario Salir
  • Client- Plantillas y controladores
  • lado de direccionamiento
  • cambios de ruta
  • proteger ciertas rutas

Este puesto proporciona una solución a la pregunta: “¿Cómo puedo manejar la autenticación de usuarios con AngularJS y F Lask?”

Actualizaciones :

  • 17.04.2016: Se ha actualizado a la última versión de Python (3.5.1) y AngularJS (1.4.10); añadido una sección sobre los inicios de sesión persistentes.

Antes de comenzar, tenga en cuenta que esta no es la única solución a la cuestión que nos ocupa, y que ni siquiera puede ser el derecho solución para su situación. Independientemente de la solución a implementar, es importante tener en cuenta que ya que los usuarios finales tienen un control total del navegador, así como el acceso al código de front-end, los datos sensibles de estar en su API del servidor debe ser seguro. Es decir, asegurarse de que se implementa una estrategia de autenticación en el lado del servidor para proteger los puntos finales de API sensibles.

Dicho esto, tenemos que permitir que el flujo de trabajo siguiente:

Introducción

En primer lugar, agarrar el código estándar de la cesión temporal, activar un entorno virtual, e instalar los requisitos.

A continuación, cree la migración inicial:

$ python manage.py create_db
$ python manage.py db init
$ python manage.py db migrate
prueba

a cabo la aplicación:

$ python manage.py runserver

Vaya a http: // localhost: 5000 / y debería ver un simple mensaje de bienvenida – “Bienvenido!”. Una vez hecho esto admirando la página principal, matar al servidor, y la mirada sobre el código dentro de la carpeta “proyecto”:

├── __init__.py
├── config.py
├── models.py
└── static
├── app.js
├── index.html
└── partials
└── home.html

Nada demasiado espectacular. La mayoría de los reside el código / lógica de back-end en el archivo __init__.py , mientras que las aplicaciones reside angular en el directorio “estática”.

Para más información sobre esta estructura, echa un vistazo al curso real del pitón.

Edificio iniciar la conexión API

Vamos con la API de servicios de fondo …

Registro de Usuario

actualización de la función de registro () en __init__.py :

@app.route('/api/register', methods=['POST'])
def register():
json_data = request.json
user = User(
email=json_data['email'],
password=json_data['password']
)
try:
db.session.add(user)
db.session.commit()
status = 'success'
except:
status = 'this user is already registered'
db.session.close()
return jsonify({'result': status})

Aquí, hemos establecido la carga útil enviada con la solicitud POST (desde el lado del cliente) para json_data, que luego se utiliza para crear una instancia de usuario. Posteriormente, se trató a añadir el usuario a la base de datos y confirmar los cambios. Si esto tiene éxito, se añade un usuario, y luego nos devuelve una respuesta JSON a través del método método jsonify con un estado de “éxito”. Si falla, se cierra la sesión y una respuesta de error “este usuario ya está registrado”, se envía.

Asegúrese de añadir las siguientes importaciones, así:

from flask import request, jsonify
from project.models import User

La última importación debe ser importado después creamos el caso del DB – por ejemplo, db = SQLAlchemy (app) – para evitar una dependencia circular. La prueba de

dejar que esto a través de rizo. Pon en marcha el servidor y ejecute el siguiente comando en una nueva ventana de terminal:

$ curl -H "Accept: application/json" \
-H "Content-type: application/json" -X POST \
-d '{"email": "test@test.com", "password": "test"}' \
http://localhost:5000/api/register

Debería ver un mensaje de éxito:

{
"result": "success"
}

intentarlo de nuevo, y usted debería ver un error:

{
"result": "this user is already registered"
}

Por último, abra la base de datos en el navegador de base de datos SQLite para asegurar que el usuario no se insertan en la tabla:

en la entrada …

usuario Iniciar sesión

actualización de la función de inicio de sesión () en __init__.py :

@app.route('/api/login', methods=['POST'])
def login():
json_data = request.json
user = User.query.filter_by(email=json_data['email']).first()
if user and bcrypt.check_password_hash(
user.password, json_data['password']):
session['logged_in'] = True
status = True
else:
status = False
return jsonify({'result': status})

Hemos consultado la base de datos para ver si existe un usuario, basado en el correo electrónico enviado en la carga útil, y si es así, se verifica entonces la contraseña. se devuelve la respuesta apropiada.

Asegúrese de actualizar las importaciones:

from flask import Flask, request, jsonify, session

con el servidor en ejecución, prueba de nuevo con curl-

$ curl -H "Accept: application/json" \
-H "Content-type: application/json" -X POST \
-d '{"email": "test@test.com", "password": "test"}' \
http://localhost:5000/api/login

-y debería ver:

{
"result": true
}

Prueba de nuevo con rizo, el envío de las credenciales de usuario equivocadas, y debería ver:

{
"result": false
}

perfecto!

usuario Salir

actualización de la función de cierre de sesión () de esta manera, con el fin de actualizar la sesión:

@app.route('/api/logout')
def logout():
session.pop('logged_in', None)
return jsonify({'result': 'success'})

Esto debe ser sencillo, y que es fácil adivinar la respuesta a esta solicitud rizo – pero la prueba de nuevo si desea . Una vez hecho esto, vamos a pasar a la parte de cliente!

Desarrollo de la Aplicación angular

necesita el código de la sección anterior? Agarrarlo desde el repositorio.

Ahora, aquí es donde las cosas se ponen un poco complicado. Una vez más, ya que los usuarios finales un acceso completo a la potencia del navegador, así como DevTools y el código del lado del cliente, es vital que no sólo se restringe el acceso a los puntos finales sensibles en el lado del servidor – pero que también no almacena datos sensibles en el del lado del cliente. Tenga esto en cuenta a medida que agrega la funcionalidad de autenticación a su propia pila de aplicaciones. derecho salto de

Let mediante la creación de un servicio de autenticación de mango. Servicio de autenticación

de inicio con la estructura básica de este servicio, añadiendo el siguiente código en un nuevo archivo llamado services.js en el directorio “estática”:

angular.module('myApp').factory('AuthService',
['$q', '$timeout', '$http',
function ($q, $timeout, $http) {

// create user variable
var user = null;

// return available functions for use in controllers
return ({
isLoggedIn: isLoggedIn,
login: login,
logout: logout,
register: register
});

}]);

Aquí, definimos el nombre del servicio, AuthService, y inyectada las dependencias que vamos a utilizar – $ q $, tiempo de espera, $ http – y luego regresó las funciones para su uso fuera del servicio.

Asegúrese de añadir la secuencia de comandos en el archivo index.html :


Vamos a crear cada función …

IsLoggedIn ()

function isLoggedIn() {
if(user) {
return true;
} else {
return false;
}
}

vuelve Esta función cierto si el usuario evalúa a cierto – por ejemplo, un usuario es conectado – de lo contrario devuelve false.

login ()

function login(email, password) {

// create a new instance of deferred
var deferred = $q.defer();

// send a post request to the server
$http.post('/api/login', {email: email, password: password})
// handle success
.success(function (data, status) {
if(status === 200 && data.result){
user = true;
deferred.resolve();
} else {
user = false;
deferred.reject();
}
})
// handle error
.error(function (data) {
user = false;
deferred.reject();
});

// return promise object
return deferred.promise;

}

caso, hemos utilizado el servicio $ q para establecer una promesa, que vamos a acceder a un controlador en el futuro. También usamos el servicio $ http para enviar una petición AJAX a la / api / inicio de sesión de punto final que ya establecimos en nuestro back-end Frasco aplicación.

basa en la respuesta devuelto, ya sea resolver o rechazar el objeto y establecer el valor del usuario a verdadero o falso.

cierre de sesión ()

function logout() {

// create a new instance of deferred
var deferred = $q.defer();

// send a get request to the server
$http.get('/api/logout')
// handle success
.success(function (data) {
user = false;
deferred.resolve();
})
// handle error
.error(function (data) {
user = false;
deferred.reject();
});

// return promise object
return deferred.promise;

}

Aquí, hemos seguido la misma fórmula que la función de inicio de sesión (), excepto que enviamos una petición GET en lugar de POST y, a ser prudentes, en lugar de enviar un error si el usuario no lo hace existen, que acaba de conectarse a cabo el usuario.

registro ()

function register(email, password) {

// create a new instance of deferred
var deferred = $q.defer();

// send a post request to the server
$http.post('/api/register', {email: email, password: password})
// handle success
.success(function (data, status) {
if(status === 200 && data.result){
deferred.resolve();
} else {
deferred.reject();
}
})
// handle error
.error(function (data) {
deferred.reject();
});

// return promise object
return deferred.promise;

}

nuevo, siguió una fórmula similar a la función de cierre de sesión (). Se puede saber lo que está pasando?

Eso es todo por el servicio. Tenga en cuenta que todavía no hemos “usado” este servicio. Con el fin de hacer eso, sólo tenemos que inyectarlo en los componentes necesarios en la aplicación angular. En nuestro caso, que serán los controladores, cada uno asociado a una ruta diferente …

del lado del cliente de enrutamiento

Añadir el resto de las rutas del lado del cliente a la app.js archivo :

myApp.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'static/partials/home.html'
})
.when('/login', {
templateUrl: 'static/partials/login.html',
controller: 'loginController'
})
.when('/logout', {
controller: 'logoutController'
})
.when('/register', {
templateUrl: 'static/partials/register.html',
controller: 'registerController'
})
.when('/one', {
template: '

This is page one!

'
})
.when('wo', {
template: '

This is page two!

'
})
.otherwise({
redirectTo: '/'
});
});

Aquí, hemos creado cinco nuevas rutas. Ahora podemos añadir las plantillas y los controladores posteriores.

plantillas y controladores

volver

mirando nuestras rutas, tenemos que configurar dos parciales / plantillas y tres controladores:

.when('/login', {
templateUrl: 'static/partials/login.html',
controller: 'loginController'
})
.when('/logout', {
controller: 'logoutController'
})
.when('/register', {
templateUrl: 'static/partials/register.html',
controller: 'registerController'
})

sesión

En primer lugar, añadir el código HTML siguiente en un nuevo archivo llamado login.html :

Login

{{errorMessage}}


Añadir este archivo en el directorio “parciales”.

Tomar nota de la forma. Se utilizó la directiva ng-modelo en cada una de las entradas de modo que podemos capturar esos valores en el controlador. Además, cuando se envía el formulario, la ng-presentar asas directiva del evento por el disparo de la función de inicio de sesión ().

A continuación, dentro de la carpeta “estática” y añadir un nuevo archivo llamado controllers.js . Sí, esto va a contener todos los controladores de nuestra aplicación angular. Asegúrese de añadir la secuencia de comandos en el archivo index.html :


Ahora, vamos a añadir el primer controlador:

angular.module('myApp').controller('loginController',
['$scope', '$location', 'AuthService',
function ($scope, $location, AuthService) {

$scope.login = function () {

// initial values
$scope.error = false;
$scope.disabled = true;

// call login from service
AuthService.login($scope.loginForm.email, $scope.loginForm.password)
// handle success
.then(function () {
$location.path('/');
$scope.disabled = false;
$scope.loginForm = {};
})
// handle error
.catch(function () {
$scope.error = true;
$scope.errorMessage = "Invalid username and/or password";
$scope.disabled = false;
$scope.loginForm = {};
});

};

}]);

Por lo tanto, cuando se dispara la función de inicio de sesión (), nos propusimos algunos valores iniciales y después de inicio de sesión de llamada ( ) desde el AuthService, pasando el usuario inputed correo electrónico y contraseña como argumentos. El éxito o el error subsiguiente a continuación se maneja y el DOM / view / plantilla se actualiza adecuadamente.

listos para probar la primera de ida y vuelta – cliente a servidor y luego otra vez a cliente ?

fuego hasta el servidor y vaya a http: // localhost: 5000 / # / inicio de sesión en su navegador. En primer lugar, intente iniciar la sesión con las credenciales de usuario que se utilizan para registrar antes – por ejemplo, test@test.com y prueba. Si todo ha ido bien, debería ser redirigido a la URL principal. A continuación, tratar de iniciar sesión con credenciales no son válidas. Debería ver el mensaje flash error “nombre de usuario válido y / o contraseña”.

Salir

Añadir el controlador:

angular.module('myApp').controller('logoutController',
['$scope', '$location', 'AuthService',
function ($scope, $location, AuthService) {

$scope.logout = function () {
// call logout from service
AuthService.logout()
.then(function () {
$location.path('/login');
});
};

}]);

Aquí, llamamos AuthService.logout () y luego se redirige al usuario a la ruta / entrada después de la promesa que se resuelva.

Añadir un botón a home.html :

Y luego probarlo de nuevo.

Registro

Añadir un nuevo fichero llamado register.html a la carpeta “parciales” y añadir el código HTML siguiente:

Register

{{errorMessage}}


A continuación, agregue el controlador:

angular.module('myApp').controller('registerController',
['$scope', '$location', 'AuthService',
function ($scope, $location, AuthService) {

$scope.register = function () {

// initial values
$scope.error = false;
$scope.disabled = true;

// call register from service
AuthService.register($scope.registerForm.email,
$scope.registerForm.password)
// handle success
.then(function () {
$location.path('/login');
$scope.disabled = false;
$scope.registerForm = {};
})
// handle error
.catch(function () {
$scope.error = true;
$scope.errorMessage = "Something went wrong!";
$scope.disabled = false;
$scope.registerForm = {};
});

};

}]);

Usted ha visto esto antes, así vamos a pasar a la derecha en la prueba.

fuego hasta el servidor y registrar un nuevo usuario en http: // localhost: 5000 / # / Registro. Asegúrese de que el registro de datos en la que un usuario nuevo también.

Bueno, eso es todo por las plantillas y los controladores. Ahora tenemos que añadir la funcionalidad para comprobar si un usuario está conectado en cada cambio de ruta.

cambios de ruta

Agregue el código siguiente para app.js : caso

myApp.run(function ($rootScope, $location, $route, AuthService) {
$rootScope.$on('$routeChangeStart', function (event, next, current) {
if (AuthService.isLoggedIn() === false) {
$location.path('/login');
$route.reload();
}
});
});

El routeChangeStart $ sucede antes de que ocurra el cambio de ruta real. Por lo tanto, cada vez que se accede a una ruta, antes de que se sirve la vista, nos aseguramos de que el usuario se registra en. Prueba de esto!

proteger ciertas rutas

en este momento todas las rutas del lado del cliente requieren que el usuario se ha autentificado. ¿Qué pasa si usted quiere ciertas rutas restringidas y otras vías se abren? Puede añadir el siguiente código a cada controlador de ruta, en sustitución de verdad con datos falsos para las rutas que no desea restringir:

access: {restricted: true}

En nuestro caso, actualizar las rutas, así:

myApp.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'static/partials/home.html',
access: {restricted: true}
})
.when('/login', {
templateUrl: 'static/partials/login.html',
controller: 'loginController',
access: {restricted: false}
})
.when('/logout', {
controller: 'logoutController',
access: {restricted: true}
})
.when('/register', {
templateUrl: 'static/partials/register.html',
controller: 'registerController',
access: {restricted: false}
})
.when('/one', {
template: '

This is page one!

',
access: {restricted: true}
})
.when('wo', {
template: '

This is page two!

',
access: {restricted: false}
})
.otherwise({
redirectTo: '/'
});
});

Ahora acaba de actualizar el código routeChangeStart $ en main.js :

myApp.run(function ($rootScope, $location, $route, AuthService) {
$rootScope.$on('$routeChangeStart', function (event, next, current) {
if (next.access.restricted && AuthService.isLoggedIn() === false) {
$location.path('/login');
$route.reload();
}
});
});
prueba

cada ruta hacia fuera!

Persistente sesión

Por último, lo que sucede en una actualización de la página? Intentalo.

El usuario se registra, ¿verdad? ¿Por qué? Debido a que el controlador y servicios se denominan de nuevo, estableciendo la variable de usuario nulo. Este es un problema ya que el usuario ha iniciado sesión en el lado del cliente.

Afortunadamente, la solución es simple: Dentro de los $ routeChangeStart tenemos que comprobar siempre si un usuario se registra en este momento, está comprobando si IsLoggedIn () es falsa.. Vamos a añadir una nueva función, getUserStatus (), que verifica el estado del usuario en el back-end:

function getUserStatus() {
return $http.get('/api/status')
// handle success
.success(function (data) {
if(data.status){
user = true;
} else {
user = false;
}
})
// handle error
.error(function (data) {
user = false;
});
}

Asegúrese de devolver la función, así:

return ({
isLoggedIn: isLoggedIn,
login: login,
logout: logout,
register: register,
getUserStatus: getUserStatus
});

Luego agregar el controlador de ruta en el lado del cliente:

@app.route('/api/status')
def status():
if session.get('logged_in'):
if session['logged_in']:
return jsonify({'status': True})
else:
return jsonify({'status': False})

Por último, actualizar el $ routeChangeStart:

myApp.run(function ($rootScope, $location, $route, AuthService) {
$rootScope.$on('$routeChangeStart',
function (event, next, current) {
AuthService.getUserStatus()
.then(function(){
if (next.access.restricted && !AuthService.isLoggedIn()){
$location.path('/login');
$route.reload();
}
});
});
});

Pruébalo!

Conclusión

Eso es todo. ¿Preguntas? Comenta abajo.

Una cosa que debe observar es que la aplicación angular se puede utilizar con diversos marcos, siempre y cuando los criterios de valoración están configurados correctamente en las peticiones AJAX. Por lo tanto, se puede tomar fácilmente la parte angular y añadirlo a su Django o pirámide o NodeJS aplicación. ¡Intentalo!

Coge el código final de la cesión temporal. ¡Salud!

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *