diff --git a/scm-core/src/main/java/sonia/scm/security/ScmAuthenticationToken.java b/scm-core/src/main/java/sonia/scm/security/ScmAuthenticationToken.java deleted file mode 100644 index f4a96aec42..0000000000 --- a/scm-core/src/main/java/sonia/scm/security/ScmAuthenticationToken.java +++ /dev/null @@ -1,222 +0,0 @@ -/** - * 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.security; - -//~--- non-JDK imports -------------------------------------------------------- - -import com.google.common.base.Objects; - -import org.apache.shiro.authc.AuthenticationToken; - -//~--- JDK imports ------------------------------------------------------------ - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -/** - * - * @author Sebastian Sdorra - * @since 1.21 - */ -public class ScmAuthenticationToken implements AuthenticationToken -{ - - /** Field description */ - private static final long serialVersionUID = -3208692400029843828L; - - //~--- constructors --------------------------------------------------------- - - /** - * Constructs ... - * - * - * @param request - * @param response - * @param username - * @param password - */ - public ScmAuthenticationToken(HttpServletRequest request, - HttpServletResponse response, String username, String password) - { - this.request = request; - this.response = response; - this.username = username; - 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 ScmAuthenticationToken other = (ScmAuthenticationToken) obj; - - return Objects.equal(request, other.request) - && Objects.equal(response, other.response) - && Objects.equal(username, other.username) - && Objects.equal(password, other.password); - } - - /** - * Method description - * - * - * @return - */ - @Override - public int hashCode() - { - return Objects.hashCode(request, response, username, password); - } - - /** - * Method description - * - * - * @return - */ - @Override - public String toString() - { - //J- - return Objects.toStringHelper(this) - .add("request", request) - .add("response", response) - .add("username", username) - .add("password", "xxx") - .toString(); - //J+ - } - - //~--- get methods ---------------------------------------------------------- - - /** - * Method description - * - * - * @return - */ - @Override - public String getCredentials() - { - return password; - } - - /** - * Method description - * - * - * @return - */ - public String getPassword() - { - return password; - } - - /** - * Method description - * - * - * @return - */ - @Override - public String getPrincipal() - { - return username; - } - - /** - * Method description - * - * - * @return - */ - public HttpServletRequest getRequest() - { - return request; - } - - /** - * Method description - * - * - * @return - */ - public HttpServletResponse getResponse() - { - return response; - } - - /** - * Method description - * - * - * @return - */ - public String getUsername() - { - return username; - } - - //~--- fields --------------------------------------------------------------- - - /** Field description */ - private String password; - - /** Field description */ - private HttpServletRequest request; - - /** Field description */ - private HttpServletResponse response; - - /** Field description */ - private String username; -} diff --git a/scm-core/src/main/java/sonia/scm/security/Tokens.java b/scm-core/src/main/java/sonia/scm/security/Tokens.java new file mode 100644 index 0000000000..0a619d825c --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/security/Tokens.java @@ -0,0 +1,67 @@ +/** + * 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.security; + +//~--- non-JDK imports -------------------------------------------------------- + +import org.apache.shiro.authc.AuthenticationToken; +import org.apache.shiro.authc.UsernamePasswordToken; + +//~--- JDK imports ------------------------------------------------------------ + +import javax.servlet.http.HttpServletRequest; + +/** + * + * @author Sebastian Sdorra + * @since 1.21 + */ +public final class Tokens +{ + + /** + * Method description + * + * + * @param request + * @param username + * @param password + * + * @return + */ + public static AuthenticationToken createAuthenticationToken( + HttpServletRequest request, String username, String password) + { + return new UsernamePasswordToken(username, password, + request.getRemoteAddr()); + } +} diff --git a/scm-core/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java b/scm-core/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java index 6e2f34c454..fc2cc6d681 100644 --- a/scm-core/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java +++ b/scm-core/src/main/java/sonia/scm/web/filter/BasicAuthenticationFilter.java @@ -41,6 +41,7 @@ import com.google.inject.Singleton; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; +import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.subject.Subject; import org.slf4j.Logger; @@ -48,7 +49,6 @@ import org.slf4j.LoggerFactory; import sonia.scm.SCMContext; import sonia.scm.config.ScmConfiguration; -import sonia.scm.security.ScmAuthenticationToken; import sonia.scm.user.User; import sonia.scm.util.HttpUtil; import sonia.scm.util.Util; @@ -245,8 +245,8 @@ public class BasicAuthenticationFilter extends HttpFilter try { - subject.login(new ScmAuthenticationToken(request, response, username, - password)); + subject.login(new UsernamePasswordToken(username, password, + request.getRemoteAddr())); user = subject.getPrincipals().oneByType(User.class); } catch (AuthenticationException ex) diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgHookCallbackServlet.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgHookCallbackServlet.java index 8e2c8b558c..23ba07ffc4 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgHookCallbackServlet.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/web/HgHookCallbackServlet.java @@ -54,7 +54,7 @@ import sonia.scm.repository.RepositoryManager; import sonia.scm.repository.RepositoryNotFoundException; import sonia.scm.repository.RepositoryUtil; import sonia.scm.security.CipherUtil; -import sonia.scm.security.ScmAuthenticationToken; +import sonia.scm.security.Tokens; import sonia.scm.util.HttpUtil; import sonia.scm.util.Util; @@ -195,7 +195,7 @@ public class HgHookCallbackServlet extends HttpServlet if (Util.isNotEmpty(credentials)) { - authenticate(request, response, credentials); + authenticate(request, credentials); } hookCallback(response, repositoryId, type, challenge, node); @@ -229,8 +229,7 @@ public class HgHookCallbackServlet extends HttpServlet * @param response * @param credentials */ - private void authenticate(HttpServletRequest request, - HttpServletResponse response, String credentials) + private void authenticate(HttpServletRequest request, String credentials) { try { @@ -244,7 +243,7 @@ public class HgHookCallbackServlet extends HttpServlet { Subject subject = SecurityUtils.getSubject(); - subject.login(new ScmAuthenticationToken(request, response, + subject.login(Tokens.createAuthenticationToken(request, credentialsArray[0], credentialsArray[1])); } } diff --git a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AuthenticationResource.java b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AuthenticationResource.java index b00cf19dd9..150d352219 100644 --- a/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AuthenticationResource.java +++ b/scm-webapp/src/main/java/sonia/scm/api/rest/resources/AuthenticationResource.java @@ -56,7 +56,7 @@ import sonia.scm.ScmState; import sonia.scm.config.ScmConfiguration; import sonia.scm.group.GroupNames; import sonia.scm.repository.RepositoryManager; -import sonia.scm.security.ScmAuthenticationToken; +import sonia.scm.security.Tokens; import sonia.scm.user.User; import sonia.scm.user.UserManager; @@ -138,7 +138,6 @@ public class AuthenticationResource @Path("login") @TypeHint(ScmState.class) public ScmState authenticate(@Context HttpServletRequest request, - @Context HttpServletResponse response, @FormParam("username") String username, @FormParam("password") String password) { @@ -148,7 +147,7 @@ public class AuthenticationResource try { - subject.login(new ScmAuthenticationToken(request, response, username, + subject.login(Tokens.createAuthenticationToken(request, username, password)); state = createState(subject); } diff --git a/scm-webapp/src/main/java/sonia/scm/security/ScmRealm.java b/scm-webapp/src/main/java/sonia/scm/security/ScmRealm.java index 479087d432..80e9b694b3 100644 --- a/scm-webapp/src/main/java/sonia/scm/security/ScmRealm.java +++ b/scm-webapp/src/main/java/sonia/scm/security/ScmRealm.java @@ -39,6 +39,7 @@ import com.google.common.base.Joiner; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.google.inject.Inject; +import com.google.inject.Provider; import com.google.inject.Singleton; import org.apache.shiro.authc.AccountException; @@ -48,6 +49,7 @@ import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.DisabledAccountException; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authc.UnknownAccountException; +import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.authc.pam.UnsupportedTokenException; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; @@ -91,6 +93,7 @@ import java.util.List; import java.util.Set; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; /** * @@ -130,12 +133,16 @@ public class ScmRealm extends AuthorizingRealm * @param repositoryDAO * @param userDAO * @param authenticator + * @param requestProvider + * @param responseProvider */ @Inject public ScmRealm(ScmConfiguration configuration, CacheManager cacheManager, UserManager userManager, GroupManager groupManager, RepositoryManager repositoryManager, RepositoryDAO repositoryDAO, - UserDAO userDAO, AuthenticationManager authenticator) + UserDAO userDAO, AuthenticationManager authenticator, + Provider requestProvider, + Provider responseProvider) { this.configuration = configuration; this.userManager = userManager; @@ -143,13 +150,15 @@ public class ScmRealm extends AuthorizingRealm this.repositoryDAO = repositoryDAO; this.userDAO = userDAO; this.authenticator = authenticator; + this.requestProvider = requestProvider; + this.responseProvider = responseProvider; // init cache this.cache = cacheManager.getCache(String.class, AuthorizationInfo.class, CACHE_NAME); // set token class - setAuthenticationTokenClass(ScmAuthenticationToken.class); + setAuthenticationTokenClass(UsernamePasswordToken.class); // use own custom caching setCachingEnabled(false); @@ -229,17 +238,17 @@ public class ScmRealm extends AuthorizingRealm AuthenticationToken authToken) throws AuthenticationException { - if (!(authToken instanceof ScmAuthenticationToken)) + if (!(authToken instanceof UsernamePasswordToken)) { throw new UnsupportedTokenException("ScmAuthenticationToken is required"); } - ScmAuthenticationToken token = (ScmAuthenticationToken) authToken; + UsernamePasswordToken token = (UsernamePasswordToken) authToken; AuthenticationInfo info = null; AuthenticationResult result = - authenticator.authenticate(token.getRequest(), token.getResponse(), - token.getUsername(), token.getPassword()); + authenticator.authenticate(requestProvider.get(), responseProvider.get(), + token.getUsername(), new String(token.getPassword())); if ((result != null) && (AuthenticationState.SUCCESS == result.getState())) { @@ -549,11 +558,11 @@ public class ScmRealm extends AuthorizingRealm * @return */ private AuthenticationInfo createAuthenticationInfo( - ScmAuthenticationToken token, AuthenticationResult result) + UsernamePasswordToken token, AuthenticationResult result) { User user = result.getUser(); - Collection groups = authenticate(token.getRequest(), - token.getPassword(), result); + Collection groups = authenticate(requestProvider.get(), + new String(token.getPassword()), result); SimplePrincipalCollection collection = new SimplePrincipalCollection(); @@ -754,6 +763,12 @@ public class ScmRealm extends AuthorizingRealm /** Field description */ private RepositoryDAO repositoryDAO; + /** Field description */ + private Provider requestProvider; + + /** Field description */ + private Provider responseProvider; + /** Field description */ private UserDAO userDAO; diff --git a/scm-webapp/src/main/java/sonia/scm/web/security/BasicSecurityContext.java b/scm-webapp/src/main/java/sonia/scm/web/security/BasicSecurityContext.java index 96192230a6..1cd5d645cd 100644 --- a/scm-webapp/src/main/java/sonia/scm/web/security/BasicSecurityContext.java +++ b/scm-webapp/src/main/java/sonia/scm/web/security/BasicSecurityContext.java @@ -46,7 +46,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import sonia.scm.config.ScmConfiguration; -import sonia.scm.security.ScmAuthenticationToken; +import sonia.scm.group.GroupNames; +import sonia.scm.security.Tokens; import sonia.scm.user.User; import sonia.scm.user.UserManager; @@ -58,7 +59,6 @@ import java.util.Collections; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; -import sonia.scm.group.GroupNames; /** * @@ -118,7 +118,7 @@ public class BasicSecurityContext implements WebSecurityContext Subject subject = SecurityUtils.getSubject(); - subject.login(new ScmAuthenticationToken(request, response, username, + subject.login(Tokens.createAuthenticationToken(request, username, password)); user = subject.getPrincipals().oneByType(User.class); @@ -166,7 +166,6 @@ public class BasicSecurityContext implements WebSecurityContext @Override public Collection getGroups() { - Subject subject = SecurityUtils.getSubject(); GroupNames groups = getPrincipal(GroupNames.class); Collection groupCollection = null;