Monday, October 26, 2009

CXF, WSS4J & Spring Security Recipe


How to use Spring Security to authenticate a user/password web service implemented with CXF using WSS4J (Apache Java WS-Security):

In the Spring Application context, we define the namespaces, import CXF's xml and define the "Interceptor" to deal with security:
<?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:p="http://www.springframework.org/schema/p"
    xmlns:cxf="http://cxf.apache.org/core"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:jaxws="http://cxf.apache.org/jaxws"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
        http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
        http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd"
    >

    <!-- Load CXF modules from cxf.jar -->
    <import resource="classpath:META-INF/cxf/cxf.xml" />
    <import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

    <bean id="WSS4JInInterceptor" class="org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor">
     <property name="properties">
      <map>
          <entry key="action" value="UsernameToken Timestamp"/>
          <entry key="passwordType" value="PasswordDigest"/>
          <entry key="passwordCallbackRef">
           <bean class="my.company.SecurityInPasswordHandler"/>
          </entry>
      </map>
     </property>
   </bean>
</beans>

And then we add the interceptor to the webservice:
<jaxws:endpoint id="salaWebService" implementor="#salaService" address="/salas">
    <jaxws:inInterceptors>
        <ref bean="WSS4JInInterceptor"/>
    </jaxws:inInterceptors>
</jaxws:endpoint>

Assuming we have the following service:
@WebService
@SOAPBinding
public interface SalaService {
    @WebResult(name = "sala")
    public abstract Sala get(@WebParam(name = "id") Long id);
}

@Service("salaService")
@WebService(serviceName = "SalaService", portName = "SalaPort", endpointInterface = "my.company.service.SalaService")
public class SalaServiceImpl implements SalaService {
    public Sala get(Long id) {
        return (Sala) executor.execute(SalaBusinessOperations.GET, new Long(id));
    }
}

And CXF configured in web.xml as follows:
<servlet>
    <servlet-name>CXFServlet</servlet-name>
    <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
</servlet>    
<servlet-mapping>
    <servlet-name>CXFServlet</servlet-name>
    <url-pattern>/services/*</url-pattern>
</servlet-mapping>

The spring security should be configured with something like this:
<http >
    <intercept-url pattern="/services/**" access="ROLE_ANONYMOUS" />
    <intercept-url pattern="/**" access="ROLE_USER" />
    <logout/>
    <anonymous/>
</http>

Finally we could write the interceptor class:
public class SecurityInPasswordHandler implements CallbackHandler {
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private UserDetailsService userService;

    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException, AuthenticationException {

        WSPasswordCallback pwdCallback = (WSPasswordCallback) callbacks[0];

        int usage = pwdCallback.getUsage();
        if ((usage == WSPasswordCallback.USERNAME_TOKEN) || (usage == WSPasswordCallback.USERNAME_TOKEN_UNKNOWN)) {
            String password = pwdCallback.getPassword();
            if (usage == WSPasswordCallback.USERNAME_TOKEN) {
                UserDetails userDetails = userService.loadUserByUsername(pwdCallback.getIdentifier());
                password = userDetails.getPassword();
            }
            Authentication authentication = new UsernamePasswordAuthenticationToken(pwdCallback.getIdentifier(), password);
            authentication = authenticationManager.authenticate(authentication); //throws AuthenticationException
            SecurityContextHolder.getContext().setAuthentication(authentication);
            // Return the password to the caller
            pwdCallback.setPassword(password);
        }
    }
}

Now we could handle plain (PasswordText) or encrypted (PasswordDigest) passwords. In both cases creating a SecurityContext for the request to have the user roles and use them in our Spring Security "@Secured" annotations.

Friday, June 27, 2008

Visualizing the commit history of the Eclipse IDE project



code_swarm - Eclipse (short ver.) from Michael Ogawa on Vimeo.

Friday, February 29, 2008

Spring Integration


The new family member, Spring Integration, allows us to use the famous Enterprise Integration Patterns inside our application, without getting away from the Spring programming model.

With a simple configuration like this one, we could read files from a folder and process them:


<?xml version="1.0" encoding="UTF-8"?>

<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/integration"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration-1.0.xsd">

<message-bus/>
<channel id="fileInputChannel" />
<annotation-driven/>

<context:component-scan base-package="com.habuma.si.example" />

<file-source directory="/Users/wallsc/sucker"
poll-period="1000" channel="fileInputChannel"/>
</beans:beans>
----
package com.habuma.si.example;
import org.apache.log4j.Logger;
import org.springframework.integration.annotation.Handler;
import org.springframework.integration.annotation.MessageEndpoint;

@MessageEndpoint(input = "fileInputChannel")
public class FileSucker {
private static final Logger LOGGER = Logger.getLogger(FileSucker.class);

@Handler
public void suckAFile(String fileContents) {
LOGGER.debug(fileContents);
}
}


But not all ends here. The input messages (the files in the previous example) could be routed to other end points: another file, JMS queues, webservices or any system with adapters.
In the same way, the input messages could come from several sources.

The previous example was kindly copied from Spring Integration: Meet the channel adapters. In the same blog, from Craig Walls we could found more information and example code.

Wednesday, August 01, 2007

Atlassian buys Cenqua


Who knows what could emerge from this union: Atlassian buys Cenqua
With applications like FishEye, Crucible y Clover, the Atlassian product rage in impressive.

Monday, July 16, 2007

Agile documenting using Confluence wiki


Managing a project requirements is no easy task. But where that difficulty lies, in gathering or documenting these requirements? It's two sides of the same coin, and in the end, good managing of both things will define a project success.
There are a lot of methodologies to gather requirements, as many as flavors. Maybe RUP is the most famous for large projects, and Agile variants are for smaller ones. Whatever the chosen methodology is, the available tools for managing requirements plainly suck.
The king of requirement tool, RequisitePro, it's an outdated mix of MsWord and a proprietary application, together with a reporting tool (SODA) in MsWord. Not at all agile. Maybe the new Jazz development will bright things for Rational, but we're at least 2 years away from it. What's left for requirements documentation? Maybe Enterprise Arquitect it's good at it, but still a heavy client.
So, welcome to the web! If he most popular distributed document system nowadays is wikipedia, then why not document a project in a wiki? The first argument against it would be that information in a wiki is very unstructured, but there are some tools that allow to add control to the input forms and data editing. XWiki is such an example, but today I'm going to write about something made with Confluence and a few plugins available for this platform.

Step 1. Create a "Client" document template.
First we will create a template to store the clients data. To keep things simple, we'll just store the name. We will have to go to "Browse Space/Advanced/Templates/Add New Space Template" and add the following code and save it with the name "Client".



| Name: | {page-info:title} |

{report-table}
{content-reporter:spaces=@self|type=page|scope=@self > children}
{text-sort:content:title|order=ascending}
{text-filter:data:FormName|include=Project}
{content-reporter}
{report-column:title=Name}{report-info:content:title|link=true}{report-column}
{report-column:title=Project Leader}{report-info:data:ProjectLeader|link=true}{report-column}
{report-column:title=Start Date}{report-info:data:StartDate|link=true}{report-column}
{report-column:title=End Date}{report-info:data:EndDate|link=true}{report-column}
{report-column:title=Status}{report-info:data:Status|link=true}{report-column}
{report-table}
(+) {add-page:template=Project|live=true}Add project{add-page}

{set-data:FormName|hidden=true}Client{set-data}


In this template we see a table with the document title, a projects report and a link to add a new project. At last, the tag {set-data} from the Scaffolding,
plugin allows us to identify the document with the property "FormName=Client", facilitating the client reports we will want to do.

Step 2. Crate a root document.
After that we need a page somewhere on our wiki, containing the client listing. To make the report we will use the Reporting plugin:



{report-table}
{content-reporter:spaces=@self|type=page|scope=Clients > children}
{text-sort:content:title|order=ascending}
{content-reporter}
{report-column:title=Name}{report-info:content:title|link=true}{report-column}
{report-table}

(+) {add-page:template=Client|live=true}Add client{add-page}


At the end of the page there's the tag {add-page}, to add client type documents with the previously created template:

Step 3. Add a client.


The previous link will show us a "client template" based new document:



After saved it will look like this:



Step 4. Create the "project" template
Analogous, to create a project we will have to create first a template, with title “Project”:

| Name: | {page-info:title} |
| Client: | {report-link:content:parent > content:url}{report-info:key=content:parent}{report-link} |
| JIRA Code | {text-data:JiraCode|content=text|width=100px}{text-data} |
| Project Leader: | {list-data:ProjectLeader|required=true}
{user-options:groups=confluence-users}
{list-data} |
| Team Members: | {list-data:TeamMembers|type=check|multiple=true}
{user-options:confluence-users}
{list-data} |
| Start Date: | {date-data:StartDate|format=dd-MMM-yyyy}today{date-data} |
| End Date: | {date-data:EndDate|format=dd-MMM-yyyy}{date-data} |
| Status: | {list-data:Status}
{list-option}Unstarted{list-option}
{list-option}In progress{list-option}
{list-option}Awaiting approval{list-option}
{list-option}Completed{list-option}
{list-data} |

[Requerements|Requirements]
[Use Cases|UseCases]
[Iterations|Iterations]
[Meeting Minutes|MeetingMinutes]
[Status Reports|StatusReports]

{set-data:FormName|hidden=true}Project{set-data}


This template have the project data, including the project leader, team members, start and end date and status. At the end also we have links to documents that will act as parents to the requirements, iterations and all the rest of the documents our methodology needs.

Step 5. Create a project.
After created the project template we can create project documents, with the link at the end of the client form:



It will ask for the project title, and then the data specified in the template:



After saved it will have the following appearance:



Step 6. The requirements report.
To have a requierements list in each project is left as an excercise, since currently the project template simply contains a link to a generic page called "Requirements": [Requirements|Requirements]. The best option is to use a different space for each project.
But let's continue with the design of the mentioned "Requirements" parent page:

h3.Functional Requirements

{report-table}
{content-reporter:type=page|scope=@self > children}
{text-sort:data:Date|order=ascending}
{text-filter:data:FormName|include=Requirement}
{text-filter:data:Type|include=Functional}
{content-reporter}
{report-column:title=Title}{report-info:content:title|link=true}{report-column}
{report-column:title=State}{report-info:data:State}{report-column}
{report-column:title=Priority}{report-info:data:Priority}{report-column}
{report-column:title=Owner}{report-info:data:Owner}{report-column}
{report-column:title=Added}{report-info:content:creation date}{report-column}
{report-column:title=Added by}{report-info:content:creator}{report-column}
{report-table}

h3.Non Functional Requirements
{report-table}
{content-reporter:type=page|scope=@self > children}
{text-sort:data:Date|order=ascending}
{text-filter:data:FormName|include=Requirement}
{text-filter:data:Type|include=Non Functional}
{content-reporter}
{report-column:title=Title}{report-info:content:title|link=true}{report-column}
{report-column:title=State}{report-info:data:State}{report-column}
{report-column:title=Priority}{report-info:data:Priority}{report-column}
{report-column:title=Owner}{report-info:data:Owner}{report-column}
{report-column:title=Added}{report-info:content:creation date}{report-column}
{report-column:title=Added by}{report-info:content:creator}{report-column}
{report-table}

(+) {add-page:template=Requirement|live=true}Add requirement{add-page}


The page has been divided in functional and nonfunctional requirements, but that could be changed to meet our needs. What we need to know is that the page lists the "Requirement" type of document, created in turn from the "Requirement" template:

Step 7. The requirements form:

{section}
{column:width=300px}

*Details*
{table:width=300px}

{table-row}
{table-cell}
Tipo:
{table-cell}
{table-cell}
{list-data:Type|required=true}
{list-option}Functional{list-option}
{list-option}Non Functional{list-option}
{list-data}
{table-cell}
{table-row}
{table-row}
{table-cell:width=100px}
Prioridad:
{table-cell}
{table-cell:width=200px}
{list-data:Priority}
{list-option}Non assigned{list-option}
{list-option}High{list-option}
{list-option}Medium{list-option}
{list-option}Low{list-option}
{list-data}
{table-cell}
{table-row}
{table-row}
{table-cell:width=100px}
State:
{table-cell}
{table-cell:width=200px}
{list-data:State}
{list-option}Proposed{list-option}
{list-option}Rejected{list-option}
{list-option}Approved{list-option}
{list-option}Differed{list-option}
{list-data}
{table-cell}
{table-row}
{table-row}
{table-cell}
Dueño:
{table-cell}
{table-cell}
{list-data:Owner|required=true}{user-options:groups=confluence-users}{list-data}
{table-cell}
{table-row}

{table}

{column}
{column:width=90%}
*Description*
{text-data:Description|type=area|content=wiki|width=100%|height=500px}
{column}

{section}

{set-data:FormName|hidden=true}Requirement{set-data}


The result is the form:



And a report of all the requirements:



Only left to say is that the Graphviz plugin allow us to make diagrams without go out of the wiki (see UML class diagrams in Confluence using Graphviz and DOT), what increases the agility of the documentation by several degrees and allows graphs like this:

Tuesday, July 03, 2007

Exception handling in java


About Exception-Handling Antipatterns
Tim McCune show us in an "old" post (2006) several ways of do the wrong thing with exceptions. Without borrow the post, here are some of my favorite antipatterns:

Log and Throw
(Duplicate entries in the error logs)
catch (NoSuchMethodException e) {
e.printStackTrace();
throw new MyServiceException("Blah", e);
}


Throwing Exception
(Too ambiguous)
public void foo() throws Exception


Catch and Ignore
(Destroys the exception information)
catch (NoSuchMethodException e) {
return null;
}


Destructive Wrapping
(Destroys the original exception)
catch (NoSuchMethodException e) {
throw new MyServiceException("Blah: " +
e.getMessage());
}

Tuesday, May 08, 2007

Semmle, an original idea


Semmle is a tool to make queries to our code similar to SQL. The following query:
from Class c 
where c.declaresMethod("equals")
and not(c.declaresMethod("hashCode"))
select c.getPackage(),c
returns the results:
Photo Sharing and Video Hosting at Photobucket
from the "framework" working space of my eclipse workspace (All classes that define an equals method but not hashCode).
".QL", an object-oriented query language, allows us to build our own classes to extend the query capabilities.
With a Metrics Library such as Lack of Cohesion of Methods and Afferent Coupling/Efferent Coupling, I only miss an ant task to add this tool to the continuos integration server.
Now, here's an original idea!