Based on Laravel (5.1) & Ember. laravel, a user authorization system of js (1.6.2), provides a complete user authorization solution. for PHP-driven multi-page applications, Laravel can perfectly solve user authorization problems. However, in the SPA, laravel degrades to an API server, and the page routing and form submission are completely controlled by the front-end Framework. at this time, there are two problems:
How to implement page access control on the front-end?
How to authorize ajax requests?
How to implement page access control on the front-end?
Ember. js 1.6.2 does not provide the authentication function. I used a third-party extension named ember-simple-auth. This is its Github homepage:
Https://github.com/simplabs/ember-simple-auth
First, install the extension in the root directory of your ember-cli project:
ember install ember-cli-simple-auth
Then configure it in the ember/config/environment. js file. the specific configuration options are described in detail in this document. my configuration is as follows:
// Ember/config/environment. jsENV ['simple-auth'] = {authorizer: 'authorizer: custom' // I used a custom authorization module };
Ember-simple-auth defines a series of mixin classes. as long as your route inherits a certain mixin, it gets some predefined behaviors or functions. For example, my ember/app/routes/application. js content is as follows:
// ember/app/routes/application.js import ApplicationRouteMixin from 'simple-auth/mixins/application-route-mixin';export default Ember.Route.extend(ApplicationRouteMixin, { actions: { invalidateSession: function() { this.get('session').invalidate(); } }});
Application-route-mixin has predefined a series of actions methods. When a session event is triggered, the corresponding action is called to process the event. You can also go to ember/app/routes/application. js's own actions overwrite these methods (ember-simple-auth maintains a session object in local localStorage, which stores all the authorization information generated by the front-end ).
Then, add authenticated-route-mixin to the page route that can only be accessed by authorized users:
// ember/app/routes/user.js import AuthenticatedRouteMixin from 'simple-auth/mixins/authenticated-route-mixin';export default Ember.Route.extend(AuthenticatedRouteMixin,{ model: function(params) { return this.store.find('user',params.user_id); }});
Authenticated-route-mixin ensures that only authorized users can access/users. If not authorized, it is redirected to/login by default. Therefore, in ember/app/routes/login. js, you need to add unauthenticated-route-mixin:
// ember/app/routes/login.js import UnauthenticatedRouteMixin from 'simple-auth/mixins/unauthenticated-route-mixin';export default Ember.Route.extend(UnauthenticatedRouteMixin);
Unauthenticated-route-mixin ensures that the path can be accessed without authorization, which is reasonable for/login.
How to authorize ajax requests?
Custom authenticator: ember/app/authenticators/custom. js
// Ember/app/authenticators/custom. jsimport Base from 'Simple-auth/authenticators/base'; export default base. extend ({/*** Check auth state of frontend *** @ param data (incoming session data) * @ returns {ES6Promise. promise} */restore: function (data) {return new Ember. RSVP. promise (function (resolve, reject) {if (data. is_login) {resolve (data) ;}else {reject () ;}) ;},/*** Permission to login by fron Tend ** @ param obj credentials * @ returns {ES6Promise. Promise} */authenticate: function (credentials) {var authUrl = credentials. isLogin? '/Auth/login':'/auth/register 'return new Ember. RSVP. promise (function (resolve, reject) {Ember. $. ajax ({url: authUrl, type: 'post', data: {email: credentials. identification, password: credentials. password }}). then (function (response) {if (response. login = 'success') {resolve ({is_login: true}) ;}, function (xhr, status, error) {reject (xhr. responseText) ;}) ;},/*** Permission to logout by frontend *** @ returns {ES6Promise. promise} */invalidate: function () {return new Ember. RSVP. promise (function (resolve) {Ember. $. ajax ({url: '/auth/logout', type: 'get '}). then (function (response) {if (response. logout = 'success') {resolve ();}});});}});
The restore, authenticate, and invalidate functions are used to obtain authorization, perform authorization, and cancel authorization.
Custom authorizer: ember/app/authorizers/custom. js
// Ember/app/authorizers/custom. jsimport Base from 'Simple-auth/authorizers/base'; export default base. extend ({authorize: function (jqXHR, requestOptions) {var _ this = this; Ember. $. ajaxSetup ({headers: {'X-XSRF-TOKEN ': Ember. $. cookie ('xsrf-token') // prevents cross-origin attacks}, complete: function (response, state) {// check the server's authorization status if (response. status = 403 & _ this. get ('session '). isAuthenticated) {_ this. get ('session '). invalidate ();}}});}});
The authorize function does two things:
Add 'X-XSRF-TOKEN 'header for each ajax request
Check the authorization status returned by the server and process it.
?? Specifically :??
The header content is the value of the 'xsrf-token' cookie set by laravel, laravel tries to read the header ('x-XSRF-TOKEN ') from each request '), check whether the token value is valid. if the verification succeeds, it is considered as a secure request (this function is available in laravel/app/Http/Middleware/VerifyCsrfToken. php ).
Then, create a Middleware (Middleware) in laravel, and I name it VerifyAuth:
Auth = $ auth;}/*** Handle an incoming request. ** @ param \ Illuminate \ Http \ Request $ request * @ param \ Closure $ next * @ abort 403 * @ return mixed */public function handle ($ request, Closure $ next) {if ($ this-> shouldPassThrough ($ request) | $ this-> auth-> check () {return $ next ($ request);} abort (403, 'unauthorized action. '); // throw an exception, captured and processed by the front end}/*** Determine if the request has a URI that shoshould pass through auth verification. ** @ param \ Illuminate \ Http \ Request $ request * @ return bool */protected function shouldPassThrough ($ request) {foreach ($ this-> include as $ include) {if ($ request-> is ($ include) {return false ;}} return true ;}}
It only performs permission verification on API requests, because AUTH requests are permission operations, and other requests are routed to the front-end as invalid requests, or an error is thrown. If a request is unauthorized, the server throws a 403 error to remind the front-end that the user needs to log on or register.
Finally, implement all the authorization logic in laravel \ app \ Http \ Controllers \ Auth \ AuthController. php:
Middleware ('guest ', ['login t' => 'getlogout']);} public function postLogin (Request $ credentials) // log on to {return $ this-> logUserIn ($ credentials);} public function getLogout () // logout {Auth: logout (); return Response :: json (['logout' => 'success']);} public function postRegister (Request $ credentials) // Create and register a new User {$ newUser = new User; $ newUser-> email = $ credentials ['email ']; $ newUser-> password = bcrypt ($ credentials ['password']); $ newUser-> save (); return $ this-> logUserIn ($ credentials);} protected function logUserIn (Request $ credentials) // implement user logon {$ loginData = ['email '=> $ credentials ['email'], 'password' => $ credentials ['password']; if (Auth: attempt ($ loginData, $ this-> remember) {return Response: json (['login' => 'success']);} else {return Response: json (['login' => 'failed']) ;}}
Summary
Setting page access permissions can prevent unauthorized users from accessing pages that do not belong to them, but the front-end is completely exposed to users. Therefore, the user's authorization status must be maintained by the server. On the one hand, the front end adds tokens to each ajax request to prevent cross-origin attacks. on the other hand, when each request returns, it checks whether the http status code is 403 permission error. If yes, the user is required to be authorized to redirect to the logon page.