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.

Thursday, June 5, 2008

Telephone Idiots

To my dyin' day, i will never understands the imbeciles that ring a phone
and let it ring for twenty times. What do they expect? That I'm busy the first
nineteen rings and then, decide differently and pick it up?

Extra points for the morons that do this on office phones in a shared office.
Extra points and a pie for the jerk practicing this on my flat-share's phone
in the night.

But the mother of all phone crapheads must be piece of rotten flesh [see Book of Job, 7,5], that is just right now doin' this in the office behind me in a five minute rhythm. THE GUY IS JUST NOT THERE! HE WON'T PICK UP!

Communication rage.

Monday, June 2, 2008

Spring Security Javadoc generation

For whatever reason, there is no javadoc with the current Spring Security.
Here's how to generate it. Mainly for me to remember.

jar xvf spring-security-acl-2.0.1-sources.jar
jar xvf spring-security-cas-client-2.0.1-sources.jar
jar xvf spring-security-catalina-2.0.1-sources.jar
jar xvf spring-security-core-2.0.1-sources.jar
jar xvf spring-security-core-tiger-2.0.1-sources.jar
jar xvf spring-security-jboss-2.0.1-sources.jar
jar xvf spring-security-jetty-2.0.1-sources.jar
jar xvf spring-security-ntlm-2.0.1-sources.jar
jar xvf spring-security-openid-2.0.1-sources.jar
jar xvf spring-security-portlet-2.0.1-sources.jar
jar xvf spring-security-resin-2.0.1-sources.jar
jar xvf spring-security-samples-contacts-2.0.1-sources.jar
jar xvf spring-security-samples-tutorial-2.0.1-sources.jar
jar xvf spring-security-taglibs-2.0.1-sources.jar

javadoc -sourcepath . -subpackages org -d docs
cd docs
jar cf spring-security-javadoc.jar .