Sfoglia il codice sorgente

[MRM-773]

-added basic http authentication to rss feed servlet 
-added commons-codec as dependency which is used for decoding the username and password
-updated tests


git-svn-id: https://svn.apache.org/repos/asf/archiva/trunk@652981 13f79535-47bb-0310-9956-ffa450edef68
tags/archiva-r676265
Maria Odea B. Ching 16 anni fa
parent
commit
f781bfffa4

+ 5
- 0
archiva-modules/archiva-web/archiva-webapp/pom.xml Vedi File

@@ -299,6 +299,11 @@
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.3</version>
</dependency>
</dependencies>
<build>
<plugins>

+ 150
- 17
archiva-modules/archiva-web/archiva-webapp/src/main/java/org/apache/maven/archiva/web/rss/RssFeedServlet.java Vedi File

@@ -20,7 +20,10 @@ package org.apache.maven.archiva.web.rss;
*/

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
@@ -28,8 +31,23 @@ import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.archiva.rss.RssFeedGenerator;
import org.apache.archiva.rss.processor.RssFeedProcessor;
import org.apache.commons.codec.Decoder;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Base64;
import org.apache.maven.archiva.security.AccessDeniedException;
import org.apache.maven.archiva.security.ArchivaRoleConstants;
import org.apache.maven.archiva.security.ArchivaSecurityException;
import org.apache.maven.archiva.security.PrincipalNotFoundException;
import org.apache.maven.archiva.security.UserRepositories;
import org.codehaus.plexus.redback.authentication.AuthenticationDataSource;
import org.codehaus.plexus.redback.authentication.AuthenticationException;
import org.codehaus.plexus.redback.authentication.PasswordBasedAuthenticationDataSource;
import org.codehaus.plexus.redback.authorization.AuthorizationException;
import org.codehaus.plexus.redback.policy.AccountLockedException;
import org.codehaus.plexus.redback.system.SecuritySession;
import org.codehaus.plexus.redback.system.SecuritySystem;
import org.codehaus.plexus.redback.users.UserNotFoundException;
import org.codehaus.plexus.spring.PlexusToSpringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -53,17 +71,29 @@ public class RssFeedServlet

private static final String COULD_NOT_GENERATE_FEED_ERROR = "Could not generate feed";

private Logger log = LoggerFactory.getLogger( RssFeedGenerator.class );
private static final String COULD_NOT_AUTHENTICATE_USER = "Could not authenticate user";

private static final String USER_NOT_AUTHORIZED = "User not authorized to access feed.";

private Logger log = LoggerFactory.getLogger( RssFeedServlet.class );

private RssFeedProcessor processor;

private WebApplicationContext wac;

private SecuritySystem securitySystem;

private UserRepositories userRepositories;

public void init( javax.servlet.ServletConfig servletConfig )
throws ServletException
{
super.init( servletConfig );
wac = WebApplicationContextUtils.getRequiredWebApplicationContext( servletConfig.getServletContext() );
securitySystem =
(SecuritySystem) wac.getBean( PlexusToSpringUtils.buildSpringId( SecuritySystem.class.getName() ) );
userRepositories =
(UserRepositories) wac.getBean( PlexusToSpringUtils.buildSpringId( UserRepositories.class.getName() ) );
}

public void doGet( HttpServletRequest req, HttpServletResponse res )
@@ -74,17 +104,21 @@ public class RssFeedServlet
{
Map<String, String> map = new HashMap<String, String>();
SyndFeed feed = null;
if ( req.getParameter( "repoId" ) != null )
String repoId = req.getParameter( "repoId" );
String groupId = req.getParameter( "groupId" );
String artifactId = req.getParameter( "artifactId" );

if ( repoId != null )
{
if ( isAuthorized() )

if ( isAuthorized( req ) )
{
// new artifacts in repo feed request
// new artifacts in repo feed request
processor =
(RssFeedProcessor) wac.getBean( PlexusToSpringUtils.buildSpringId(
RssFeedProcessor.class.getName(),
"new-artifacts" ) );
map.put( RssFeedProcessor.KEY_REPO_ID, req.getParameter( "repoId" ) );
map.put( RssFeedProcessor.KEY_REPO_ID, repoId );
}
else
{
@@ -92,17 +126,17 @@ public class RssFeedServlet
return;
}
}
else if ( ( req.getParameter( "groupId" ) != null ) && ( req.getParameter( "artifactId" ) != null ) )
else if ( ( groupId != null ) && ( artifactId != null ) )
{
if ( isAuthorized() )
if ( isAuthorized( req ) )
{
// new versions of artifact feed request
// new versions of artifact feed request
processor =
(RssFeedProcessor) wac.getBean( PlexusToSpringUtils.buildSpringId(
RssFeedProcessor.class.getName(),
"new-versions" ) );
map.put( RssFeedProcessor.KEY_GROUP_ID, req.getParameter( "groupId" ) );
map.put( RssFeedProcessor.KEY_ARTIFACT_ID, req.getParameter( "artifactId" ) );
map.put( RssFeedProcessor.KEY_GROUP_ID, groupId );
map.put( RssFeedProcessor.KEY_ARTIFACT_ID, artifactId );
}
else
{
@@ -122,16 +156,115 @@ public class RssFeedServlet
SyndFeedOutput output = new SyndFeedOutput();
output.output( feed, res.getWriter() );
}
catch ( AuthorizationException ae )
{
log.error( USER_NOT_AUTHORIZED, ae );
res.sendError( HttpServletResponse.SC_UNAUTHORIZED, USER_NOT_AUTHORIZED );
}
catch ( UserNotFoundException unfe )
{
log.error( COULD_NOT_AUTHENTICATE_USER, unfe );
res.sendError( HttpServletResponse.SC_UNAUTHORIZED, COULD_NOT_AUTHENTICATE_USER );
}
catch ( AccountLockedException acce )
{
log.error( COULD_NOT_AUTHENTICATE_USER, acce );
res.sendError( HttpServletResponse.SC_UNAUTHORIZED, COULD_NOT_AUTHENTICATE_USER );
}
catch ( AuthenticationException authe )
{
log.error( COULD_NOT_AUTHENTICATE_USER, authe );
res.sendError( HttpServletResponse.SC_UNAUTHORIZED, COULD_NOT_AUTHENTICATE_USER );
}
catch ( FeedException ex )
{
String msg = COULD_NOT_GENERATE_FEED_ERROR;
log.error( msg, ex );
res.sendError( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, msg );
log.error( COULD_NOT_GENERATE_FEED_ERROR, ex );
res.sendError( HttpServletResponse.SC_INTERNAL_SERVER_ERROR, COULD_NOT_GENERATE_FEED_ERROR );
}
}

private boolean isAuthorized()
/**
* Basic authentication.
*
* @param req
* @return
*/
private boolean isAuthorized( HttpServletRequest req )
throws UserNotFoundException, AccountLockedException, AuthenticationException, AuthorizationException
{
return true;
String auth = req.getHeader( "Authorization" );

if ( auth == null )
{
return false;
}

if ( !auth.toUpperCase().startsWith( "BASIC " ) )
{
return false;
}

Decoder dec = new Base64();
String usernamePassword = "";

try
{
usernamePassword = new String( ( byte[] ) dec.decode( auth.substring( 6 ).getBytes() ) );
}
catch ( DecoderException ie )
{
log.error( "Error decoding username and password.", ie.getMessage() );
}
String[] userCredentials = usernamePassword.split( ":" );
String username = userCredentials[0];
String password = userCredentials[1];

AuthenticationDataSource dataSource = new PasswordBasedAuthenticationDataSource( username, password );
SecuritySession session = null;

List<String> repoIds = new ArrayList<String>();
if ( req.getParameter( "repoId" ) != null )
{
repoIds.add( req.getParameter( "repoId" ) );
}
else
{
repoIds = getObservableRepos( username );
}

session = securitySystem.authenticate( dataSource );

for ( String repoId : repoIds )
{
if ( securitySystem.isAuthorized( session, ArchivaRoleConstants.OPERATION_REPOSITORY_ACCESS, repoId ) )
{
return true;
}
}

return false;
}

private List<String> getObservableRepos( String principal )
{
try
{
return userRepositories.getObservableRepositoryIds( principal );
}
catch ( PrincipalNotFoundException e )
{
log.warn( e.getMessage(), e );
}
catch ( AccessDeniedException e )
{
log.warn( e.getMessage(), e );
}
catch ( ArchivaSecurityException e )
{
log.warn( e.getMessage(), e );
}

return Collections.emptyList();
}
}

+ 71
- 10
archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/rss/RssFeedServletTest.java Vedi File

@@ -19,9 +19,19 @@ package org.apache.maven.archiva.web.rss;
* under the License.
*/

import java.io.IOException;

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.codec.Encoder;
import org.apache.commons.codec.binary.Base64;
import org.codehaus.plexus.spring.PlexusInSpringTestCase;

import sun.misc.BASE64Encoder;

import com.meterware.httpunit.GetMethodWebRequest;
import com.meterware.httpunit.HttpException;
import com.meterware.httpunit.WebRequest;
import com.meterware.httpunit.WebResponse;
import com.meterware.servletunit.ServletRunner;
import com.meterware.servletunit.ServletUnitClient;
@@ -60,9 +70,15 @@ public class RssFeedServletTest
(RssFeedServlet) client.newInvocation( "http://localhost/rss/rss_feeds?repoId=test-repo" ).getServlet();
assertNotNull( servlet );

WebResponse response = client.getResponse( "http://localhost/rss/rss_feeds?repoId=test-repo" );
WebRequest request = new GetMethodWebRequest( "http://localhost/rss/rss_feeds?repoId=test-repo" );
BASE64Encoder encoder = new BASE64Encoder();
String userPass = "user1:password1";
String encodedUserPass = encoder.encode( userPass.getBytes() );
request.setHeaderField( "Authorization", "BASIC " + encodedUserPass );
WebResponse response = client.getResponse( request );
assertEquals( RssFeedServlet.MIME_TYPE, response.getHeaderField( "CONTENT-TYPE" ) );

assertNotNull( "Should have recieved a response", response );
assertEquals( "Should have been an OK response code.", HttpServletResponse.SC_OK, response.getResponseCode() );
}
@@ -75,9 +91,15 @@ public class RssFeedServletTest
"http://localhost/rss/rss_feeds?groupId=org.apache.archiva&artifactId=artifact-two" ).getServlet();
assertNotNull( servlet );

WebResponse response = client.getResponse( "http://localhost/rss/rss_feeds?groupId=org.apache.archiva&artifactId=artifact-two" );
WebRequest request = new GetMethodWebRequest( "http://localhost/rss/rss_feeds?groupId=org.apache.archiva&artifactId=artifact-two" );
BASE64Encoder encoder = new BASE64Encoder();
String userPass = "user1:password1";
String encodedUserPass = encoder.encode( userPass.getBytes() );
request.setHeaderField( "Authorization", "BASIC " + encodedUserPass );
WebResponse response = client.getResponse( request );
assertEquals( RssFeedServlet.MIME_TYPE, response.getHeaderField( "CONTENT-TYPE" ) );

assertNotNull( "Should have recieved a response", response );
assertEquals( "Should have been an OK response code.", HttpServletResponse.SC_OK, response.getResponseCode() );
}
@@ -99,20 +121,59 @@ public class RssFeedServletTest
assertEquals( "Should have been a bad request response code.", HttpServletResponse.SC_BAD_REQUEST, he.getResponseCode() );
}
}
public void testInvalidAuthenticationRequest()
throws Exception
{
RssFeedServlet servlet =
(RssFeedServlet) client.newInvocation(
"http://localhost/rss/rss_feeds?repoId=unauthorized-repo" ).getServlet();
assertNotNull( servlet );
public void testUnAuthorizedRequest()
WebRequest request = new GetMethodWebRequest( "http://localhost/rss/rss_feeds?repoId=unauthorized-repo" );
Encoder encoder = new Base64();
String userPass = "unauthUser:unauthPass";
String encodedUserPass = new String( ( byte[] ) encoder.encode( userPass.getBytes() ) );
request.setHeaderField( "Authorization", "BASIC " + encodedUserPass );
try
{
WebResponse response = client.getResponse( request );
}
catch ( HttpException he )
{
assertEquals( "Should have been a unauthorized response.", HttpServletResponse.SC_UNAUTHORIZED, he.getResponseCode() );
}
}
public void testUnauthorizedRequest()
throws Exception
{
RssFeedServlet servlet =
(RssFeedServlet) client.newInvocation(
"http://localhost/rss/rss_feeds" ).getServlet();
"http://localhost/rss/rss_feeds?repoId=unauthorized-repo" ).getServlet();
assertNotNull( servlet );
//WebResponse response = client.getResponse( "http://localhost/rss/rss_feeds" );
//assertNotNull( "Should have recieved a response", response );
//assertEquals( "Should have been a bad request response code.", HttpServletResponse.SC_BAD_REQUEST, response.getResponseCode() );
WebRequest request = new GetMethodWebRequest( "http://localhost/rss/rss_feeds?repoId=unauthorized-repo" );
BASE64Encoder encoder = new BASE64Encoder();
String userPass = "user1:password1";
String encodedUserPass = encoder.encode( userPass.getBytes() );
request.setHeaderField( "Authorization", "BASIC " + encodedUserPass );
try
{
WebResponse response = client.getResponse( request );
}
catch ( HttpException he )
{
assertEquals( "Should have been a unauthorized response.", HttpServletResponse.SC_UNAUTHORIZED, he.getResponseCode() );
}
}

@Override
protected String getPlexusConfigLocation()
{

+ 164
- 0
archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/rss/SecuritySystemStub.java Vedi File

@@ -0,0 +1,164 @@
package org.apache.maven.archiva.web.rss;

/*
* 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.ArrayList;
import java.util.HashMap;
import java.util.List;
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.authorization.AuthorizationException;
import org.codehaus.plexus.redback.authorization.AuthorizationResult;
import org.codehaus.plexus.redback.keys.KeyManager;
import org.codehaus.plexus.redback.policy.AccountLockedException;
import org.codehaus.plexus.redback.policy.UserSecurityPolicy;
import org.codehaus.plexus.redback.system.DefaultSecuritySession;
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.UserManager;
import org.codehaus.plexus.redback.users.UserNotFoundException;
import org.codehaus.plexus.redback.users.jdo.JdoUser;

/**
* SecuritySystem stub used for testing.
*
* @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
* @version $Id$
*/
public class SecuritySystemStub
implements SecuritySystem
{
Map<String, String> users = new HashMap<String, String>();

List<String> repoIds = new ArrayList<String>();

public SecuritySystemStub()
{
users.put( "user1", "password1" );
users.put( "user2", "password2" );
users.put( "user3", "password3" );

repoIds.add( "test-repo" );
}

public SecuritySession authenticate( AuthenticationDataSource source )
throws AuthenticationException, UserNotFoundException, AccountLockedException
{
AuthenticationResult result = null;
SecuritySession session = null;

if ( users.get( source.getPrincipal() ) != null )
{
result = new AuthenticationResult( true, source.getPrincipal(), null );

User user = new JdoUser();
user.setUsername( source.getPrincipal() );
user.setPassword( users.get( source.getPrincipal() ) );

session = new DefaultSecuritySession( result, user );
}
else
{
result = new AuthenticationResult( false, source.getPrincipal(), null );
session = new DefaultSecuritySession( result );
}
return session;
}

public AuthorizationResult authorize( SecuritySession arg0, Object arg1 )
throws AuthorizationException
{
// TODO Auto-generated method stub
return null;
}

public AuthorizationResult authorize( SecuritySession arg0, Object arg1, Object arg2 )
throws AuthorizationException
{
// TODO Auto-generated method stub
return null;
}

public String getAuthenticatorId()
{
// TODO Auto-generated method stub
return null;
}

public String getAuthorizerId()
{
// TODO Auto-generated method stub
return null;
}

public KeyManager getKeyManager()
{
// TODO Auto-generated method stub
return null;
}

public UserSecurityPolicy getPolicy()
{
// TODO Auto-generated method stub
return null;
}

public String getUserManagementId()
{
// TODO Auto-generated method stub
return null;
}

public UserManager getUserManager()
{
// TODO Auto-generated method stub
return null;
}

public boolean isAuthenticated( AuthenticationDataSource arg0 )
throws AuthenticationException, UserNotFoundException, AccountLockedException
{
// TODO Auto-generated method stub
return false;
}

public boolean isAuthorized( SecuritySession arg0, Object arg1 )
throws AuthorizationException
{
// TODO Auto-generated method stub
return false;
}

public boolean isAuthorized( SecuritySession arg0, Object arg1, Object arg2 )
throws AuthorizationException
{
if ( repoIds.contains( arg2 ) )
{
return true;
}

return false;
}

}

+ 63
- 0
archiva-modules/archiva-web/archiva-webapp/src/test/java/org/apache/maven/archiva/web/rss/UserRepositoriesStub.java Vedi File

@@ -0,0 +1,63 @@
package org.apache.maven.archiva.web.rss;

/*
* 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.ArrayList;
import java.util.List;

import org.apache.maven.archiva.security.AccessDeniedException;
import org.apache.maven.archiva.security.ArchivaSecurityException;
import org.apache.maven.archiva.security.PrincipalNotFoundException;
import org.apache.maven.archiva.security.UserRepositories;

/**
* UserRepositories stub used for testing.
*
* @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
* @version $Id$
*/
public class UserRepositoriesStub
implements UserRepositories
{

public void createMissingRepositoryRoles( String repoId )
throws ArchivaSecurityException
{
// TODO Auto-generated method stub

}

public List<String> getObservableRepositoryIds( String principal )
throws PrincipalNotFoundException, AccessDeniedException, ArchivaSecurityException
{
List<String> repoIds = new ArrayList<String>();
repoIds.add( "test-repo" );

return repoIds;
}

public boolean isAuthorizedToUploadArtifacts( String principal, String repoId )
throws PrincipalNotFoundException, ArchivaSecurityException
{
// TODO Auto-generated method stub
return false;
}

}

+ 12
- 0
archiva-modules/archiva-web/archiva-webapp/src/test/resources/org/apache/maven/archiva/web/rss/RssFeedServletTest.xml Vedi File

@@ -34,5 +34,17 @@
<role-hint>jdo</role-hint>
<implementation>org.apache.maven.archiva.web.rss.ArtifactDAOStub</implementation>
</component>
<component>
<role>org.codehaus.plexus.redback.system.SecuritySystem</role>
<role-hint>default</role-hint>
<implementation>org.apache.maven.archiva.web.rss.SecuritySystemStub</implementation>
</component>
<component>
<role>org.apache.maven.archiva.security.UserRepositories</role>
<role-hint>default</role-hint>
<implementation>org.apache.maven.archiva.web.rss.UserRepositoriesStub</implementation>
</component>
</components>
</plexus>

Loading…
Annulla
Salva