start implementation of authentication and authorization

This commit is contained in:
Sebastian Sdorra
2013-01-06 14:38:08 +01:00
parent 0ce48bb5d8
commit 1813452411
16 changed files with 1018 additions and 10 deletions

View File

@@ -32,6 +32,26 @@
<version>1.1</version>
<scope>provided</scope>
</dependency>
<!-- logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>log4j-over-slf4j</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
@@ -51,12 +71,6 @@
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
</dependency>
<dependency>
<groupId>rome</groupId>
<artifactId>rome</artifactId>

View File

@@ -0,0 +1,229 @@
/**
* Copyright (c) 2010, Sebastian Sdorra All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. 2. Redistributions in
* binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. 3. Neither the name of SCM-Manager;
* nor the names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.plugin;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.base.Objects;
import org.apache.shiro.authc.SaltedAuthenticationInfo;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.util.ByteSource;
//~--- JDK imports ------------------------------------------------------------
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
/**
*
* @author Sebastian Sdorra
*/
@XmlRootElement(name = "admin-account")
@XmlAccessorType(XmlAccessType.FIELD)
public class AdminAccountConfiguration implements SaltedAuthenticationInfo
{
/** Field description */
private static final long serialVersionUID = -8678832281151044462L;
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
*/
public AdminAccountConfiguration() {}
/**
* Constructs ...
*
*
* @param username
* @param salt
* @param password
*/
public AdminAccountConfiguration(String username, String salt,
String password)
{
this.username = username;
this.salt = salt;
this.password = password;
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param obj
*
* @return
*/
@Override
public boolean equals(Object obj)
{
if (obj == null)
{
return false;
}
if (getClass() != obj.getClass())
{
return false;
}
final AdminAccountConfiguration other = (AdminAccountConfiguration) obj;
return Objects.equal(username, other.username)
&& Objects.equal(salt, other.salt)
&& Objects.equal(password, other.password);
}
/**
* Method description
*
*
* @return
*/
@Override
public int hashCode()
{
return Objects.hashCode(username, salt, password);
}
/**
* Method description
*
*
* @return
*/
@Override
public String toString()
{
//J-
return Objects.toStringHelper(this)
.add("username", username)
.add("salt", "xxx")
.add("password", "xxx")
.toString();
//J+
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @return
*/
@Override
public Object getCredentials()
{
return password;
}
/**
* Method description
*
*
* @return
*/
@Override
public ByteSource getCredentialsSalt()
{
return ByteSource.Util.bytes(Base64.decode(salt));
}
/**
* Method description
*
*
* @return
*/
public String getPassword()
{
return password;
}
/**
* Method description
*
*
* @return
*/
@Override
public PrincipalCollection getPrincipals()
{
// TODO
return new SimplePrincipalCollection(username, "scm-backend");
}
/**
* Method description
*
*
* @return
*/
public String getSalt()
{
return salt;
}
/**
* Method description
*
*
* @return
*/
public String getUsername()
{
return username;
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private String password;
/** Field description */
private String salt;
/** Field description */
private String username;
}

View File

@@ -42,7 +42,6 @@ import sonia.scm.xml.XmlIntervalAdapter;
import java.io.File;
import java.util.Set;
import javax.xml.bind.annotation.XmlAccessType;
@@ -61,6 +60,17 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
public class BackendConfiguration
{
/**
* Method description
*
*
* @return
*/
public AdminAccountConfiguration getAdminAccount()
{
return adminAccount;
}
/**
* Method description
*
@@ -140,6 +150,10 @@ public class BackendConfiguration
//~--- fields ---------------------------------------------------------------
/** Field description */
@XmlElement(name = "admin-account")
private AdminAccountConfiguration adminAccount;
/** Field description */
@XmlElement(name = "directory")
@XmlElementWrapper(name = "directories")

View File

@@ -39,10 +39,14 @@ import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.servlet.GuiceServletContextListener;
import org.apache.shiro.guice.web.ShiroWebModule;
import sonia.scm.plugin.scanner.PluginScannerScheduler;
import sonia.scm.plugin.security.SecurityModule;
//~--- JDK imports ------------------------------------------------------------
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
/**
@@ -74,6 +78,7 @@ public class BackendContextListener extends GuiceServletContextListener
@Override
public void contextInitialized(ServletContextEvent servletContextEvent)
{
this.servletContext = servletContextEvent.getServletContext();
super.contextInitialized(servletContextEvent);
scheduler = injector.getInstance(PluginScannerScheduler.class);
scheduler.start();
@@ -90,7 +95,8 @@ public class BackendContextListener extends GuiceServletContextListener
@Override
protected Injector getInjector()
{
injector = Guice.createInjector(new ScmBackendModule());
injector = Guice.createInjector(ShiroWebModule.guiceFilterModule(),
new SecurityModule(servletContext), new ScmBackendModule());
return injector;
}
@@ -102,4 +108,7 @@ public class BackendContextListener extends GuiceServletContextListener
/** Field description */
private PluginScannerScheduler scheduler;
/** Field description */
private ServletContext servletContext;
}

View File

@@ -0,0 +1,38 @@
/**
* Copyright (c) 2010, Sebastian Sdorra All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. 2. Redistributions in
* binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. 3. Neither the name of SCM-Manager;
* nor the names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.plugin;
/**
*
* @author Sebastian Sdorra
*/
public class Roles
{
public static final String ADMIN = "admin";
}

View File

@@ -36,7 +36,6 @@ package sonia.scm.plugin;
//~--- non-JDK imports --------------------------------------------------------
import com.google.inject.multibindings.Multibinder;
import com.google.inject.name.Names;
import com.google.inject.servlet.ServletModule;
import net.sf.ehcache.CacheManager;
@@ -51,7 +50,6 @@ import sonia.scm.plugin.scanner.DefaultPluginScannerFactory;
import sonia.scm.plugin.scanner.PluginScannerFactory;
import sonia.scm.plugin.scanner.PluginScannerScheduler;
import sonia.scm.plugin.scanner.TimerPluginScannerScheduler;
import sonia.scm.util.Util;
import sonia.scm.web.proxy.ProxyConfigurationProvider;
import sonia.scm.web.proxy.ProxyServlet;

View File

@@ -0,0 +1,97 @@
/**
* Copyright (c) 2010, Sebastian Sdorra All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. 2. Redistributions in
* binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. 3. Neither the name of SCM-Manager;
* nor the names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.plugin.rest;
//~--- non-JDK imports --------------------------------------------------------
import com.google.inject.Inject;
import sonia.scm.plugin.BackendConfiguration;
//~--- JDK imports ------------------------------------------------------------
import com.sun.jersey.api.view.Viewable;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
/**
*
* @author Sebastian Sdorra
*/
@Path("admin")
public class AdminResource extends ViewableResource
{
/** Field description */
private static final String PAGE_OVERVIEW = "/admin/index";
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
*
* @param context
* @param configuration
*/
@Inject
public AdminResource(ServletContext context,
BackendConfiguration configuration)
{
super(context, configuration);
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @return
*/
@GET
@Path("index.html")
@Produces(MediaType.TEXT_HTML)
public Viewable overview()
{
Map<String, Object> env = createVarMap("Administrator");
return new Viewable(PAGE_OVERVIEW, env);
}
}

View File

@@ -0,0 +1,97 @@
/**
* Copyright (c) 2010, Sebastian Sdorra All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. 2. Redistributions in
* binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. 3. Neither the name of SCM-Manager;
* nor the names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.plugin.rest;
//~--- non-JDK imports --------------------------------------------------------
import com.google.inject.Inject;
import sonia.scm.plugin.BackendConfiguration;
//~--- JDK imports ------------------------------------------------------------
import com.sun.jersey.api.view.Viewable;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
/**
*
* @author Sebastian Sdorra
*/
@Path("error")
public class ErrorResource extends ViewableResource
{
/** Field description */
private static final String PAGE_UNAUTHORIZED = "/error/Unauthorized.html";
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
*
* @param context
* @param configuration
*/
@Inject
public ErrorResource(ServletContext context,
BackendConfiguration configuration)
{
super(context, configuration);
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @return
*/
@GET
@Path("unauthorized.html")
@Produces(MediaType.TEXT_HTML)
public Viewable unauthorized()
{
Map<String, Object> env = createVarMap("Unauthorized");
return new Viewable(PAGE_UNAUTHORIZED, env);
}
}

View File

@@ -0,0 +1,116 @@
/**
* Copyright (c) 2010, Sebastian Sdorra All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. 2. Redistributions in
* binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. 3. Neither the name of SCM-Manager;
* nor the names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.plugin.rest;
//~--- non-JDK imports --------------------------------------------------------
import com.google.inject.Inject;
import sonia.scm.plugin.BackendConfiguration;
//~--- JDK imports ------------------------------------------------------------
import com.sun.jersey.api.view.Viewable;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
/**
*
* @author Sebastian Sdorra
*/
@Path("/page/login.html")
public class LoginResource extends ViewableResource
{
/** Field description */
private static final String PAGE_LOGIN = "/login";
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
*
* @param context
* @param configuration
*/
@Inject
public LoginResource(ServletContext context,
BackendConfiguration configuration)
{
super(context, configuration);
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @return
*/
@POST
@Produces(MediaType.TEXT_HTML)
public Viewable loginFailed()
{
Map<String, Object> vars = createVarMap("Login");
vars.put("error", "Login failed");
return new Viewable(PAGE_LOGIN, vars);
}
//~--- get methods ----------------------------------------------------------
/**
* Method description
*
*
* @return
*/
@GET
@Produces(MediaType.TEXT_HTML)
public Viewable getForm()
{
Map<String, Object> vars = createVarMap("Login");
return new Viewable(PAGE_LOGIN, vars);
}
}

View File

@@ -0,0 +1,154 @@
/**
* Copyright (c) 2010, Sebastian Sdorra All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. 2. Redistributions in
* binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. 3. Neither the name of SCM-Manager;
* nor the names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.plugin.security;
//~--- non-JDK imports --------------------------------------------------------
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSet;
import com.google.inject.Inject;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.plugin.AdminAccountConfiguration;
import sonia.scm.plugin.BackendConfiguration;
import sonia.scm.plugin.Roles;
/**
*
* @author Sebastian Sdorra
*/
public class DefaultAdminRealm extends AuthorizingRealm
{
/** Field description */
public static final String NAME = "scm.backend";
/**
* the logger for ScmBackendRealm
*/
private static final Logger logger =
LoggerFactory.getLogger(DefaultAdminRealm.class);
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
*
* @param configuration
* @param credentialsMatcher
*/
@Inject
public DefaultAdminRealm(BackendConfiguration configuration,
CredentialsMatcher credentialsMatcher)
{
super(credentialsMatcher);
this.configuration = configuration;
setAuthenticationTokenClass(UsernamePasswordToken.class);
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param token
*
* @return
*
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token)
throws AuthenticationException
{
Preconditions.checkNotNull(token);
UsernamePasswordToken upToken = (UsernamePasswordToken) token;
String username = upToken.getUsername();
if (logger.isDebugEnabled())
{
logger.debug("start authentication for user {}", username);
}
AdminAccountConfiguration adminAccount = configuration.getAdminAccount();
if (!adminAccount.getUsername().equals(adminAccount.getUsername()))
{
throw new UnknownAccountException("unknown account ".concat(username));
}
return adminAccount;
}
/**
* Method description
*
*
* @param principals
*
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals)
{
if (principals == null)
{
throw new AuthenticationException("principals should not be null");
}
return new SimpleAuthorizationInfo(ImmutableSet.of(Roles.ADMIN));
}
//~--- fields ---------------------------------------------------------------
/** Field description */
private BackendConfiguration configuration;
}

View File

@@ -0,0 +1,198 @@
/**
* Copyright (c) 2010, Sebastian Sdorra All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer. 2. Redistributions in
* binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution. 3. Neither the name of SCM-Manager;
* nor the names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* http://bitbucket.org/sdorra/scm-manager
*
*/
package sonia.scm.plugin.security;
//~--- non-JDK imports --------------------------------------------------------
import com.google.inject.name.Named;
import com.google.inject.name.Names;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.crypto.RandomNumberGenerator;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.guice.web.ShiroWebModule;
import org.apache.shiro.util.ByteSource;
import sonia.scm.plugin.Roles;
//~--- JDK imports ------------------------------------------------------------
import javax.servlet.ServletContext;
import javax.swing.JOptionPane;
/**
*
* @author Sebastian Sdorra
*/
public class SecurityModule extends ShiroWebModule
{
/** Field description */
private static final String ATTRIBUTE_FAILURE = "shiroLoginFailure";
/** Field description */
private static final String HASH_ALGORITHM = "SHA-256";
/** Field description */
private static final int HASH_ITERATIONS = 1024;
/** Field description */
private static final String PAGE_LOGIN = "/page/login.html";
/** Field description */
private static final String PAGE_SUCCESS = "/admin/index.html";
/** Field description */
private static final String PAGE_UNAUTHORIZED = "/error/unauthorized.html";
/** Field description */
private static final String PARAM_PASSWORD = "password";
/** Field description */
private static final String PARAM_REMEMBERME = "rememberme";
/** Field description */
private static final String PARAM_USERNAME = "username";
/** Field description */
private static final String PATTERN_ADMIN = "/admin/**";
/** Field description */
private static final Named NAMED_USERNAMEPARAM =
Names.named("shiro.usernameParam");
/** Field description */
private static final Named NAMED_UNAUTHORIZEDURL =
Names.named("shiro.unauthorizedUrl");
/** Field description */
private static final Named NAMED_SUCCESSURL = Names.named("shiro.successUrl");
/** Field description */
private static final Named NAMED_REMEMBERMEPARAM =
Names.named("shiro.rememberMeParam");
/** Field description */
private static final Named NAMED_PASSWORDPARAM =
Names.named("shiro.passwordParam");
/** Field description */
private static final Named NAMED_LOGINURL = Names.named("shiro.loginUrl");
/** Field description */
private static final Named NAMED_FAILUREKEYATTRIBUTE =
Names.named("shiro.failureKeyAttribute");
//~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*
*
* @param servletContext
*/
public SecurityModule(ServletContext servletContext)
{
super(servletContext);
}
//~--- methods --------------------------------------------------------------
/**
* Method description
*
*
* @param args
*/
public static void main(String[] args)
{
String value = JOptionPane.showInputDialog("Password");
RandomNumberGenerator rng = new SecureRandomNumberGenerator();
ByteSource salt = rng.nextBytes();
SimpleHash hash = new SimpleHash(HASH_ALGORITHM, value, salt,
HASH_ITERATIONS);
System.out.append("Salt: ").println(salt.toBase64());
System.out.append("Hash: ").println(hash.toBase64());
}
/**
* Method description
*
*/
@Override
protected void configureShiroWeb()
{
bindConstants();
bindCredentialsMatcher();
// bind realm
bindRealm().to(DefaultAdminRealm.class);
// add filters
addFilterChain(PAGE_LOGIN, AUTHC);
addFilterChain(PATTERN_ADMIN, AUTHC, config(ROLES, Roles.ADMIN));
}
/**
* Method description
*
*/
private void bindConstants()
{
bindConstant().annotatedWith(NAMED_LOGINURL).to(PAGE_LOGIN);
bindConstant().annotatedWith(NAMED_USERNAMEPARAM).to(PARAM_USERNAME);
bindConstant().annotatedWith(NAMED_PASSWORDPARAM).to(PARAM_PASSWORD);
bindConstant().annotatedWith(NAMED_REMEMBERMEPARAM).to(PARAM_REMEMBERME);
bindConstant().annotatedWith(NAMED_SUCCESSURL).to(PAGE_SUCCESS);
bindConstant().annotatedWith(NAMED_UNAUTHORIZEDURL).to(PAGE_UNAUTHORIZED);
bindConstant().annotatedWith(NAMED_FAILUREKEYATTRIBUTE).to(
ATTRIBUTE_FAILURE);
}
/**
* Method description
*
*/
private void bindCredentialsMatcher()
{
HashedCredentialsMatcher matcher =
new HashedCredentialsMatcher(HASH_ALGORITHM);
matcher.setHashIterations(HASH_ITERATIONS);
matcher.setStoredCredentialsHexEncoded(false);
bind(CredentialsMatcher.class).toInstance(matcher);
}
}

View File

@@ -52,6 +52,9 @@
<logger name="sonia.scm" level="DEBUG" />
<logger name="sonia.scm.plugin.scanner.DefaultPluginScanner" level="INFO" />
<!-- trace logging -->
<logger name="org.apache.shiro" level="INFO" />
<root level="WARN">
<appender-ref ref="STDOUT" />

View File

@@ -0,0 +1,5 @@
<#include "../template/header.html">
<h2>Admin</h2>
<#include "../template/footer.html">

View File

@@ -0,0 +1,5 @@
<#include "../template/header.html">
<h2>Unauthorized</h2>
<#include "../template/footer.html">

View File

@@ -0,0 +1,28 @@
<#include "template/header.html">
<form method="POST" action="">
<table>
<tr>
<td>
<label for="username">Username</label>
</td>
<td>
<input type="text" name="username">
</td>
</tr>
<tr>
<td>
<label for="password">Password</label>
</td>
<td>
<input type="password" name="password">
</td>
</tr>
</table>
<input type="submit" value="Login">
</form>
<#include "template/footer.html">

View File

@@ -113,6 +113,9 @@
<header class="entry-header">
<h1 class="entry-title">${title}</h1>
</header>
<#if error??>
<div style="color: red">${error}</div>
</#if>
<div class="entry-content">
<!-- content begin -->