The solution I ended up with is based on this answer: https://stackoverflow.com/a/1422202/711031. I use the following FilteredRequest
implementation:
public class LoginDomainCutFilter implements Filter {
public void init(FilterConfig arg0) throws ServletException {
}
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
chain.doFilter(new FilteredRequest(request), response);
}
private static class FilteredRequest extends HttpServletRequestWrapper {
public FilteredRequest(ServletRequest request) {
super((HttpServletRequest) request);
}
public String getParameter(String paramName) {
String value = super.getParameter(paramName);
if ("j_username".equals(paramName)) {
value = cutSuffix(value, "@mail.domain.com");
value = cutSuffix(value, "@domain.com");
}
return value;
}
private String cutSuffix(String value, String suffix) {
if (value.endsWith(suffix)) value = value.substring(0, value.length() - suffix.length());
return value;
}
}
}
In this case we should register our filter at web.xml
before the Spring Security filter:
<filter>
<filter-name>loginDomainCutFilter</filter-name>
<filter-class>org.mydomain.myapp.LoginDomainCutFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>loginDomainCutFilter</filter-name>
<url-pattern>/j_spring_security_check</url-pattern>
</filter-mapping>
<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>
Finishing touch is to change (mail={0})
to (mail={0}@*)
in your LDAP search filter:
<beans:bean id="userSearch" class="org.springframework.security.ldap.search.FilterBasedLdapUserSearch">
<beans:constructor-arg index="0" value="ou=users,ou=myorgunit"/>
<beans:constructor-arg index="1" value="(mail={0}@*)"/>
<beans:constructor-arg index="2" ref="contextSource"/>
<beans:property name="searchSubtree" value="true"/>
</beans:bean>
Please note that side-effect of the solution is that Spring Security username will no longer contain @domain
suffix, so you should add it manually when you need to display the email. You should decide which one is primary, however.
You should also note that the filter doesn't affect usernames that contain another domain suffix, or doesn't have suffix at all. This is done for purpose, and you can add a simple check for that.
Now user could login as user@mail.domain.com
, user@domain.com
or even user
. If you don't like the latter "bonus behaviour", you can also add a check.