(Yet another) PHP Unzip code

Basically it’s just a “merge” of this and this combining the best of both (the second one rely on a system(‘zip’) call which often a standard php hosting doesn’t allow).

 

<?php
    // The unzip script
    // Created by Max at http://www.solvedo.com
    //
    // This script lists all of the .zip files in a directory
    // and allows you to select one to unzip. 
    //
    // To use this script, FTP or paste this script into a folder where you can
    // invoke it remotey (i.e. www.mysite.com/unzip.php"
 
    // TO CUSTOMIZE: Directory where to read and unzip the files
    // N.B. Unzip will be done in the '$workdir/zipfilename.zip.tmp/' folder.
    $workdir = 'tmp/';
	
    // See if there's a file parameter in the URL string
    $file = $_GET['file'];
 
    if (isset($file)) {
		echo "Unzipping " . $file . "
"; $zip = new ZipArchive; $res = $zip->open($workdir.$file); if ($res === TRUE) { if ($zip->extractTo($workdir.$file.'.tmp/')){ echo "Unzip done."; } else { echo "Unzip failed."; } $zip->close(); } else { echo "Failed to open file."; } exit; } // create a handler to read the directory contents $handler = opendir($workdir); echo "Please choose a file to unzip: " . "
"; // A blank action field posts the form to itself echo "
"; $found = FALSE; // Used to see if there were any valid files // keep going until all files in directory have been read while ($file = readdir($handler)) { if (preg_match ('/.zip$/i', $file)) { echo " " . $file . "
"; $found = true; } } closedir($handler); if ($found == FALSE) echo "No files ending in .zip found
"; else echo "
Warning: Existing files will be overwritten.

"; echo "
"; ?>

Spring-Security3 PreAuthentication + JSF2

Spring Security (formerly Acegi Security) is for sure one of the most flexible framework to address security+authentication for a real-life web application. Its pluggable mechanism offers an easy path to achieve security in a large number of contexts.

Recently I decided to use it for a webapp that will be deployed and used by an organization which use a custom SSO strategy.

From the webapp perspective this means that we don’t have to authenticate users, this was already done by the SSO framework. What the webapp need to know is basically who is the user and which role he play in the webapp domain.

The “which” part is essentially a mapping of the organization-wide user grants to the webapp specific (three) roles.

Spring Security offers a rich set of ready-made tools for the “pre-authenticated” scenario (link). Unfortunately I didn’t found any real life example showing how to use these tools. So here comes this article.

First of all the web.xml…

...
<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>classpath*:applicationContext.xml, 
               classpath*:applicationContext-security.xml</param-value>
</context-param>

<filter>
  <filter-name>springSecurityFilterChain</filter-name>
  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
  <filter-name>springSecurityFilterChain</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>
...

Here you have to customize two things:

  • the contextConfigLocation value to meet your configuration setup (in the example above there are two separate files, one for the generic Spring beans configuration, another for the security configuration only)
  • the url-pattern for the filter mapping that need to address your specific security requirement. (in the example all pages will be “secured”)

Now, let’s see the applicationContext-security.xml….

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xmlns:sec="http://www.springframework.org/schema/security"
  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
    http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">

<!-- <sec:debug/> --> <!-- Uncomment this to have verbose debug informations -->

  <sec:http realm="My Realm" auto-config='true' create-session="ifRequired" disable-url-rewriting="true">
    <sec:intercept-url pattern="/**" access="ROLE_USER"/>    
    <sec:custom-filter ref="myPreAuthFilter" position="PRE_AUTH_FILTER"/>    
    <sec:session-management session-fixation-protection="newSession"/>
  </sec:http>

  <sec:authentication-manager alias="authenticationManager">
    <sec:authentication-provider ref='preAuthenticatedAuthenticationProvider'/>
  </sec:authentication-manager>

  <bean id="myPreAuthFilter" class="mypackage.MyPreAuthenticatedProcessingFilter">
    <property name="authenticationManager" ref="authenticationManager"/>
    <property name="authenticationDetailsSource" ref="authenticationDetailsSource"/>
    <property name="continueFilterChainOnUnsuccessfulAuthentication" value="false"/>
  </bean>

  <bean id="authenticationDetailsSource" class="mypackage.MyAuthenticationDetailsSource" />

  <bean id="authenticationManager" class="org.springframework.security.authentication.ProviderManager">
    <constructor-arg>
      <list>
        <ref bean="preAuthenticatedAuthenticationProvider"/>
      </list>
    </constructor-arg>
  </bean>

  <bean id="preAuthenticatedAuthenticationProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
    <property name="preAuthenticatedUserDetailsService" ref="preAuthenticatedUserDetailsService"/>
  </bean>
  <bean id="preAuthenticatedUserDetailsService" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedGrantedAuthoritiesUserDetailsService"/>
</beans>

Let’s see the most important things …

  • the sec:http part configure the relevant things in our secure  realm, inside this we are saying that
  • we want to intercept access to every page, including sub-folders (/**), and make them accessible to users with role “ROLE_USER” (which in our scenario means to every SSO authenticated user) and
  • we want to place our pre-authenticated filter in the Spring-Security filters-chain in the appropriate position (more here)

The rest of the file says that we want to use a certain authenticationManager, a custom authenticationFilter and a custom authenticationDetailSource.

The easier way to understand what those filter and detail source do it’s to look to their source:

public class MyPreAuthenticatedProcessingFilter extends AbstractPreAuthenticatedProcessingFilter{

  @Override
  protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
    MyUser user = null;
      try {       
        // Here you have to extract the user from the request.
        // This is SSO framework dependant.
        user = customMethodToGetTheUserFromTheRequest(request);
      } catch (MyException e) {
        throw new AuthenticationServiceException("Error....", e);
      }

    return user; //User must implement java.security.Principal
  }

  @Override
  protected Object getPreAuthenticatedCredentials(HttpServletRequest request) {
    //Normally this should return the password or any other credential
    return "N/A";
  }
}
public class MyAuthenticationDetailsSource implements AuthenticationDetailsSource {

	@Override
	public GrantedAuthoritiesContainer buildDetails(HttpServletRequest request) {
		MyUser user = customMethodToGetTheUserFromTheRequest(request);

		List gal = new ArrayList();
		try{
			GrantedAuthority ga = null;
			if (user.isMemeberOfTheOrganization()){
				ga = new SimpleGrantedAuthority(Roles.ROLE_USER);
				gal.add(ga);
			}
			if (user.isMemberOfTheATeam()){
				ga = new SimpleGrantedAuthority(Roles.ROLE_MASTER);
				gal.add(ga);
			}
			if (user.isMemberOfTheBTeam()){
				ga = new SimpleGrantedAuthority(Roles.ROLE_ADMIN);
				gal.add(ga);
			}
		} catch (MyException e) {
			throw new AuthenticationServiceException("Error..", e);
		}

		return new PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails(request, gal);
	}
}

The two classes are almost self-explicative. The first one retrieve/build the webapp user reading the SSO data from the request.
The second maps the organizational user roles to the webapp user roles.

That’s all 🙂