Categories
Software Technology

Is Phalcon really so good?

Phalcon recently gained a lot of popularity, all thanks to different approaches to the problem of applications performance. In short, they achieved what other tools are missing – really high level of efficiency in the processing code.

Check out their official website for details.

How does it look in practice? In fact, the results are very impressive (compared to other leading frameworks), because the tests RPS (Requests Per Second) and TPR (Time Per Request) reaches at least twice better results than its competitors. Also, in the challenge with HHVM (HipHop Virtual Machine) from Facebook, high-level language – Zephir (which is the Phalcon’s basis) wins in all benchmarks. However, an entry about this will be published another time, and now I will try to focus on the pros and cons of the Phalcon. Below you can find charts which are showing the benchmark tests results. There are more than three frameworks (mentioned in the article) – it’s just to compare with other popular tools.

As you know, this kind of data may not mean anything, because everything depends on the dimensions of the application and performance of the machine, which is serving it. Low performance of the software is frequently caused by many, wrongly constructed queries to overflowed and unwisely designed database, which is even served by weak hardware without any SSD. Most common this is the reason of long delays. In that case efficient code won’t change anything so you should ask yourself at this stage – is it worth it?

I don’t think so. Personally, I believe that tools such as Symfony and Laravel are better equipped to be the core of medium and large applications, and this is because it’s actually facilitate the programmer’s work and relieves the customer from costs. The new functionalities are produced faster, the code is much better organized, finding support and consultation are also easier than if we were doing the same thing in Phalcon, and the introduction of a new team member into the project is not a problem, because he should actually know this environment from other projects. As a programmer, I believe that software development with this framework makes sense, but you have to think about it seriously and consider all the options (not just performance) before it’s too late. This framework has its own, very narrow purpose. From this point of view, Symfony and Laravel offers much more, have better support and they are not as weak as statistics show. You can squeeze more from each code, it’s just matter of time and team experience.

An important feature that distinguishes Phalcon is it’s size. At the start application doesn’t weigh practically nothing and the right component (extension) size is about 3MB. It makes Phalcon easy to migrate and work with at the start, but the lack of imposed structure and any files can introduce chaos and slow down the development at an advanced stage of the project.

In conclusion, I think that Phalcon is the best for small applications, and the idea has a future and will certainly put the PHP language into a new age, despite the fact that there is a similar, less known project (called “yaf”). Anyway Symfony and Laravel are unbeatable with more complex projects on which work is in progress more than a few dozen days. So it all depends on what you want to achieve and at what cost.

author: Maciej Tomaszewski

Categories
Software Technology Uncategorized

Authentication in AngularJS (or similar) based application

Implementation of the concept described below and also a demo application is available here: https://github.com/witoldsz/angular-http-auth.


Hello again,

today I would like to write a little bit about how am I handling authentication in an application front-end running inside web browser, using AngularJS.

Traditional server ‘login form’? Well… no, thank you.

At the beginning, I did not realize that traditional and commonly used form based authentication does not suit my client-side application. The major problem lies in a key difference between traditional – server-side, and client-side applications. In server-side applications, no one else but server itself knows user state and intentions, whereas in client-side applications this is no longer true.
Let’s take a look at a sample server-side web application flow of events:

  • user asks for a web page: something.com,
  • server generates markup and sends it back,
  • user chooses to visit a secured sub-page: something.com/secured,
  • server figures out that user does need to authenticate itself, so it:
    – remembers what user asked for,
    – responds with a login form (or a redirect to) instead of a requested content,
  • once user sends credentials back to the server, it serves what user initially asked for,
  • user keeps visiting secured pages and filling secured forms until their authorization expires (for whatever reason),
  • server once again responses with a login form and once user provides credentials, server redirects them back whenever they wanted to go.

Same application, but different flow:

  • user asks for: something.com/secured/formXyz,
  • server sends a login form,
  • user logs in, fills a long and complicated form, but they are doing it so long that theirs session expires,
  • user submits a form, but since the session is not valid anymore, login screen appears,
  • once user logs in, server can process the submitted form, no need to re-enter everything again.

Now let’s see how it is in client-side application, running inside a web browser:

  • user types somewhere.com in an address bar,
  • browser sends a “Content-Type: text/html” request,
  • server sends back a page with client-side application code,
  • code starts to execute and asks for user name (e.g. it wants to display user name in the upper right corner), so next request is issued, e.g.: “Content-Type: application/json”
  • traditional login form does not make sense here, as browser is not requesting a web page, but some data instead. Something is not right here.

OK, so let’s try other way around:

  • user asks for somewhere.com
  • entire site is hidden behind a login form authentication mechanism, so instead of an application, user is presented a form, so they can provide credentials,
  • once user submits, the originally requested page is provided, so as it was before: application loads, issues a new data request (application/json) for user name and receives it back, everything is nice so far… but let’s assume that our session expires (for whatever reason) while we are in the middle of a long and complicated form…

Guess what? We are exactly in the same place as before: our application is up and running, but our session is not valid any more and form based authentication is useless at this point. Or isn’t it?
Let’s try to adapt. Using AngularJS, we can simply write an http interceptor. Such a interceptor can check every response and once it detects a login form, we can… well…

  • We can redirect ourselves to a login page, but this is a complicated task, because server does not know where we are at the moment (or to be more precise: what is our state, what were we doing). Remember, client-side application is client-side, how is server supposed to figure out what to do next, after we logged in? From server-side point of view we are sitting on one page all the time.
  • We can be smarter: we can bring an IFRAME to life, it will show login form. But this is also complicated: we have to figure out somehow what is happening inside such an IFRAME. How to detect successful login? Is it easy? Hard? Not that hard but tricky?

Of course everything is doable, but after investigation, I did something else. Very simple and clean, but requires server side adjustments.
Solution: client-side login form when server answers: status 401.
My solution assumes the following server side behaviour: for every /resources/* call, if user is not authorized, response a 401 status. Otherwise, when user is authorized or when not a /resources/* request, send what client asked for. No login forms, but we still need some login URL, so our application can send login and password there. Plain-old cookie based sessions? Why not, they work for me, web browsers and application servers handle them automatically by default.
AngularJS has a $http service. It allows custom interceptors to be plugged in:

[sourcecode language=”javascript”]
myapp.config(function($httpProvider) {
function exampleInterceptor($q, $log) {
function success(response) {
$log.info(‘Successful response: ‘ + response);
return response;
}
function error(response) {
var status = response.status;
$log.error(‘Response status: ‘ + status + ‘. ‘ + response);
return $q.reject(response); //similar to throw response;
}
return function(promise) {
return promise.then(success, error);
}
}
$httpProvider.responseInterceptors.push(exampleInterceptor);
});
[/sourcecode]

Nice thing is that from ‘response’ parameter we can rebuild the request. To fully understand how the $http interceptor works, we need to understand $q.
The goal is to be able to:

  • capture 401 response,
  • save the request parameters, so in the future we can reconstruct original request,
  • create and return new object representing server’s future answer (instead of returning the original failed response),
  • broadcast that login is required, so application can react, in particular login form can appear,
  • listen to login successful events, so we can gather all the saved request parameters, resend them again and trigger all the ‘future’ objects (returned previously).

Nice thing about the solution above is that when you request something, but server responds with status 401, you do not have (and you cannot) handle this. Interceptor will handle this for you. You will eventually receive the response. It will come as nothing had happened, just a little bit later (unless user won’t provide valid credentials).
OK, so here is a bit of code.

[sourcecode language=”javascript”]
/**
* $http interceptor.
* On 401 response – it stores the request and broadcasts ‘event:loginRequired’.
*/
myapp.config(function($httpProvider) {
var interceptor = [‘$rootScope’, ‘$q’, function(scope, $q) {
function success(response) {
return response;
}
function error(response) {
var status = response.status;
if (status === 401) {
var deferred = $q.defer();
var req = {
config: response.config,
deferred: deferred
};
scope.requests401.push(req);
scope.$broadcast(‘event:loginRequired’);
return deferred.promise;
}
// otherwise
return $q.reject(response);
}
return function(promise) {
return promise.then(success, error);
}
}];
$httpProvider.responseInterceptors.push(interceptor);
});
[/sourcecode]

[sourcecode language=”javascript”]
myapp.run([‘$rootScope’, ‘$http’, function(scope, $http) {
/**
* Holds all the requests which failed due to 401 response.
*/
scope.requests401 = [];
/**
* On ‘event:loginConfirmed’, resend all the 401 requests.
*/
scope.$on(‘event:loginConfirmed’, function() {
var i, requests = scope.requests401;
for (i = 0; i < requests.length; i++) {
retry(requests[i]);
}
scope.requests401 = [];
function retry(req) {
$http(req.config).then(function(response) {
req.deferred.resolve(response);
});
}
});
/**
* On ‘event:loginRequest’ send credentials to the server.
*/
scope.$on(‘event:loginRequest’, function(event, username, password) {
var payload = $.param({j_username: username, j_password: password});
var config = {
headers: {‘Content-Type’: ‘application/x-www-form-urlencoded; charset=UTF-8’}
};
$http.post(‘j_spring_security_check’, payload, config).success(function(data) {
if (data === ‘AUTHENTICATION_SUCCESS’) {
scope.$broadcast(‘event:loginConfirmed’);
}
});
});
/**
* On ‘logoutRequest’ invoke logout on the server and broadcast ‘event:loginRequired’.
*/
scope.$on(‘event:logoutRequest’, function() {
$http.put(‘j_spring_security_logout’, {}).success(function() {
ping();
});
});
/**
* Ping server to figure out if user is already logged in.
*/
function ping() {
$http.get(‘rest/ping’).success(function() {
scope.$broadcast(‘event:loginConfirmed’);
});
}
ping();
}]);
[/sourcecode]

I wanted to provide a working example with a login window, using jsfiddle.net, but have to postpone it. It is getting a little bit late now, so I am finishing this entry here. I hope you like it 🙂
author: Witold Szczerba