rutas paginas mvc example ejemplo con javascript ruby-on-rails angularjs angularjs-authentication

javascript - paginas - AngularJS- Inicio de sesión y autenticación en cada ruta y controlador



paginas web con angularjs (10)

Aquí hay otra posible solución, utilizando el atributo resolve del $stateProvider o el $routeProvider . Ejemplo con $stateProvider :

.config(["$stateProvider", function ($stateProvider) { $stateProvider .state("forbidden", { /* ... */ }) .state("signIn", { /* ... */ resolve: { access: ["Access", function (Access) { return Access.isAnonymous(); }], } }) .state("home", { /* ... */ resolve: { access: ["Access", function (Access) { return Access.isAuthenticated(); }], } }) .state("admin", { /* ... */ resolve: { access: ["Access", function (Access) { return Access.hasRole("ROLE_ADMIN"); }], } }); }])

Access resuelve o rechaza una promesa dependiendo de los derechos de usuario actuales:

.factory("Access", ["$q", "UserProfile", function ($q, UserProfile) { var Access = { OK: 200, // "we don''t know who you are, so we can''t say if you''re authorized to access // this resource or not yet, please sign in first" UNAUTHORIZED: 401, // "we know who you are, and your profile does not allow you to access this resource" FORBIDDEN: 403, hasRole: function (role) { return UserProfile.then(function (userProfile) { if (userProfile.$hasRole(role)) { return Access.OK; } else if (userProfile.$isAnonymous()) { return $q.reject(Access.UNAUTHORIZED); } else { return $q.reject(Access.FORBIDDEN); } }); }, hasAnyRole: function (roles) { return UserProfile.then(function (userProfile) { if (userProfile.$hasAnyRole(roles)) { return Access.OK; } else if (userProfile.$isAnonymous()) { return $q.reject(Access.UNAUTHORIZED); } else { return $q.reject(Access.FORBIDDEN); } }); }, isAnonymous: function () { return UserProfile.then(function (userProfile) { if (userProfile.$isAnonymous()) { return Access.OK; } else { return $q.reject(Access.FORBIDDEN); } }); }, isAuthenticated: function () { return UserProfile.then(function (userProfile) { if (userProfile.$isAuthenticated()) { return Access.OK; } else { return $q.reject(Access.UNAUTHORIZED); } }); } }; return Access; }])

UserProfile copia las propiedades de usuario actuales e implementa la lógica de métodos $hasRole , $hasAnyRole , $isAnonymous y $isAuthenticated (más un método de $refresh , que se explica más adelante):

.factory("UserProfile", ["Auth", function (Auth) { var userProfile = {}; var clearUserProfile = function () { for (var prop in userProfile) { if (userProfile.hasOwnProperty(prop)) { delete userProfile[prop]; } } }; var fetchUserProfile = function () { return Auth.getProfile().then(function (response) { clearUserProfile(); return angular.extend(userProfile, response.data, { $refresh: fetchUserProfile, $hasRole: function (role) { return userProfile.roles.indexOf(role) >= 0; }, $hasAnyRole: function (roles) { return !!userProfile.roles.filter(function (role) { return roles.indexOf(role) >= 0; }).length; }, $isAnonymous: function () { return userProfile.anonymous; }, $isAuthenticated: function () { return !userProfile.anonymous; } }); }); }; return fetchUserProfile(); }])

Auth se encarga de solicitar el servidor, conocer el perfil del usuario (vinculado a un token de acceso adjunto a la solicitud, por ejemplo):

.service("Auth", ["$http", function ($http) { this.getProfile = function () { return $http.get("api/auth"); }; }])

Se espera que el servidor devuelva un objeto JSON de este tipo al solicitar GET api/auth :

{ "name": "John Doe", // plus any other user information "roles": ["ROLE_ADMIN", "ROLE_USER"], // or any other role (or no role at all, i.e. an empty array) "anonymous": false // or true }

Finalmente, cuando Access rechaza una promesa, si usa ui.router , se $stateChangeError evento $stateChangeError :

.run(["$rootScope", "Access", "$state", "$log", function ($rootScope, Access, $state, $log) { $rootScope.$on("$stateChangeError", function (event, toState, toParams, fromState, fromParams, error) { switch (error) { case Access.UNAUTHORIZED: $state.go("signIn"); break; case Access.FORBIDDEN: $state.go("forbidden"); break; default: $log.warn("$stateChangeError event catched"); break; } }); }])

Si usa ngRoute , se disparará el evento $routeChangeError ngRoute :

.run(["$rootScope", "Access", "$location", "$log", function ($rootScope, Access, $location, $log) { $rootScope.$on("$routeChangeError", function (event, current, previous, rejection) { switch (rejection) { case Access.UNAUTHORIZED: $location.path("/signin"); break; case Access.FORBIDDEN: $location.path("/forbidden"); break; default: $log.warn("$stateChangeError event catched"); break; } }); }])

El perfil de usuario también se puede acceder en los controladores:

.state("home", { /* ... */ controller: "HomeController", resolve: { userProfile: "UserProfile" } })

UserProfile contiene las propiedades devueltas por el servidor al solicitar GET api/auth :

.controller("HomeController", ["$scope", "userProfile", function ($scope, userProfile) { $scope.title = "Hello " + userProfile.name; // "Hello John Doe" in the example }])

UserProfile necesita actualizarse cuando un usuario inicia o UserProfile , para que Access pueda gestionar las rutas con el nuevo perfil de usuario. Puede volver a cargar toda la página o llamar a UserProfile.$refresh() . Ejemplo al iniciar sesión:

.service("Auth", ["$http", function ($http) { /* ... */ this.signIn = function (credentials) { return $http.post("api/auth", credentials).then(function (response) { // authentication succeeded, store the response access token somewhere (if any) }); }; }])

.state("signIn", { /* ... */ controller: "SignInController", resolve: { /* ... */ userProfile: "UserProfile" } })

.controller("SignInController", ["$scope", "$state", "Auth", "userProfile", function ($scope, $state, Auth, userProfile) { $scope.signIn = function () { Auth.signIn($scope.credentials).then(function () { // user successfully authenticated, refresh UserProfile return userProfile.$refresh(); }).then(function () { // UserProfile is refreshed, redirect user somewhere $state.go("home"); }); }; }])

Tengo una aplicación AngularJS creada mediante el uso de yeoman, grunt y bower.

Tengo una página de inicio de sesión que tiene un controlador que verifica la autenticación. Si las credenciales son correctas, vuelvo a dirigirme a la página de inicio.

app.js

''use strict''; //Define Routing for app angular.module(''myApp'', []).config([''$routeProvider'', ''$locationProvider'', function($routeProvider,$locationProvider) { $routeProvider .when(''/login'', { templateUrl: ''login.html'', controller: ''LoginController'' }) .when(''/register'', { templateUrl: ''register.html'', controller: ''RegisterController'' }) .when(''/forgotPassword'', { templateUrl: ''forgotpassword.html'', controller: ''forgotController'' }) .when(''/home'', { templateUrl: ''views/home.html'', controller: ''homeController'' }) .otherwise({ redirectTo: ''/login'' }); // $locationProvider.html5Mode(true); //Remove the ''#'' from URL. }]); angular.module(''myApp'').factory("page", function($rootScope){ var page={}; var user={}; page.setPage=function(title,bodyClass){ $rootScope.pageTitle = title; $rootScope.bodylayout=bodyClass; }; page.setUser=function(user){ $rootScope.user=user; } return page; });

LoginControler.js

''use strict''; angular.module(''myApp'').controller(''LoginController'', function($scope, $location, $window,page) { page.setPage("Login","login-layout"); $scope.user = {}; $scope.loginUser=function() { var username=$scope.user.name; var password=$scope.user.password; if(username=="admin" && password=="admin123") { page.setUser($scope.user); $location.path( "/home" ); } else { $scope.message="Error"; $scope.messagecolor="alert alert-danger"; } } });

En la página de inicio tengo

<span class="user-info"> <small>Welcome,</small> {{user.name}} </span> <span class="logout"><a href="" ng-click="logoutUser()">Logout</a></span>

En el loginController , compruebo la información de inicio de sesión y, si tiene éxito, configuro el objeto del usuario en la fábrica de servicios. No sé si esto es correcto o no.

Lo que necesito es que, cuando el usuario inicie sesión, establezca algún valor en el objeto del usuario para que todas las demás puedan obtener ese valor.

Siempre que ocurra algún cambio de ruta, el controlador debe verificar si el usuario está conectado o no. De lo contrario, debería redirigir a la página de inicio de sesión. Además, si el usuario ya inició sesión y regresa a la página, debería ir a la página de inicio. El controlador también debe verificar las credenciales en todas las rutas.

He oído hablar de ng-cookies, pero no sé cómo usarlas.

Muchos de los ejemplos que vi no eran muy claros y usan algún tipo de roles de acceso o algo así. No quiero eso. Solo quiero un filtro de inicio de sesión. ¿Puede alguien darme algunas ideas?


Debe verificar la autenticación del usuario en dos sitios principales.

  • Cuando los usuarios cambian de estado, lo verifican usando ''$routeChangeStart'' devolución ''$routeChangeStart'' llamada ''$routeChangeStart''
  • Cuando se envía una solicitud $ http desde angular, usando un interceptor.

Hace algunos meses, escribí una publicación sobre cómo configurar el registro de usuario y la funcionalidad de inicio de sesión con Angular, puede consultarlo en http://jasonwatmore.com/post/2015/03/10/AngularJS-User-Registration-and-Login-Example.aspx

Compruebo si el usuario ha iniciado sesión en el evento $locationChangeStart , aquí está mi app.js principal que muestra esto:

(function () {     ''use strict'';       angular         .module(''app'', [''ngRoute'', ''ngCookies''])         .config(config)         .run(run);       config.$inject = [''$routeProvider'', ''$locationProvider''];     function config($routeProvider, $locationProvider) {         $routeProvider             .when(''/'', {                 controller: ''HomeController'',                 templateUrl: ''home/home.view.html'',                 controllerAs: ''vm''             })               .when(''/login'', {                 controller: ''LoginController'',                 templateUrl: ''login/login.view.html'',                 controllerAs: ''vm''             })               .when(''/register'', {                 controller: ''RegisterController'',                 templateUrl: ''register/register.view.html'',                 controllerAs: ''vm''             })               .otherwise({ redirectTo: ''/login'' });     }       run.$inject = [''$rootScope'', ''$location'', ''$cookieStore'', ''$http''];     function run($rootScope, $location, $cookieStore, $http) {         // keep user logged in after page refresh         $rootScope.globals = $cookieStore.get(''globals'') || {};         if ($rootScope.globals.currentUser) {             $http.defaults.headers.common[''Authorization''] = ''Basic '' + $rootScope.globals.currentUser.authdata; // jshint ignore:line         }           $rootScope.$on(''$locationChangeStart'', function (event, next, current) {             // redirect to login page if not logged in and trying to access a restricted page             var restrictedPage = $.inArray($location.path(), [''/login'', ''/register'']) === -1;             var loggedIn = $rootScope.globals.currentUser;             if (restrictedPage && !loggedIn) {                 $location.path(''/login'');             }         });     }   })();


La forma más simple de definir el comportamiento personalizado para rutas individuales sería bastante fácil:

1) routes.js : crea una nueva propiedad (como requireAuth ) para cualquier ruta deseada

angular.module(''yourApp'').config([''$routeProvider'', function($routeProvider) { $routeProvider .when(''/home'', { templateUrl: ''templates/home.html'', requireAuth: true }) .when(''/login'', { templateUrl: ''templates/login.html'', }) .otherwise({ redirectTo: ''/home'' }); }])

2) En un controlador de nivel superior que no está vinculado a un elemento dentro de la ng-view (para evitar el conflicto con $routeProvider angular), compruebe si newUrl tiene la propiedad requireAuth y actúe en consecuencia

angular.module(''YourApp'').controller(''YourController'', [''$scope'', ''session'', ''$location'', function($scope, session, $location) { $scope.$on(''$routeChangeStart'', function(angularEvent, newUrl) { if (newUrl.requireAuth && !session.user) { // User isn’t authenticated $location.path("/login"); } }); } ]);


Mi solución se divide en 3 partes: el estado del usuario se almacena en un servicio, en el método de ejecución que observa cuando la ruta cambia y usted verifica si el usuario tiene permiso para acceder a la página solicitada, en su controlador principal mira si el estado del usuario cambia.

app.run([''$rootScope'', ''$location'', ''Auth'', function ($rootScope, $location, Auth) { $rootScope.$on(''$routeChangeStart'', function (event) { if (!Auth.isLoggedIn()) { console.log(''DENY''); event.preventDefault(); $location.path(''/login''); } else { console.log(''ALLOW''); $location.path(''/home''); } }); }]);

Debe crear un servicio (lo Auth ) que manejará el objeto del usuario y tendrá un método para saber si el usuario está conectado o no.

servicio :

.factory(''Auth'', function(){ var user; return{ setUser : function(aUser){ user = aUser; }, isLoggedIn : function(){ return(user)? user : false; } } })

Desde tu app.run , deberías escuchar el evento $routeChangeStart . Cuando la ruta cambie, se verificará si el usuario está conectado (el método isLoggedIn debe manejarlo). No cargará la ruta solicitada si el usuario no está conectado y redirigirá al usuario a la página correcta (en el inicio de sesión de su caso).

El loginController debe usarse en su página de inicio de sesión para manejar el inicio de sesión. Solo debería interactuar con el servicio Auth y establecer al usuario como registrado o no.

loginController :

.controller(''loginCtrl'', [ ''$scope'', ''Auth'', function ($scope, Auth) { //submit $scope.login = function () { // Ask to the server, do your job and THEN set the user Auth.setUser(user); //Update the state of the user in the app }; }])

Desde su controlador principal, podría escuchar si el estado del usuario cambia y reacciona con una redirección.

.controller(''mainCtrl'', [''$scope'', ''Auth'', ''$location'', function ($scope, Auth, $location) { $scope.$watch(Auth.isLoggedIn, function (value, oldValue) { if(!value && oldValue) { console.log("Disconnect"); $location.path(''/login''); } if(value) { console.log("Connect"); //Do something when the user is connected } }, true);


Por ejemplo, una aplicación tiene dos usuarios llamados ap y auc. Estoy pasando una propiedad adicional a cada ruta y manejo la ruta en función de los datos que obtengo en $ routeChangeStart.

Prueba esto:

angular.module("app").config([''$routeProvider'', function ($routeProvider) { $routeProvider. when(''/ap'', { templateUrl: ''template1.html'', controller: ''template1'', isAp: ''ap'', }). when(''/auc'', { templateUrl: ''template2.html'', controller: ''template2'', isAp: ''common'', }). when(''/ic'', { templateUrl: ''template3.html'', controller: ''template3'', isAp: ''auc'', }). when(''/mup'', { templateUrl: ''template4.html'', controller: ''template4'', isAp: ''ap'', }). when(''/mnu'', { templateUrl: ''template5.html'', controller: ''template5'', isAp: ''common'', }). otherwise({ redirectTo: ''/ap'', }); }]);

app.js:

.run([''$rootScope'', ''$location'', function ($rootScope, $location) { $rootScope.$on("$routeChangeStart", function (event, next, current) { if (next.$$route.isAp != ''common'') { if ($rootScope.userTypeGlobal == 1) { if (next.$$route.isAp != ''ap'') { $location.path("/ap"); } } else { if (next.$$route.isAp != ''auc'') { $location.path("/auc"); } } } }); }]);


Puedes usar resolve :

angular.module(''app'',[]) .config(function($routeProvider) { $routeProvider .when(''/'', { templateUrl : ''app/views/login.html'', controller : ''YourController'', controllerAs : ''Your'', resolve: { factory : checkLoginRedirect } }) }

Y, la función de la resolución:

function checkLoginRedirect($location){ var user = firebase.auth().currentUser; if (user) { // User is signed in. if ($location.path() == "/"){ $location.path(''dash''); } return true; }else{ // No user is signed in. $location.path(''/''); return false; } }

Firebase también tiene un método que te ayuda a instalar un observador. Aconsejo instalarlo dentro de un .run :

.run(function(){ firebase.auth().onAuthStateChanged(function(user) { if (user) { console.log(''User is signed in.''); } else { console.log(''No user is signed in.''); } }); }


Siento que de esta manera es más fácil, pero tal vez solo sea una preferencia personal.

Cuando especifique su ruta de inicio de sesión (y cualquier otra ruta anónima, por ejemplo: / register, / logout, / refreshToken, etc.), agregue:

allowAnonymous: true

Entonces, algo como esto:

$stateProvider.state(''login'', { url: ''/login'', allowAnonymous: true, //if you move this, don''t forget to update //variable path in the force-page check. views: { root: { templateUrl: "app/auth/login/login.html", controller: ''LoginCtrl'' } } //Any other config }

No es necesario que especifique "allowAnonymous: false", si no está presente, se supone que es falso, en el cheque. En una aplicación donde la mayoría de las URL se fuerzan autenticadas, esto es menos trabajo. Y más seguro; Si olvida agregarlo a una nueva URL, lo peor que puede pasar es que una URL anónima esté protegida. Si lo haces de otra manera, especificando "requireAuthentication: true" y olvidas agregarlo a una URL, estás filtrando una página sensible al público.

Luego ejecute esto donde sienta que se ajusta mejor al diseño de su código.

//I put it right after the main app module config. I.e. This thing: angular.module(''app'', [ /* your dependencies*/ ]) .config(function (/* you injections */) { /* your config */ }) //Make sure there''s no '';'' ending the previous line. We''re chaining. (or just use a variable) // //Then force the logon page .run(function ($rootScope, $state, $location, User /* My custom session obj */) { $rootScope.$on(''$stateChangeStart'', function(event, newState) { if (!User.authenticated && newState.allowAnonymous != true) { //Don''t use: $state.go(''login''); //Apparently you can''t set the $state while in a $state event. //It doesn''t work properly. So we use the other way. $location.path("/login"); } }); });


Todos han sugerido una gran solución por la cual estás preocupado por la sesión en el lado del cliente. Quiero decir que cuando el estado / url cambia, supongo que estás haciendo una llamada ajax para cargar los datos para el temperado.

Note :- To Save user''s data you may use `resolve` feature of `ui-router`. Check cookie if it exist load template , if even cookies doesn''t exist than there is no chance of logged in , simply redirect to login template/page.

Ahora el servidor devuelve los datos ajax con cualquier api. Ahora el punto entró en juego, devuelve tipos de retorno estándar utilizando el servidor de acuerdo con el estado de usuario registrado. Verifique esos códigos de retorno y procese su solicitud en el controlador. Nota: - Para el controlador que no requiere una llamada ajax de forma nativa, puede llamar a una solicitud en blanco al servidor como este server.location/api/checkSession.php y esto es checkSession.php

<?php/ANY_LANGUAGE session_start();//You may use your language specific function if required if(isset($_SESSION["logged_in"])){ set_header("200 OK");//this is not right syntax , it is just to hint } else{ set_header("-1 NOT LOGGED_IN");//you may set any code but compare that same //code on client side to check if user is logged in or not. } //thanks.....

Del lado del cliente dentro del controlador o a través de cualquier servicio como se muestra en otras respuestas

$http.get(dataUrl) .success(function (data){ $scope.templateData = data; }) .error(function (error, status){ $scope.data.error = { message: error, status: status}; console.log($scope.data.error.status); if(status == CODE_CONFIGURED_ON_SERVER_SIDE_FOR_NON_LOGGED_IN){ //redirect to login });

Nota: - Actualizaré más mañana o en el futuro


app.js

''use strict''; // Declare app level module which depends on filters, and services var app= angular.module(''myApp'', [''ngRoute'',''angularUtils.directives.dirPagination'',''ngLoadingSpinner'']); app.config([''$routeProvider'', function($routeProvider) { $routeProvider.when(''/login'', {templateUrl: ''partials/login.html'', controller: ''loginCtrl''}); $routeProvider.when(''/home'', {templateUrl: ''partials/home.html'', controller: ''homeCtrl''}); $routeProvider.when(''/salesnew'', {templateUrl: ''partials/salesnew.html'', controller: ''salesnewCtrl''}); $routeProvider.when(''/salesview'', {templateUrl: ''partials/salesview.html'', controller: ''salesviewCtrl''}); $routeProvider.when(''/users'', {templateUrl: ''partials/users.html'', controller: ''usersCtrl''}); $routeProvider.when(''/forgot'', {templateUrl: ''partials/forgot.html'', controller: ''forgotCtrl''}); $routeProvider.otherwise({redirectTo: ''/login''}); }]); app.run(function($rootScope, $location, loginService){ var routespermission=[''/home'']; //route that require login var salesnew=[''/salesnew'']; var salesview=[''/salesview'']; var users=[''/users'']; $rootScope.$on(''$routeChangeStart'', function(){ if( routespermission.indexOf($location.path()) !=-1 || salesview.indexOf($location.path()) !=-1 || salesnew.indexOf($location.path()) !=-1 || users.indexOf($location.path()) !=-1) { var connected=loginService.islogged(); connected.then(function(msg){ if(!msg.data) { $location.path(''/login''); } }); } }); });

loginServices.js

''use strict''; app.factory(''loginService'',function($http, $location, sessionService){ return{ login:function(data,scope){ var $promise=$http.post(''data/user.php'',data); //send data to user.php $promise.then(function(msg){ var uid=msg.data; if(uid){ scope.msgtxt=''Correct information''; sessionService.set(''uid'',uid); $location.path(''/home''); } else { scope.msgtxt=''incorrect information''; $location.path(''/login''); } }); }, logout:function(){ sessionService.destroy(''uid''); $location.path(''/login''); }, islogged:function(){ var $checkSessionServer=$http.post(''data/check_session.php''); return $checkSessionServer; /* if(sessionService.get(''user'')) return true; else return false; */ } } });

sessionServices.js

''use strict''; app.factory(''sessionService'', [''$http'', function($http){ return{ set:function(key,value){ return sessionStorage.setItem(key,value); }, get:function(key){ return sessionStorage.getItem(key); }, destroy:function(key){ $http.post(''data/destroy_session.php''); return sessionStorage.removeItem(key); } }; }])

loginCtrl.js

''use strict''; app.controller(''loginCtrl'', [''$scope'',''loginService'', function ($scope,loginService) { $scope.msgtxt=''''; $scope.login=function(data){ loginService.login(data,$scope); //call login service }; }]);