20 November 2014

Implementing Spring Security with JSF (Login + RedirectStrategy)

When implementing Spring Security in JSF application, many problems happens, and one of the most important one is the redirection in case of HTTP errors!

In this post, I'll take about 2 points, the first point is how to implement the Login page (you will find many resources illustrate this - for example this) but I'll extend it allowing the user to continue on the page he was coming from (aka. Saved Request URL), the second point and the more important one is handling HTTP errors in case of Ajax requests.

Point #1 Handle Login From:

Initially, you have your JSF application (in my case I use Primefaces, but shouldn't matter at all, because the solution is JSF related not primefaces-related)


You have your xhtml login page (login.xhtml) like this:


<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui">
<f:view>
    <h:form id="loginForm">
        <h:messages style="color: red;" />

        <table>
            <tr>
                <td><p:outputLabel for="usernameTxt" value="Username" /></td>
                <td><p:inputText id="usernameTxt" value="#{loginBean.username}" /></td>
            </tr>
            <tr>
                <td><p:outputLabel for="passwordTxt" value="Password" /></td>
                <td><p:password id="passwordTxt" value="#{loginBean.password}" /></td>
            </tr>
            <tr>
                <td colspan="2"><p:commandButton value="Login"
                        action="#{loginBean.login}" /></td>
            </tr>
        </table>
    </h:form>
</f:view>

</html>

Very simple!, regularly with spring security, we submit the form to /j_spring_security_check but we have different situation here, we have a command button which send POST request to the same URL of the page.

2 solutions here, I'll take about one of them (as appears in Macro-blog link above) which is using a reference for the authenticationManager from the bean action method:

first, you need to expose the authenticationManager in the security context configuration file:


    <authentication-manager alias="authenticationManager">
        <authentication-provider>
            <user-service>
                <user name="admin" password="admin" authorities="ROLE_ADMIN" />
            </user-service>
        </authentication-provider>
    </authentication-manager>

Note the use of "alias" attribute.

Then in you JSF Managed bean, you can inject it and use it as the following:

@Inject
private AuthenticationManager authenticationManager;

@Setter
@Getter
private String username;

@Setter
@Getter
private String password;

public LoginBean() {
}

public String login() {
    try {
        Authentication authentication = authenticationManager
                .authenticate(new UsernamePasswordAuthenticationToken(
                        this.username, this.password));

        SecurityContextHolder.getContext()
                .setAuthentication(authentication);

    } catch (AuthenticationException ex) {
        log.equals(ex.getMessage());
        Util.addMessage("Login Failed: " + ex.getMessage());
        return "";
    }

    return Util.getSavedUrl() + "?faces-redirect=true";
}

The code above is pretty clear, If fail (AuthenticationExcpetion thrown, show error message), else redirect to some URL.

The point here is some URL is critical, because if the user was trying to access resource "A", then spring security asked him to login first, then after login he should access resource "A" itself not a welcome screen.

This handled by spring security, but in our case, we need to ask Spring-security explicity to give us the "SavedURL" from the session. so the implmenetation of Util.getSavedUrl() is below:

public static String getSavedUrl() {
    HttpServletRequest request = ((HttpServletRequest) FacesContext
            .getCurrentInstance().getExternalContext().getRequest());

    SavedRequest savedRequest = new HttpSessionRequestCache().getRequest(
            request, (HttpServletResponse) FacesContext
                    .getCurrentInstance().getExternalContext()
                    .getResponse());

    if (savedRequest != null) {
        try {
            URL url = new URL(savedRequest.getRedirectUrl());
            return url.getFile().substring(
                    request.getContextPath().length());
        } catch (Exception e) {
            log.error(e.getMessage() + " Using default URL");
        }
    }
    return "admin/index.xhtml?faces-redirect=true"; // default page!
}

And that's all for the first point.

Point #2 Handle HTTP error codes for Ajax requests:

JSF (and jsf based frameworks) uses Ajax in many cases,  the PrimeFaces autocomplete is a good example.

Originally with regular HTTP requests (non-Ajax), when the user try to access a resource after session expired, spring security will send error code 302 to the browser, when browser sees the response code, he will do the redirect the Login page.


But in case of Ajax requests, the ajax client should handle this on his own.

In case of JSF, (I am not the JSF expert Guy :D ) JSF uses some internal protocol sending XML between the server and the client, and this XML is well defined in matter if the server wants the client to do redirect, the server doesn't send 302 for the client, instead, he sends a response like:

<?xml version="1.0" encoding="UTF-8"?>
<partial-response>
    <redirect url="URL to redirect to"></redirect>
</partial-response>

So, when the ajax caller (who send the JSF request), see this response, he will do redirect immediately.


So, to integrate this with Spring security we need to tell it override the cod that sends the response code and add the above xml payload just in case of Ajax requests.

To do this Spring security provide a redirect strategy (org.springframework.security.web.RedirectStrategy) that you can extends and hook the spring security at some points.

So, here's a sample implementation:


package testing.ss;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.util.UrlUtils;

/**
 * Based on code from DefaultDirectStrategy and
 * https://gist.github.com/banterCZ/5160269
 * 
 * @author mhewedy
 *
 */
public class JsfRedirectStrategy implements RedirectStrategy {

    private static final String FACES_REQUEST_HEADER = "faces-request";

    protected final Log logger = LogFactory.getLog(getClass());

    private boolean contextRelative;

    /**
     * Redirects the response to the supplied URL.
     * <p>
     * If <tt>contextRelative</tt> is set, the redirect value will be the value
     * after the request context path. Note that this will result in the loss of
     * protocol information (HTTP or HTTPS), so will cause problems if a
     * redirect is being performed to change to HTTPS, for example.
     */
    public void sendRedirect(HttpServletRequest request,
            HttpServletResponse response, String url) throws IOException {
        String redirectUrl = calculateRedirectUrl(request.getContextPath(), url);
        redirectUrl = response.encodeRedirectURL(redirectUrl);

        boolean ajaxRedirect = "partial/ajax".equals(request
                .getHeader(FACES_REQUEST_HEADER));
        if (ajaxRedirect) {

            String ajaxRedirectXml = createAjaxRedirectXml(redirectUrl);
            logger.debug("Ajax partial response to redirect: "
                    + ajaxRedirectXml);

            response.setContentType("text/xml");
            response.getWriter().write(ajaxRedirectXml);
        } else {
            logger.debug("Non-ajax redirecting to '" + redirectUrl + "'");
            response.sendRedirect(redirectUrl);
        }
    }

    private String calculateRedirectUrl(String contextPath, String url) {
        if (!UrlUtils.isAbsoluteUrl(url)) {
            if (contextRelative) {
                return url;
            } else {
                return contextPath + url;
            }
        }

        // Full URL, including http(s)://

        if (!contextRelative) {
            return url;
        }

        // Calculate the relative URL from the fully qualified URL, minus the
        // last
        // occurrence of the scheme and base context.
        url = url.substring(url.lastIndexOf("://") + 3); // strip off scheme
        url = url.substring(url.indexOf(contextPath) + contextPath.length());

        if (url.length() > 1 && url.charAt(0) == '/') {
            url = url.substring(1);
        }

        return url;
    }

    /**
     * If <tt>true</tt>, causes any redirection URLs to be calculated minus the
     * protocol and context path (defaults to <tt>false</tt>).
     */
    public void setContextRelative(boolean useRelativeContext) {
        this.contextRelative = useRelativeContext;
    }

    // from https://gist.github.com/banterCZ/5160269
    private String createAjaxRedirectXml(String redirectUrl) {
        return new StringBuilder()
                .append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
                .append("<partial-response><redirect url=\"")
                .append(redirectUrl)
                .append("\"></redirect></partial-response>").toString();
    }

}


Then you have to hock the LoginUrlAuthenticationEntryPoint, but because the RedirectStrategy is a final variable, you have to extend it like this:

package testing.ss;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.RedirectStrategy;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;

/**
 * Based on code from LoginUrlAuthenticationEntryPoint
 * 
 * @author mhewedy
 *
 */
// see http://forum.spring.io/forum/spring-projects/security/88829-is-it-possible-to-change-spring-security-3-redirects-from-full-urls-to-relative-urls
@SuppressWarnings("deprecation")
public class JsfLoginUrlAuthenticationEntryPoint extends
        LoginUrlAuthenticationEntryPoint {

    Log log = LogFactory.getLog(getClass());

    private RedirectStrategy redirectStrategy;

    public void setRedirectStrategy(RedirectStrategy redirectStrategy) {
        this.redirectStrategy = redirectStrategy;
    }

    @Override
    public void commence(HttpServletRequest request,
            HttpServletResponse response, AuthenticationException authException)
            throws IOException, ServletException {

        String redirectUrl = null;

        if (isUseForward()) {

            if (isForceHttps() && "http".equals(request.getScheme())) {
                // First redirect the current request to HTTPS.
                // When that request is received, the forward to the login page
                // will be used.
                redirectUrl = buildHttpsRedirectUrlForRequest(request);
            }

            if (redirectUrl == null) {
                String loginForm = determineUrlToUseForThisRequest(request,
                        response, authException);

                log.debug("Server side forward to: " + loginForm);

                RequestDispatcher dispatcher = request
                        .getRequestDispatcher(loginForm);

                dispatcher.forward(request, response);

                return;
            }
        } else {
            // redirect to login page. Use https if forceHttps true

            redirectUrl = buildRedirectUrlToLoginPage(request, response,
                    authException);
        }
        redirectStrategy.sendRedirect(request, response, redirectUrl);
    }

}


Then go back and configure http tag to reference the Entry Point:

<http auto-config="true" use-expressions="true" entry-point-ref="authenticationEntryPoint">
    .....
</http>

<beans:bean id="authenticationEntryPoint"
    class="testing.ss.JsfLoginUrlAuthenticationEntryPoint" p:loginFormUrl="/login.xhtml"
    p:redirectStrategy-ref="redirectStrategy" />
    
<beans:bean id="redirectStrategy" class="testing.ss.JsfRedirectStrategy" />

And that's all.

The complete source code on github.

01 November 2014

How easy it is to create a multi module maven project

It is very easy.. no complexity presented here ..

The multi module project is folder with a parent pom file and some sub modules, each is a maven project reside in the directly of the parent project (also can reside in any relative path, not necessary to be in the parent folder).

And the parent project itself is a regular maven project but without src folder and with packaging `pom` instead of  `jar` or `war`...

If you have a shared dependency, as if you work with spring framework, you can put the shared dependencies in the parent pom. and in sub modules pom you can put unique dependencies and also can have one module depend on others (web app module to depend on domain module and repository module)

The following is directory structure using parent module with two sub modules (quick-start and webapp)

pom.xml
my-model-app
|____.classpath
|____.project
|____.settings
| |____org.eclipse.jdt.core.prefs
| |____org.eclipse.m2e.core.prefs
| |____org.eclipse.wst.common.component
| |____org.eclipse.wst.common.project.facet.core.xml
|____pom.xml
|____src
| |____main
| | |____java
| | | |____com
| | | | |____me
| | | | | |____model
| | | | | | |____App.java
| |____test
| | |____java
| | | |____com
| | | | |____me
| | | | | |____AppTest.java
my-web-app
|____.classpath
|____.DS_Store
|____.project
|____.settings
| |____.jsdtscope
| |____org.eclipse.jdt.core.prefs
| |____org.eclipse.m2e.core.prefs
| |____org.eclipse.wst.common.component
| |____org.eclipse.wst.common.project.facet.core.xml
| |____org.eclipse.wst.jsdt.ui.superType.container
| |____org.eclipse.wst.jsdt.ui.superType.name
| |____org.eclipse.wst.validation.prefs
|____pom.xml
|____src
| |____.DS_Store
| |____main
| | |____java
| | |____resources
| | |____webapp
| | | |____index.jsp
| | | |____WEB-INF
| | | | |____web.xml


Note, the .classpath and other eclipse files are added because I've imported the project in eclipse.

Now it is very easy, go ahead and create your multi module maven project.

22 October 2014

About Batabase Transactions

DB Transactions has 4 attributes, which is expressed as ACID, where:

A -> Atomicity, means transaction run as an atomic single unit of work, either all is successes and committed or all rollbacked in case of failure.

C -> Consistency, means the transactions should leave the DB data in consistent state, regardless of its success or fail. so, this attribute is ensured using the first attribute.

I -> Isolation, means the user transaction should run in isolation from other users transaction, and no one should affected by others during the single transaction. also this ensures DB consistency.

D -> Durable, means the transaction should be written permanent to the DB after the transaction committed, even if the system crashes afterwards.

When two ore more transactions are operate concurrently on the same data, the following errors might happen:
  1. The first transaction write some data to the DB but still the transaction not committed, a second transaction come and read the modified data, then the first transaction rolled-back.
    This called "Dirty reads", and can prevented by applying the "Isolation" attribute, so every transaction should be isolated from other transactions in terms on data modifications.

  2. The first transaction read some data, then a second transaction come and modify that data and then commit, so the data written to the database. meanwhile the first transaction is still running and when come to read the same data again, it find it changed.
    This called "Non repeatable reads" which means multiple reads by some transaction to the same data is differ. and this can prevented by having some row-level locks on the database, so once a transaction start reading/modifying some data no other transaction cannot use until this transaction ends.

  3. The first transaction read some rows using a certain where condition, then a second transaction come and insert a new row that reside in the where condition area and then committed. When the first transaction come and re-query the first select with that certain where condition, it finds the rows number changed.
    This called "Phantom reads" and this cab be prevented by applying table-level lock whenever a transaction come and start reading/modifying some data in a table, the transaction acquire full-table lock.
This leads to talk about Isolation levels, which are (from less control to more control, and more control means low performance):
  • Read Uncommitted
    Read dirty data, data before being committed by other transactions, leads to all there "Dirty reads", "Non repeatable reads" and "Phantom reads"
  • Read Committed
    Read only committed data, lead to only "Non repeatable reads" and "phantom reads".
  • Repeatable Read (lock data)
    Transaction acquire lock on the data being read (either cell-level or row-level locks), so nobody can change the data until transaction commit or rollback. but still "Phantom reads" can happen.
  • Serializable (lock table)
    Table-level lock. Nobody can touch the whole table until the transaction committed or rolled-back. no isolation violations can happen.

Read more here:
http://en.wikipedia.org/wiki/ACID 
http://en.wikipedia.org/wiki/Isolation_(database_systems)


Source (with my modifications) Spring in action 3rd ed. ch 06



21 October 2014

Indirect login to Target System

The following is a sequence diagram for direct/indirect login to a Target system using user's credentials os Main System.


18 October 2014

shortly.pw is an open source URL shorten, unshorten and tracker

I'd like to talk about shortly.pw which is an website to allow you not just to shorten your URLs, also to unshorten the URL for any shorten services and a URL click tracker.

Feature (see screenshots below):

  • Easily copy the result link.
  • Track the shorten link in terms of time of clicks and details about each click.
  • Unshorten URLs from other services such as goo.gl, tiny url, etc..
  • API available to use the service from your app (mobile, desktop, website, etc...)
  • you get all the other features with no need to login.



Easily copy the result URL:


 Shortly keeps detailed information about links you shorten. (no login required) 
You can unshorten URLs from any other service (bit.ly, tiny url, goo.gl, etc..)

Also you can use the HTTP API from your application, see: http://api.shortly.pw/apidoc

New features are being added..
Shortly plan: https://trello.com/b/or9dg3Zr/shortly-pw-plan
Shortly source code at Github: https://github.com/MuhammadHewedy/short-url

27 September 2014

Ifelse shortcut

if (testCondition() && executeMe() || executeMeOtherwise());

Origin come from bash, to execute if else on a single line:
[ $# == 0 ]  && echo 'invalid input' || processInput($*)
If no parameters passed, the echo 'Invalid input' else, start processing the input.