Wednesday, July 30, 2008

The peach window

The peach window is the time interval where the peaches you bought are in an edible state. That is, the time between rock hard causing gum bleeding and moldy,
covered with fruit flies.

While the time before the window takes up to a week (and after as long a you can stand the flies), the peach window seems to be sized 12 hours in average.

Unfortunately, here they come packed at least by eight, and worse I seem always to get them in a synchronized set. So once a week, it's peach diet. Lucky me.

Wednesday, July 16, 2008

The longest classnames in spring security

If you ever wondered, how long a classname can become, have a look at spring security.

Here are the top-five of the longest ones (excluding package-name):

Sharing the second place, there are:

BasicAclEntryAfterInvocationCollectionFilteringProvider
J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource
PreAuthenticatedGrantedAuthoritiesAuthenticationDetails
WebSpherePreAuthenticatedWebAuthenticationDetailsSource


This almost look like a PGP key block.
Excited, who the winner is *gasp*? Here we go.

PreAuthenticatedGrantedAuthoritiesWebAuthenticationDetails

HemingwayWroteStoriesShorterThanThat.

Wednesday, July 9, 2008

Eclipse Ganymede branding - Getting your launcher icon right

Still, eclipse is picky when you're not explicit on your branding.
When providing icons for your windows application one by one (i.e. not with a combined .ico but single bitmaps) it is mandatory to specify a file for each
of the six sizes/depths.
Looks like win xp is looking for a 32-bit icon, so the "fault" is not on eclipse's side. Of course, it's on mine.

Iconomaker is capable of creating 32-bit bitmaps, but it is shareware.
Haven't tried gimp yet, but i suppose it can do so as well.

[update]
Yeah, gimp can do. Eclipse is just overwriting the icons from the original launcher.
If you drag your launcher in irfanview you will see a multipage icon (7 pages) you can
scroll through. I only wonder where i can specify the seventh icon, since the branding wizard only allows for six?

Friday, June 27, 2008

My ganymede icon

So eclipse ganymede is finally out. Good news, although some plugins still have to be updated to work with
it. If you don't have the JEE package, don't try to install the Spring IDE Mylyn Integration, look for installation instructions here.)
The Mantis-mylyn integration is not yet ready for 3.4, so you have to use the dev version to make it work, the update-site URL is http://mylyn-mantis.sourceforge.net/eclipse/dev/update/site.xml

Unfortunately, Eclipse did not provide a new icon for ganymede but having seven zillions different versions on my desktop, I need some visual distinction. Fortunately, irfanview can extract icons from exe's, so look at this masterpiece.
Bow, Picasso!


Tuesday, June 17, 2008

Spring Security + Spring Remoting + Digest Authentication Part 2

Now for the server configuration. I will spare out the setup of a web application, since you will know that yourself.

First, the SecurityService and its implementation:

public interface SecurityService {
public String[] getRoles();
}



import org.springframework.security.GrantedAuthority;
import org.springframework.security.context.SecurityContextHolder;

public class SecurityServiceImpl implements SecurityService {
public String[] getRoles() {
GrantedAuthority[] gas = SecurityContextHolder.getContext().getAuthentication().getAuthorities();
String[] roles = new String[gas.length];
for (int i=0;i<gas.length; i++) {
roles[i] = gas[i].getAuthority();
}
return roles;
}
}


Not that complicated.
This is the web.xml, which looks rather straightforward:

<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
<display-name>web-deployed service layer</display-name>

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext-service.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>

<servlet>
<servlet-name>context</servlet-name>
<servlet-class>
org.springframework.web.context.ContextLoaderServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>remote</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>remote</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>


</web-app>



Following the convention, there is a [minimal] remote-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>

<bean name="/securityService"
class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
<property name="serviceInterface" value="de.yyy.xxx.SecurityService" />
<property name="service" ref="securityService" />
</bean>

</beans>



and finally, the biggest artifact, the server's application context.

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


<bean id="securityService" class="de.yyy.xxx.SecurityServiceImpl">
<security:intercept-methods>
<security:protect
method="de.yyy.xxx.SecurityServiceImpl.getRoles" access="ROLE_USER" />
</security:intercept-methods>
</bean>

<security:authentication-manager alias="authenticationManager" />

<bean id="digestProcessingFilter"
class="org.springframework.security.ui.digestauth.DigestProcessingFilter">
<property name="userDetailsService" ref="uds" />
<property name="authenticationEntryPoint"
ref="digestProcessingFilterEntryPoint" />
</bean>

<bean id="digestProcessingFilterEntryPoint"
class="org.springframework.security.ui.digestauth.DigestProcessingFilterEntryPoint">
<property name="realmName" value="ThisIsTheDigestRealm" />
<property name="key" value="acegi" />
<property name="nonceValiditySeconds" value="10" />
</bean>

<bean id="springSecurityFilterChain"
class="org.springframework.security.util.FilterChainProxy">
<security:filter-chain-map path-type="ant">
<security:filter-chain pattern="/**"
filters="httpSessionContextIntegrationFilter,digestProcessingFilter,exceptionTranslationFilter,filterSecurityInterceptor" />
</security:filter-chain-map>
</bean>

<bean id="httpSessionContextIntegrationFilter"
class="org.springframework.security.context.HttpSessionContextIntegrationFilter" />

<bean id="filterSecurityInterceptor"
class="org.springframework.security.intercept.web.FilterSecurityInterceptor">
<property name="authenticationManager"
ref="authenticationManager" />
<property name="accessDecisionManager"
ref="accessDecisionManager" />
<property name="objectDefinitionSource">
<security:filter-invocation-definition-source>
<security:intercept-url pattern="/**"
access="ROLE_USER" />
</security:filter-invocation-definition-source>
</property>
</bean>

<bean id="accessDecisionManager"
class="org.springframework.security.vote.AffirmativeBased">
<property name="allowIfAllAbstainDecisions" value="false" />
<property name="decisionVoters">
<list>
<bean
class="org.springframework.security.vote.RoleVoter" />
</list>
</property>
</bean>

<bean id="exceptionTranslationFilter"
class="org.springframework.security.ui.ExceptionTranslationFilter">
<property name="authenticationEntryPoint"
ref="digestProcessingFilterEntryPoint" />
</bean>

<security:authentication-provider>
<security:user-service id="uds">
<security:user name="jimi" password="jimi"
authorities="ROLE_USER, ROLE_ADMIN" />
<security:user name="bob" password="bob"
authorities="ROLE_USER" />
</security:user-service>
</security:authentication-provider>
</beans>



That's it. The client requests will be authenticated via the HTTP Digest algorithm,
the corresponding filter will set up a SecurityContext on the server side. When
the client asks for available roles, method security assures that only authorized clients can request them. The getRoles method then just accesses the SecurityContext and copies the rolenames in a String array which is returned.
There are some edges that need more polish, i.e. one could try to take the GrantedAuthority array and put this in a client's SecurityContext. With some more handcoding it should be possible to send the SecurityContext over the wire, but it needs more analysis if this makes sense.

Spring Security + Spring Remoting + Digest Authentication

This was a hard one. Documentation on how to use spring security with a rich client is thin or outdated. Using search engines, you'll have a name clash with the "spring rich client". The name change from Acegi to Spring Security and other things like the sample code not being completely distributed with the sources made it kinda hard for me to figure things out.
Nevertheless, here's what I've come up with:

The task was to integrate spring security with a rich client that uses spring remoting (via httpinvoker) so that the client knows the roles the user has and the server does so as well. I didn't want the client to use HTTPS for performance reasons, nor did i want to transfer the password in clear over the wire (or only marginally scrambled via Base64). I chose digest authentication to be the one.
I must admit that my knowledge on the spring security architecture is very shallow, so my solution is probably not the most elegant one, but it works for me.

I don't use the RemoteAuthentication classes that are provided since I couldn't make them work together with digest authentication.

Before posting the config, how does it work?
The client takes the user credentials, they would be manual input in a real app.
The creds are put into the HttpState so the Commons HttpClient library can do digest auth with the server. The problem is that you have the SecurityContext with the GrantedAuthorities available on the server, but not on the client. For that, I've created a SecurityService that just returns the GrantedAuthorities via remote invocation. That way, the client can (for example) hide or show menus or buttons,
depending on the available roles.

Ok, let's go. This is the main application, of course just a stub to show it works.

public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext( "applicationContext.xml");
String user = "jimi";
String pw = "jimi";
UsernamePasswordCredentials creds = new UsernamePasswordCredentials(user, pw);

HttpState httpState = (HttpState) ctx.getBean("httpState");
httpState.setCredentials(AuthScope.ANY, creds);

//print the available roles
String[] roles = ((SecurityService) ctx.getBean("securityService")).getRoles();
for (int i = 0; i < roles.length; i++) {
System.out.println("Role:" + roles[i]);
}
}


Now, the client's appconfig:


<?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:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd">


<bean id="securityService"
class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
<property name="serviceUrl" value="http://localhost:8999/middletierService/securityService" />
<property name="serviceInterface" value="de.yyy.xxx.SecurityService" />
<property name="httpInvokerRequestExecutor" ref="httpInvokerRequestExecutor"/>
</bean>


<bean id="httpInvokerRequestExecutor"
class="org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor">
<constructor-arg ref="httpClient"/>
</bean>

<bean id="httpClient" class="org.apache.commons.httpclient.HttpClient">
<property name="state" ref="httpState" />
</bean>

<bean id="httpState" class="org.apache.commons.httpclient.HttpState"/>

</beans>


Part 2 will be on the server's configuration.

Monday, June 16, 2008

Authenticate against NT Domain with JCIFS

I just wanted to authenticate a user against an primary domain controller in java.
The tool of choice seems to be JCIFS, so this is the minimal stripped-down example
to do this.


NtlmPasswordAuthentication auth1= new NtlmPasswordAuthentication("yourdomain", "theuser", "thepassword" );
InetAddress address=InetAddress.getByName("the.domain.controller");
UniAddress dc = new UniAddress(address);
SmbSession.logon(dc, auth1);


This will throw an exception when id or password is wrong. Otherwise it just terminates without an error.