Wiki

Clone wiki

BibSonomy / development / modules / webapp / Spring Security

Overview

NOTE: outdated, TODO: please add a documentation for Shibboleth

The following classes are currently involved in user authentication:

  • org.bibsonomy.webapp.controller.actions.UserLoginController
  • org.bibsonomy.webapp.controller.actions.PasswordReminderController
  • org.bibsonomy.webapp.controller.actions.PasswordChangeOnRemindController
  • org.bibsonomy.webapp.controller.actions.ChangePasswordController
  • org.bibsonomy.webapp.util.RequestWrapperContext
  • org.bibsonomy.webapp.controller.actions.DeleteUserController

(all can be found in the webapp module)

Config-File

spring security

 <bean:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:bean="http://www.springframework.org/schema/beans"
    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-3.0.xsd
                        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">

  <http>
    <!-- no filtering for css and js -->
    <intercept-url pattern="/resources/**" filter="none" />
    <!-- api uses own authentication handling -->
    <intercept-url pattern="/api/**" filter="none" />
    <!-- login -->
    <intercept-url pattern="/login" access="IS_AUTHENTICATED_ANONYMOUSLY" />
    <!-- restrict admin pages to admins -->
    <intercept-url pattern="/admin/**" access="ROLE_ADMIN" />
    <!-- everything else -->
    <intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />

    <remember-me key="CURRENT_USER" token-validity-seconds="3600" /> TODO: ?!?

    <http-basic /> TODO
    <logout invalidate-session="true" logout-success-url="/" logout-url="/logout" />
    <form-login login-page="/login" />

    <session-management>
      <!-- only one session; if logged in user logs in a second time the first session becomes invalid -->
      <concurrency-control max-sessions="1" /> <!-- web.xml add listener HttpSessionEventPublischer TODO: or with error error-if-maximum-exceeded="true" and 
      <session-authentication-error-url />-->
    </session-management>
  </http>

  <authentication-manager>
    <authentication-provider user-service-ref="authenticationProvider">
      <password-encoder hash="md5"/>
    </authentication-provider>
  </authentication-manager>

  <bean:bean id="authenticationProvider" class="org.bibsonomy.webapp.util.spring.security.UserDetailsProvider">
    <custom-authentication-provider />
    <bean:property name="adminLogic" ref="adminLogic" />
  </bean:bean>

web.xml

  <listener>
    <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
  </listener>
  <filter>
    <filter-name>springSecurityFilterChain</filter-name> 
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <!-- so sollte Spring security im bibsonomy2-servlet context laufen -->
     <init-param>
    <param-name>contextAttribute</param-name>
    <param-value>org.springframework.web.servlet.FrameworkServlet.CONTEXT.bibsonomy2</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name> 
    <url-pattern>/*</url-pattern>
  </filter-mapping>

Please not the init parameter of the DelegatingFilterProxy which moves the Spring Security context into the webapp context.

Spring Security

Filter Overview

The DelegatingFilterProxy loads/delegates to the FilterChainProxy. This proxy knows which filter are responsible for which path. Currently the following filters are registrated:

Authentication

Spring Security needs infos about our users (z.B. passwort, salt from the database, …). You can implement own UserDetailsServices. They return UserDetails objects. An adapter for our user model was written.

methods used

internal (database)

implemented a UserDetailsService

responsible filter: UsernamePasswordAuthenticationFilter

Open ID

pom.xml

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-openid</artifactId>
    <version>${spring-security.version}</version>
</dependency>

responsible filter: OpenIDAuthenticationFilter

LDAP

pom.xml

<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-ldap</artifactId>
    <version>${spring-security.version}</version>
</dependency>

see openID and

<ldap-authentication-provider server-ref="ldap://localhost:10389/"/>

responsible filter: UsernamePasswordAuthenticationFilter

setup test ldap server

Spring Security provides a simple ldap server for testing (see 1)

add the following to the XML configuration

<security:ldap-server port="33389" ldif="classpath:users.ldif" />

Don't forget to delete the other ldapserver from the config!

add the following dependencies to the pom:

<!-- LDAP test server -->
        <dependency>
            <groupId>org.apache.directory.server</groupId>
            <artifactId>apacheds-core</artifactId>
            <version>1.5.5</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.apache.directory.server</groupId>
            <artifactId>apacheds-server-jndi</artifactId>
            <version>1.5.5</version>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.6.0</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>1.6.0</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.6.0</version>
            <scope>runtime</scope>
        </dependency>

Add a .ldif file to the classpath with the user data:

Test sample
dn: ou=pica-users,dc=ub,dc=organization,dc=de
objectclass: top
objectclass: organizationalUnit
ou: pica-users

dn: uid=111111111,ou=pica-users,dc=ub,dc=uni-kassel,dc=de
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: top
cn: John Doe
givenName: John
uid: 111111111
sn: Doe
ou: BB 5
employeeNumber: 999999
employeeType: 30
mail: john@doe.com
l: Doe
postalCode: 34121
street:: abcdef
st: DUMMY
carLicense: 0
preferredLanguage: DE
userPassword: test

Shibboleth

http://shibboleth.internet2.edu/

TODO: document

HTTP-Basic

TODO: document responsible filter: BasicAuthenticationFilter zuständig.

available methods by Spring Security (and extensions)

OAuth

OAuth Guide

Version 1: yes

Version 2: yes/no (currently in development)

Spring Security OAuth Projekt

X.509

http://static.springsource.org/spring-security/site/docs/3.0.x/reference/x509.html

autocreate of users

InitUserFilter creates a new user if he did't exist before. :(

background: some actions in BibSonomy need a corresponding user in the "user" table gibt (z.B. settings, joining groups, etc.)

responsible filter: http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/web/authentication/preauth/x509/X509AuthenticationFilter.html

more

implementations

SecurityContextRepository

Because we do not want to save the complete Security context (containing all user details) in the HTTP session, we wrote a special implementation of the SecurtyContextRepository to only save the user name of the currently loggedin user. Configured as follows:

  <security:http (...) security-context-repository-ref="contextRepository">(...)
   <bean id="contextRepository" class="org.bibsonomy.webapp.util.spring.security.UsernameSecurityContextRepository">
    <property name="service" ref="databaseUserService" />
   </bean>

implementation: org.bibsonomy.webapp.util.spring.security.UsernameSecurityContextRepository

and the corresponding logout handler

  <bean id="securityContextLogoutHandler" class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" />

Brute Force Attacks

no implementation to prevent brute force attacks in Spring Security

wrote class that extends UsernamePasswordAuthenticationFilter and uses our Teergrube implementation users and ips are added by a special AuthenticationFailureHandler implementieren

Internal

RememberMeServices Internal

Spring security provides a RememberMeService for this remember me function: TokenBasedRememberMeServices

This RememberMeService saves the username, expiration date and a signature (configurable key + username + hashed password). If no user is loggedin, this services logs in the user of the cookie.

Open ID

UserDetailsService

Implemented a special user details service: org.bibsonomy.webapp.util.spring.security.userdetailsservice.OpenIDDatabaseUserDetailsService

Attribute Exchange:

  • mail address
  • nickname
  • language
  • name
  • gender
  • country

RememberMeServices OpenID

This implementation uses a cookie to identify the openid user. If the session expired the user is redirected to the OpenID provider (redirects back to the "normal" OpenID filter).

Implementierung: org.bibsonomy.webapp.util.spring.security.rememberMeServices.OpenIDRememberMeService

LDAP

RememberMeServices LDAP

The rememberme service uses a cookie containing the username and the clear password of the user (else we need admin privileges on the LDAP server). The Cookie is encrypted with a private key algorithm.

Configuration

TODO: update The following values are configurable:

  • active auth methods (internal, openid, basic, ldap, …) + RememberMe services
  • LDAP
  • Server
  • UserDN
  • Search
  • private key for crypting cookie

sources + tutorials

http://static.springsource.org/spring-security/site/docs/3.0.x/reference/springsecurity.html

auto create user

Google App Engine

Updated