remove unused module

git-svn-id: https://svn.apache.org/repos/asf/archiva/redback/redback-core/trunk@1310470 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Olivier Lamy 2012-04-06 16:44:18 +00:00
parent ba7e6d648a
commit ebb3032c69
17 changed files with 0 additions and 1286 deletions

View File

@ -56,7 +56,6 @@
<module>redback-common-integrations</module>
<module>redback-rest</module>
<module>redback-struts2</module>
<module>redback-jee</module>
<module>redback-jsecurity</module>
<module>redback-integrations-security</module>
</modules>

View File

@ -1,34 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Licensed to the Apache Software Foundation (ASF) under one
~ or more contributor license agreements. See the NOTICE file
~ distributed with this work for additional information
~ regarding copyright ownership. The ASF licenses this file
~ to you under the Apache License, Version 2.0 (the
~ "License"); you may not use this file except in compliance
~ with the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.codehaus.redback</groupId>
<artifactId>redback-integrations</artifactId>
<version>1.5-SNAPSHOT</version>
</parent>
<artifactId>redback-jee</artifactId>
<name>Redback :: Integration :: J(2)EE</name>
<packaging>pom</packaging>
<modules>
<module>redback-jee-web-integration</module>
</modules>
</project>

View File

@ -1,54 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Licensed to the Apache Software Foundation (ASF) under one
~ or more contributor license agreements. See the NOTICE file
~ distributed with this work for additional information
~ regarding copyright ownership. The ASF licenses this file
~ to you under the Apache License, Version 2.0 (the
~ "License"); you may not use this file except in compliance
~ with the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.codehaus.redback</groupId>
<artifactId>redback-jee</artifactId>
<version>1.5-SNAPSHOT</version>
</parent>
<artifactId>redback-jee-web-integration</artifactId>
<name>Redback :: Integration :: J(2)EE Web Integration</name>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>jsr250-api</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.codehaus.redback</groupId>
<artifactId>redback-system</artifactId>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -1,80 +0,0 @@
package org.codehaus.plexus.redback.http;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.util.Properties;
import org.codehaus.plexus.util.StringUtils;
/**
* Collection of Utility methods useful in an Http environment.
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
* @todo should move this to plexus-utils or plexus-utils-web
*/
public class HttpUtils
{
/**
* Convert typical complex header into properties.
* <p/>
* <p/>
* Example:
* </p>
* <p/>
* <code>
* realm="Somewhere Over The Rainbow", domain="kansas.co.us", nonce="65743ABCF"
* </code>
* <p/>
* <p>becomes</p>
* <p/>
* <code>
* Map ( "realm", "Somewhere Over The Rainbox" )
* Map ( "domain", "kansas.co.us" )
* Map ( "nonce", "65743ABCF" )
* </code>
*
* @param rawheader
* @param majorDelim
* @param subDelim
* @return
*/
public static Properties complexHeaderToProperties( String rawheader, String majorDelim, String subDelim )
{
Properties ret = new Properties();
if ( StringUtils.isEmpty( rawheader ) )
{
return ret;
}
String array[] = StringUtils.split( rawheader, majorDelim );
for ( int i = 0; i < array.length; i++ )
{
// String quotes.
String rawelem = StringUtils.replace( array[i], "\"", "" );
String parts[] = StringUtils.split( rawelem, subDelim, 2 );
ret.setProperty( StringUtils.trim( parts[0] ), StringUtils.trim( parts[1] ) );
}
return ret;
}
}

View File

@ -1,155 +0,0 @@
package org.codehaus.plexus.redback.http.authentication;
import org.codehaus.plexus.redback.authentication.AuthenticationDataSource;
import org.codehaus.plexus.redback.authentication.AuthenticationException;
import org.codehaus.plexus.redback.authentication.AuthenticationResult;
import org.codehaus.plexus.redback.policy.AccountLockedException;
import org.codehaus.plexus.redback.policy.MustChangePasswordException;
import org.codehaus.plexus.redback.system.SecuritySession;
import org.codehaus.plexus.redback.system.SecuritySystem;
import org.codehaus.plexus.redback.users.User;
import org.codehaus.plexus.redback.users.UserNotFoundException;
import org.codehaus.plexus.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* HttpAuthenticator is the workings of an authenticator for http with the session storage abstracted
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @author Andrew Williams
* @version $Id$
*/
public abstract class AbstractHttpAuthenticator
implements HttpAuthenticator
{
protected Logger log = LoggerFactory.getLogger( getClass() );
@Inject
protected SecuritySystem securitySystem;
/**
* The Public Face of the Authenticator.
*
* @throws org.codehaus.plexus.redback.policy.MustChangePasswordException
*
* @throws org.codehaus.plexus.redback.policy.AccountLockedException
*
*/
protected AuthenticationResult authenticate( AuthenticationDataSource ds, Object session )
throws AuthenticationException, AccountLockedException, MustChangePasswordException
{
try
{
SecuritySession securitySession = securitySystem.authenticate( ds );
setSecuritySession( securitySession, session );
return securitySession.getAuthenticationResult();
}
catch ( AuthenticationException e )
{
String msg = "Unable to authenticate user: " + ds;
log.info( msg, e );
throw new HttpAuthenticationException( msg, e );
}
catch ( UserNotFoundException e )
{
log.info( "Login attempt against unknown user: {}", ds );
throw new HttpAuthenticationException( "User name or password invalid.", e );
}
}
/**
* Entry point for a Filter.
*
* @param request
* @param response
* @throws org.codehaus.plexus.redback.authentication.AuthenticationException
*
*/
public void authenticate( HttpServletRequest request, HttpServletResponse response )
throws AuthenticationException
{
try
{
AuthenticationResult result = getAuthenticationResult( request, response );
if ( ( result == null ) || ( !result.isAuthenticated() ) )
{
throw new HttpAuthenticationException( "You are not authenticated." );
}
}
catch ( AccountLockedException e )
{
throw new HttpAuthenticationException( "Your account is locked." );
}
catch ( MustChangePasswordException e )
{
throw new HttpAuthenticationException( "You must change your password." );
}
}
protected abstract Object getSessionValue( Object session, String key );
protected abstract void setSessionValue( Object session, String key, Object value );
protected User getSessionUser( Object session )
{
return (User) getSessionValue( session, SecuritySession.USERKEY );
}
protected boolean isAlreadyAuthenticated( Object session )
{
User user = getSessionUser( session );
return ( ( user != null ) && !user.isLocked() );
}
protected SecuritySession getSecuritySession( Object session )
{
return (SecuritySession) getSessionValue( session, SecuritySession.SESSION_KEY );
}
protected void setSecuritySession( SecuritySession session, Object sessionObj )
{
setSessionValue( sessionObj, SecuritySession.SESSION_KEY, session );
setSessionValue( sessionObj, SecuritySession.USERKEY, session.getUser() );
}
protected void setSessionUser( User user, Object session )
{
setSessionValue( session, SecuritySession.SESSION_KEY, null );
setSessionValue( session, SecuritySession.USERKEY, user );
}
protected String storeDefaultUser( String principal, Object session )
{
setSessionValue( session, SecuritySession.SESSION_KEY, null );
setSessionValue( session, SecuritySession.USERKEY, null );
if ( StringUtils.isEmpty( principal ) )
{
return null;
}
try
{
User user = securitySystem.getUserManager().findUser( principal );
setSessionValue( session, SecuritySession.USERKEY, user );
return user.getPrincipal().toString();
}
catch ( UserNotFoundException e )
{
log.warn( "Default User '" + principal + "' not found.", e );
return null;
}
}
}

View File

@ -1,35 +0,0 @@
package org.codehaus.plexus.redback.http.authentication;
import org.codehaus.plexus.redback.authentication.AuthenticationException;
/**
* HttpAuthenticationException
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*/
public class HttpAuthenticationException
extends AuthenticationException
{
public HttpAuthenticationException()
{
super();
}
public HttpAuthenticationException( String message, Throwable cause )
{
super( message, cause );
}
public HttpAuthenticationException( String message )
{
super( message );
}
public HttpAuthenticationException( Throwable cause )
{
super( cause );
}
}

View File

@ -1,58 +0,0 @@
package org.codehaus.plexus.redback.http.authentication;
import org.codehaus.plexus.redback.authentication.AuthenticationException;
import org.codehaus.plexus.redback.authentication.AuthenticationResult;
import org.codehaus.plexus.redback.policy.AccountLockedException;
import org.codehaus.plexus.redback.policy.MustChangePasswordException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* HttpAuthenticator
*
* @author Andrew Williams
* @version $Id$
*/
public interface HttpAuthenticator
{
/**
* Entry point for a Filter.
*
* @param request
* @param response
* @throws AuthenticationException
*/
void authenticate( HttpServletRequest request, HttpServletResponse response )
throws AuthenticationException;
/**
* Issue a Challenge Response back to the HTTP Client.
*
* @param request
* @param response
* @param realmName
* @param exception
* @throws java.io.IOException
*/
void challenge( HttpServletRequest request, HttpServletResponse response, String realmName,
AuthenticationException exception )
throws IOException;
/**
* Parse the incoming request and return an AuthenticationResult.
*
* @param request
* @param response
* @return null if no http auth credentials, or the actual authentication result based on the credentials.
* @throws AuthenticationException
* @throws org.codehaus.plexus.redback.policy.MustChangePasswordException
*
* @throws org.codehaus.plexus.redback.policy.AccountLockedException
*
*/
AuthenticationResult getAuthenticationResult( HttpServletRequest request, HttpServletResponse response )
throws AuthenticationException, AccountLockedException, MustChangePasswordException;
}

View File

@ -1,79 +0,0 @@
package org.codehaus.plexus.redback.http.authentication;
import java.util.Map;
import org.codehaus.plexus.redback.authentication.AuthenticationDataSource;
import org.codehaus.plexus.redback.authentication.AuthenticationException;
import org.codehaus.plexus.redback.authentication.AuthenticationResult;
import org.codehaus.plexus.redback.policy.AccountLockedException;
import org.codehaus.plexus.redback.policy.MustChangePasswordException;
import org.codehaus.plexus.redback.system.SecuritySession;
import org.codehaus.plexus.redback.users.User;
/**
* An HttpAuthenticator using a Map for session storage
*
* @author Andrew Williams
* @version $Id$
* @since 1.0
*/
public abstract class MapBasedHttpAuthenticator
extends AbstractHttpAuthenticator
{
protected Object getSessionValue( Object session, String key )
{
if ( !( session instanceof Map ) )
{
throw new IllegalArgumentException( "The session for a MapBasedAuthenticator must be a java.util.Map" );
}
return ( (Map) session ).get( key );
}
protected void setSessionValue( Object session, String key, Object value )
{
if ( !( session instanceof Map ) )
{
throw new IllegalArgumentException( "The session for a MapBasedAuthenticator must be a java.util.Map" );
}
( (Map) session ).put( key, value );
}
public AuthenticationResult authenticate( AuthenticationDataSource ds, Map session )
throws AuthenticationException, AccountLockedException, MustChangePasswordException
{
return super.authenticate( ds, session );
}
public User getSessionUser( Map session )
{
return super.getSessionUser( session );
}
public boolean isAlreadyAuthenticated( Map session )
{
return super.isAlreadyAuthenticated( session );
}
public SecuritySession getSecuritySession( Map session )
{
return super.getSecuritySession( session );
}
public void setSecuritySession( SecuritySession session, Map sessionObj )
{
super.setSecuritySession( session, sessionObj );
}
public void setSessionUser( User user, Map session )
{
super.setSessionUser( user, session );
}
public String storeDefaultUser( String principal, Map session )
{
return super.storeDefaultUser( principal, session );
}
}

View File

@ -1,79 +0,0 @@
package org.codehaus.plexus.redback.http.authentication;
import javax.servlet.http.HttpSession;
import org.codehaus.plexus.redback.authentication.AuthenticationDataSource;
import org.codehaus.plexus.redback.authentication.AuthenticationException;
import org.codehaus.plexus.redback.authentication.AuthenticationResult;
import org.codehaus.plexus.redback.policy.AccountLockedException;
import org.codehaus.plexus.redback.policy.MustChangePasswordException;
import org.codehaus.plexus.redback.system.SecuritySession;
import org.codehaus.plexus.redback.users.User;
/**
* An HttpAuthenticator using an HttpSession for session storage
*
* @author Andrew Williams
* @version $Id$
* @since 1.0
*/
public abstract class SessionBasedHttpAuthenticator
extends AbstractHttpAuthenticator
{
protected Object getSessionValue( Object session, String key )
{
if ( !( session instanceof HttpSession ) )
{
throw new IllegalArgumentException( "The session for a SessionBasedAuthenticator must be a javax.servlet.http.HttpSession" );
}
return ( (HttpSession) session ).getAttribute( key );
}
protected void setSessionValue( Object session, String key, Object value )
{
if ( !( session instanceof HttpSession ) )
{
throw new IllegalArgumentException( "The session for a SessionBasedAuthenticator must be a javax.servlet.http.HttpSession" );
}
( (HttpSession) session ).setAttribute( key, value );
}
public AuthenticationResult authenticate( AuthenticationDataSource ds, HttpSession session )
throws AuthenticationException, AccountLockedException, MustChangePasswordException
{
return super.authenticate( ds, session );
}
public User getSessionUser( HttpSession session )
{
return super.getSessionUser( session );
}
public boolean isAlreadyAuthenticated( HttpSession session )
{
return super.isAlreadyAuthenticated( session );
}
public SecuritySession getSecuritySession( HttpSession session )
{
return super.getSecuritySession( session );
}
public void setSecuritySession( SecuritySession session, HttpSession sessionObj )
{
super.setSecuritySession( session, sessionObj );
}
public void setSessionUser( User user, HttpSession session )
{
super.setSessionUser( user, session );
}
public String storeDefaultUser( String principal, HttpSession session )
{
return super.storeDefaultUser( principal, session );
}
}

View File

@ -1,119 +0,0 @@
package org.codehaus.plexus.redback.http.authentication.basic;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.codec.binary.Base64;
import org.codehaus.plexus.redback.authentication.AuthenticationException;
import org.codehaus.plexus.redback.authentication.AuthenticationResult;
import org.codehaus.plexus.redback.authentication.PasswordBasedAuthenticationDataSource;
import org.codehaus.plexus.redback.http.authentication.SessionBasedHttpAuthenticator;
import org.codehaus.plexus.redback.policy.AccountLockedException;
import org.codehaus.plexus.redback.policy.MustChangePasswordException;
import org.codehaus.plexus.util.StringUtils;
import org.springframework.stereotype.Service;
/**
* HttpBasicAuthentication
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @author Andrew Williams
* @version $Id$
*/
@Service("httpAuthenticator#basic")
public class HttpBasicAuthentication
extends SessionBasedHttpAuthenticator
{
public String getId()
{
return HttpBasicAuthentication.class.getName();
}
public AuthenticationResult getAuthenticationResult( HttpServletRequest request, HttpServletResponse response )
throws AuthenticationException, AccountLockedException, MustChangePasswordException
{
HttpSession session = request.getSession();
if ( isAlreadyAuthenticated( session ) )
{
return getSecuritySession( session ).getAuthenticationResult();
}
PasswordBasedAuthenticationDataSource authDataSource;
String header = request.getHeader( "Authorization" );
// in tomcat this is : authorization=Basic YWRtaW46TWFuYWdlMDc=
if ( header == null )
{
header = request.getHeader("authorization");
}
if ( ( header != null ) && header.startsWith( "Basic " ) )
{
String base64Token = header.substring( 6 );
String token = new String( Base64.decodeBase64( base64Token.getBytes() ) );
String username = "";
String password = "";
int delim = token.indexOf( ':' );
if ( delim != ( -1 ) )
{
username = token.substring( 0, delim );
password = token.substring( delim + 1 );
}
authDataSource = new PasswordBasedAuthenticationDataSource( username, password );
return super.authenticate( authDataSource, session );
}
else
{
return null;
}
}
/**
* Return a HTTP 403 - Access Denied response.
*
* @param request the request to use.
* @param response the response to use.
* @param realmName the realm name to state.
* @param exception the exception to base the message off of.
* @throws IOException if there was a problem with the {@link HttpServletResponse#sendError(int,String)} call.
*/
public void challenge( HttpServletRequest request, HttpServletResponse response, String realmName,
AuthenticationException exception )
throws IOException
{
response.addHeader( "WWW-Authenticate", "Basic realm=\"" + realmName + "\"" );
String message = "You must provide a username and password to access this resource.";
if ( ( exception != null ) && StringUtils.isNotEmpty( exception.getMessage() ) )
{
message = exception.getMessage();
}
response.sendError( HttpServletResponse.SC_UNAUTHORIZED, message );
}
}

View File

@ -1,51 +0,0 @@
package org.codehaus.plexus.redback.http.authentication.digest;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* Digest
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
* @todo move to plexus-utils in future
*/
public class Digest
{
public static String md5Hex( String data )
{
MessageDigest digest = getDigest( "MD5" );
return Hex.encode( digest.digest( data.getBytes() ) );
}
public static MessageDigest getDigest( String algorithm )
{
try
{
return MessageDigest.getInstance( algorithm );
}
catch ( NoSuchAlgorithmException e )
{
throw new RuntimeException( "Error initializing MessageDigest: " + e.getMessage(), e );
}
}
}

View File

@ -1,52 +0,0 @@
package org.codehaus.plexus.redback.http.authentication.digest;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/**
* Hex
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
* @todo should probably move this to plexus-utils or plexus-security-common
*/
public class Hex
{
private static final byte[] DIGITS = "0123456789abcdef".getBytes();
public static String encode( byte[] data )
{
int l = data.length;
byte[] raw = new byte[l * 2];
for ( int i = 0, j = 0; i < l; i++ )
{
raw[j++] = DIGITS[( 0xF0 & data[i] ) >>> 4];
raw[j++] = DIGITS[0x0F & data[i]];
}
return new String( raw );
}
public static String encode( String raw )
{
return encode( raw.getBytes() );
}
}

View File

@ -1,212 +0,0 @@
package org.codehaus.plexus.redback.http.authentication.digest;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import org.apache.commons.codec.binary.Base64;
import org.codehaus.plexus.redback.authentication.AuthenticationException;
import org.codehaus.plexus.redback.authentication.AuthenticationResult;
import org.codehaus.plexus.redback.authentication.TokenBasedAuthenticationDataSource;
import org.codehaus.plexus.redback.http.authentication.HttpAuthenticationException;
import org.codehaus.plexus.redback.http.authentication.SessionBasedHttpAuthenticator;
import org.codehaus.plexus.redback.policy.AccountLockedException;
import org.codehaus.plexus.redback.policy.MustChangePasswordException;
import org.codehaus.plexus.redback.users.User;
import org.codehaus.plexus.redback.users.UserManager;
import org.codehaus.plexus.redback.users.UserNotFoundException;
import org.codehaus.plexus.util.StringUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* HttpDigestAuthentication methods for working with <a href="http://www.faqs.org/rfcs/rfc2617.html">RFC 2617 HTTP Authentication</a>.
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @author Andrew Williams
* @version $Id$
*/
@Service( "attpAuthenticator#digest" )
public class HttpDigestAuthentication
extends SessionBasedHttpAuthenticator
{
@Resource( name = "userManager#configurable" )
private UserManager userManager;
/**
*
*/
private int nonceLifetimeSeconds = 300;
/**
* NOTE: Must be alphanumeric.
*/
private String digestKey = "OrycteropusAfer";
private String realm;
public String getId()
{
return HttpDigestAuthentication.class.getName();
}
public AuthenticationResult getAuthenticationResult( HttpServletRequest request, HttpServletResponse response )
throws AuthenticationException, AccountLockedException, MustChangePasswordException
{
HttpSession session = request.getSession();
if ( isAlreadyAuthenticated( session ) )
{
return getSecuritySession( session ).getAuthenticationResult();
}
TokenBasedAuthenticationDataSource authDataSource = new TokenBasedAuthenticationDataSource();
String authHeader = request.getHeader( "Authorization" );
// in tomcat this is : authorization=Basic YWRtaW46TWFuYWdlMDc=
if ( authHeader == null )
{
authHeader = request.getHeader( "authorization" );
}
if ( ( authHeader != null ) && authHeader.startsWith( "Digest " ) )
{
String rawDigestHeader = authHeader.substring( 7 );
HttpDigestHeader digestHeader = new HttpDigestHeader();
digestHeader.parseClientHeader( rawDigestHeader, getRealm(), digestKey );
// Lookup password for presented username
User user = findUser( digestHeader.username );
authDataSource.setPrincipal( user.getPrincipal().toString() );
String serverSideHash = generateDigestHash( digestHeader, user.getPassword(), request.getMethod() );
if ( !StringUtils.equals( serverSideHash, digestHeader.response ) )
{
throw new HttpAuthenticationException( "Digest response was invalid." );
}
}
return super.authenticate( authDataSource, session );
}
public User findUser( String username )
throws HttpAuthenticationException
{
try
{
return userManager.findUser( username );
}
catch ( UserNotFoundException e )
{
String msg = "Unable to find primary user '" + username + "'.";
log.error( msg, e );
throw new HttpAuthenticationException( msg, e );
}
}
/**
* Issue HTTP Digest Authentication Challenge
*
* @param request the request to use.
* @param response the response to use.
* @param realmName the realm name to state.
* @param exception the exception to base the message off of.
* @throws IOException if there was a problem with the {@link HttpServletResponse#sendError(int, String)} call.
*/
public void challenge( HttpServletRequest request, HttpServletResponse response, String realmName,
AuthenticationException exception )
throws IOException
{
// The Challenge Header
StringBuilder authHeader = new StringBuilder();
authHeader.append( "Digest " );
// [REQUIRED] The name to appear in the dialog box to the user.
authHeader.append( "realm=\"" ).append( realmName ).append( "\"" );
// [OPTIONAL] We do not use the optional 'domain' header.
// authHeader.append( "domain=\"" ).append( domain ).append( "\"" );
// [REQUIRED] Nonce specification.
authHeader.append( ", nonce=\"" );
long timestamp = System.currentTimeMillis() + ( nonceLifetimeSeconds * 1000 );
// Not using ETag from RFC 2617 intentionally.
String hraw = String.valueOf( timestamp ) + ":" + digestKey;
String rawnonce = String.valueOf( timestamp ) + ":" + Digest.md5Hex( hraw );
authHeader.append( Base64.encodeBase64( rawnonce.getBytes() ) );
authHeader.append( "\"" );
// [REQUIRED] The RFC 2617 Quality of Protection.
// MSIE Appears to only support 'auth'
// Do not use 'opaque' here. (Your MSIE users will have issues)
authHeader.append( ", qop=\"auth\"" );
// [BROKEN] since we force the 'auth' qop we cannot use the opaque option.
// authHeader.append( ", opaque=\"").append(opaqueString).append("\"");
// [OPTIONAL] Use of the stale option is reserved for expired nonce strings.
if ( exception instanceof NonceExpirationException )
{
authHeader.append( ", stale=\"true\"" );
}
// [OPTIONAL] We do not use the optional Algorithm header.
// authHeader.append( ", algorithm=\"MD5\"");
response.addHeader( "WWW-Authenticate", authHeader.toString() );
response.sendError( HttpServletResponse.SC_UNAUTHORIZED, exception.getMessage() );
}
private String generateDigestHash( HttpDigestHeader digestHeader, String password, String httpMethod )
{
String a1 = Digest.md5Hex( digestHeader.username + ":" + realm + ":" + password );
String a2 = Digest.md5Hex( httpMethod + ":" + digestHeader.uri );
String digest;
if ( StringUtils.isEmpty( digestHeader.qop ) )
{
digest = a1 + ":" + digestHeader.nonce + ":" + a2;
}
else if ( StringUtils.equals( "auth", digestHeader.qop ) )
{
digest = a1 + ":" + digestHeader.nonce + ":" + digestHeader.nc + ":" + digestHeader.cnonce + ":"
+ digestHeader.qop + ":" + a2;
}
else
{
throw new IllegalStateException(
"Http Digest Parameter [qop] with value of [" + digestHeader.qop + "] is unsupported." );
}
return Digest.md5Hex( digest );
}
public String getRealm()
{
return realm;
}
public void setRealm( String realm )
{
this.realm = realm;
}
}

View File

@ -1,148 +0,0 @@
package org.codehaus.plexus.redback.http.authentication.digest;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import org.apache.commons.codec.binary.Base64;
import org.codehaus.plexus.redback.http.HttpUtils;
import org.codehaus.plexus.redback.http.authentication.HttpAuthenticationException;
import org.codehaus.plexus.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import java.util.Properties;
/**
* HttpDigestHeader
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*/
@Service( "httpClientHeader" )
@Scope( "protype" )
class HttpDigestHeader
{
private Logger log = LoggerFactory.getLogger( getClass() );
public String username;
public String realm;
public String nonce;
public String uri;
public String response;
public String qop;
public String nc;
public String cnonce;
public void parseClientHeader( String rawHeader, String expectedRealm, String digestKey )
throws HttpAuthenticationException
{
Properties authHeaderProps = HttpUtils.complexHeaderToProperties( rawHeader, ",", "=" );
username = authHeaderProps.getProperty( "username" );
realm = authHeaderProps.getProperty( "realm" );
nonce = authHeaderProps.getProperty( "nonce" );
uri = authHeaderProps.getProperty( "uri" );
response = authHeaderProps.getProperty( "response" );
qop = authHeaderProps.getProperty( "qop" );
nc = authHeaderProps.getProperty( "nc" );
cnonce = authHeaderProps.getProperty( "cnonce" );
// [RFC 2067] Validate all required values
if ( StringUtils.isEmpty( username ) || StringUtils.isEmpty( realm ) || StringUtils.isEmpty( nonce )
|| StringUtils.isEmpty( uri ) || StringUtils.isEmpty( response ) )
{
log.debug( "Missing mandatory fields: Raw Digest Header : [{}]", rawHeader );
throw new HttpAuthenticationException( "Missing mandatory digest fields per RFC2069." );
}
// [RFC 2617] Validate realm.
if ( !StringUtils.equals( expectedRealm, realm ) )
{
log.debug( "Realm name is invalid: expected [{}] but got [{}]", expectedRealm, realm );
throw new HttpAuthenticationException( "Response realm does not match expected realm." );
}
// [RFC 2617] Validate "auth" qop
if ( StringUtils.equals( "auth", qop ) )
{
if ( StringUtils.isEmpty( nc ) || StringUtils.isEmpty( cnonce ) )
{
log.debug( "Missing mandatory qop fields: nc [{}] cnonce [{}]", nc, cnonce );
throw new HttpAuthenticationException( "Missing mandatory qop digest fields per RFC2617." );
}
}
// [RFC 2617] Validate nonce
if ( !Base64.isArrayByteBase64( nonce.getBytes() ) )
{
log.debug( "Nonce is not encoded in Base64: nonce [{}]", nonce );
throw new HttpAuthenticationException( "Response nonce is not encoded in Base64." );
}
// Decode nonce
String decodedNonce = new String( Base64.decodeBase64( nonce.getBytes() ) );
String nonceTokens[] = StringUtils.split( decodedNonce, ":" );
// Validate nonce format
if ( nonceTokens.length != 2 )
{
log.debug( "Nonce format expected [2] elements, but got [{}] instead. Decoded nonce [{}]",
nonceTokens.length, decodedNonce );
throw new HttpAuthenticationException(
"Nonce format is invalid. " + "Received an unexpected number of sub elements." );
}
// Extract nonce timestamp
long nonceTimestamp = 0;
try
{
nonceTimestamp = Long.parseLong( nonceTokens[0] );
}
catch ( NumberFormatException e )
{
throw new HttpAuthenticationException( "Unexpected nonce timestamp." );
}
// Extract nonce signature
String expectedSignature = Digest.md5Hex( nonceTimestamp + ":" + digestKey );
if ( !StringUtils.equals( expectedSignature, nonceTokens[1] ) )
{
log.error( "Nonce parameter has been compromised." );
throw new HttpAuthenticationException( "Nonce parameter has been compromised." );
}
}
}

View File

@ -1,53 +0,0 @@
package org.codehaus.plexus.redback.http.authentication.digest;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import org.codehaus.plexus.redback.http.authentication.HttpAuthenticationException;
/**
* NonceExpirationException
*
* @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a>
* @version $Id$
*/
public class NonceExpirationException
extends HttpAuthenticationException
{
public NonceExpirationException()
{
super();
}
public NonceExpirationException( String message, Throwable cause )
{
super( message, cause );
}
public NonceExpirationException( String message )
{
super( message );
}
public NonceExpirationException( Throwable cause )
{
super( cause );
}
}

View File

@ -1,33 +0,0 @@
<?xml version="1.0"?>
<!--
~ Licensed to the Apache Software Foundation (ASF) under one
~ or more contributor license agreements. See the NOTICE file
~ distributed with this work for additional information
~ regarding copyright ownership. The ASF licenses this file
~ to you under the Apache License, Version 2.0 (the
~ "License"); you may not use this file except in compliance
~ with the License. You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
-->
<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"
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"
default-lazy-init="true">
<context:annotation-config />
<context:component-scan base-package="org.codehaus.plexus.redback.http.authentication"/>
</beans>

View File

@ -1,43 +0,0 @@
package org.codehaus.plexus.redback.http.authentication.digest;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import junit.framework.TestCase;
public class HexTest
extends TestCase
{
public void testEncoding()
{
String raw = "Lenore\nLenore";
String lenoreHex = "4c656e6f7265";
String expected = lenoreHex + "0a" + lenoreHex;
assertEquals( expected, Hex.encode( raw ) );
}
public void testTheRaven()
{
String raw = "Quoth the Raven, \"Nevermore.\"";
String expected = "51756f74682074686520526176656e2c20224e657665726d6f72652e22";
assertEquals( expected, Hex.encode( raw.getBytes() ) );
}
}