Monday, February 17, 2014

MEAN Flipboard Magazine

Obviously I have not updated this blog for a long time, but if you are interested in the MEAN stack (MongoDB, Express, AngularJS y Node.js) please do not forget to visit this Flipboard magazine.

Thursday, February 24, 2011

Helpful Spring Links


The SpringSource Team Blog continues posting articles about Spring 3.1 and Grean Beans Series (Spring in general). Here is the list:

Green Beans

Putting the Spring in Your Step (and Application)
Getting Started with Spring MVC
Getting Started with Spring in your Service Tier
Getting Started with Maven and Spring
Getting Started with Enterprise Messaging and Spring
Getting Started with Spring Integration

Spring 3.1

Spring 3.1 M1: Introducing @Profile
Unified Property Management
Introducing FeatureSpecification support
MVC Namespace Enhancements and @Configuration
Cache Abstraction

Monday, April 26, 2010

Presenting on Semana Informática 2010


On April 27, my colleague Pedro Molina
and me will give a talk on frameworks and MDD. The talk will be during the Computer Week 2010: Development productivity and flexibility through frameworks and code generation event.

Having helped on many occasions with the development of frameworks for the most diverse institutions, the challenge is knowing how to convey the need for such frameworks, the complexity associated with their development and the productivity gains achieved.

But do not forget a fundamental part of what is intended to achieve with a framework: development flexibility. Is useless for us to standardize how to build applications, and provide very robust infrastructure services (That's a development framework, right?), if after every technology change we have to change the framework.

If after each technology change our framework becomes obsolete, the ability to adapt to the business needs are diminished, up to the point of becoming an obstacle to it. And our goal as software developers is to always be 100% aligned to business, not to act as an obstacle of change.

This is where the benefits of code generation are obvious. From Spring Roo, to model driven development, the way is "meta-programming".

How is it that after more than 30 years of computers, we're still devoting whole days to develop a simple table maintenance screen? How come we have not yet managed to say "HAL: build me a Customer table maintenance"?

I don't have the answer, but I know that 80% of the applications code is repeatable and can be modelled and generated, and we should put more effort into meta-programming and less into maintenances.

And I also know that I would like to spend my time developing the other 20%.

Thursday, April 08, 2010

OpenSAML signature verification


Assuming that a webservice call containing a signed SAML Assertion, how do we verify that signature? CXF provides "interceptors" to add code before and after a call to a webservice.

First we must configure the call (with Spring in this case):
<jaxws:client id="clientWS" serviceClass="es.mycompany.MyService" address="http://localhost:8080/app/services/myservice">    <jaxws:dataBinding>        <ref bean="aegisBean" />    </jaxws:dataBinding>    <jaxws:inInterceptors>        <ref bean="clientWS.InInterceptor" />    </jaxws:inInterceptors></jaxws:client><bean id="clientWS.InInterceptor" class="es.mycompany.MyInterceptor">    <constructor-arg>        <map>            <entry key="action" value="Timestamp Signature"/>            <entry key="passwordCallbackClass" value="es.mycompany.MyPasswordCallback"/>            <entry key="signaturePropFile" value="keystore.properties"/>        </map>    </constructor-arg></bean>

After that, we need to create a "keystore.properties" file:
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlinorg.apache.ws.security.crypto.merlin.keystore.type=jksorg.apache.ws.security.crypto.merlin.keystore.alias=MyAliasorg.apache.ws.security.crypto.merlin.keystore.password=MyPasswordorg.apache.ws.security.crypto.merlin.file=keystore.jks

And finally the class for managing the certificate passwords. This class needs improvements, but it's good as an example:
public class MyPasswordCallback implements CallbackHandler {    private Map passwords = new HashMap();    public STSPasswordCallback() {        passwords.put("MyAlias", "MyPassword");    }    public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {        for (int i = 0; i < pc =" (WSPasswordCallback)" pass =" passwords.get(pc.getIdentifier());">
With everything in place, we only have to code the interceptor, which in turn uses a utilities class:
public class MyInterceptor extends WSS4JInInterceptor {    private String issuer = "http://www.mycompany.com";    public MyInterceptor() {        super();    }    public MyInterceptor(Map properties) {        super(properties);    }        protected void doReceiverAction(int doAction, RequestData reqData) throws WSSecurityException {                // Get SOAP Header        SOAPMessage message = ((org.apache.cxf.binding.soap.SoapMessage) reqData.getMsgContext()).getContent(javax.xml.soap.SOAPMessage.class);        SOAPHeader soapHeader = message.getSOAPHeader();                // Get Assertion XML        XPathUtils xu = new XPathUtils();        Element xmlAssertion = (Element) xu.getValueNode("//saml2:Assertion", soapHeader);                // Unmarshall        Unmarshaller unmarshaller = unmarshallerFactory.getUnmarshaller(xmlAssertion);        Assertion assertion = (Assertion) unmarshaller.unmarshall(xmlAssertion);        // Get Handler properties        String sigPropFile = getString(WSHandlerConstants.SIG_PROP_FILE, reqData.getMsgContext());        String callback = getString(WSHandlerConstants.PW_CALLBACK_CLASS, reqData.getMsgContext());        // Verify        SAMLUtils.verifySignature(assertion, issuer, sigPropFile, callback);        super.doReceiverAction(doAction, reqData);    }    public void handleMessage(SoapMessage message) throws Fault {        super.handleMessage(message);    }}public class SAMLUtils {    public static void verifySignature(Assertion assertion, String issuer, String sigPropFile, String callback) throws WSSecurityException {        X509Credential cred = getX509Credential(sigPropFile, callback);        StaticCredentialResolver credResolver = new StaticCredentialResolver(cred);        KeyInfoCredentialResolver kiResolver = SecurityHelper.buildBasicInlineKeyInfoResolver();        ExplicitKeySignatureTrustEngine trustEngine = new ExplicitKeySignatureTrustEngine(credResolver, kiResolver);        CriteriaSet criteriaSet = new CriteriaSet();        criteriaSet.add(new EntityIDCriteria(issuer));        criteriaSet.add(new UsageCriteria(UsageType.SIGNING));        criteriaSet.add(new MetadataCriteria(IDPSSODescriptor.DEFAULT_ELEMENT_NAME, SAMLConstants.SAML20P_NS));        try {            trustEngine.validate(assertion.getSignature(), criteriaSet);        } catch (SecurityException e) {            throw new WSSecurityException(e.getMessage());        }    }    public static X509Credential getX509Credential(String sigPropFile, String callback) throws WSSecurityException {        PrivateKey privateKey = null;        X509Certificate[] certs = null;        Crypto crypto = crypto = CryptoFactory.getInstance(sigPropFile);        try {            CallbackHandler cbhandler = getPasswordCallBack(callback);            WSPasswordCallback cb = new WSPasswordCallback(crypto.getDefaultX509Alias(), WSPasswordCallback.SIGNATURE);            cbhandler.handle(new Callback[] { cb });            privateKey = crypto.getPrivateKey(crypto.getDefaultX509Alias(), cb.getPassword());            certs = crypto.getCertificates(crypto.getDefaultX509Alias());        } catch (Exception e) {            throw new WSSecurityException(e.getMessage());        }        if (certs.length != 1) {            throw new WSSecurityException("Couldn't get the (" + crypto.getDefaultX509Alias() + ") signature certificate.");        }        X509Credential cred = SecurityHelper.getSimpleCredential(certs[0], privateKey);        return cred;    }    public static CallbackHandler getPasswordCallBack(String callback) throws WSSecurityException {        CallbackHandler cbHandler = null;        try {            Class cbClass = Loader.loadClass(callback);            cbHandler = (CallbackHandler) cbClass.newInstance();        } catch (Exception e) {            throw new WSSecurityException("WSHandler: cannot create instance of password callback: " + callback, e);        }        return cbHandler;    }}
As you can see, all the work is done in the trustEngine.validate(assertion.getSignature(), criteriaSet); line, we only need to reach there with the right data.

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.