提交 d51ffaba 编写于 作者: N Nicolas De Loof

Revert "Improved the mechanism of how we store passwords hashed."

This reverts commit ebc6af72.
上级 e14a9a91
......@@ -85,9 +85,6 @@ Upcoming changes</a>
<li class=bug>
Fixed: XML API Logs Too Much Information When Invalid Char is Present
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-13378">issue 13378</a>)
<li class=rfe>
Improved the way we store hashed passwords.
(<a href="http://blog.linkedin.com/2012/06/06/linkedin-member-passwords-compromised/">motivation</a>)
<li class=rfe>
Reduce the total height of items shown in the view configuration page.
(<a href="https://github.com/jenkinsci/jenkins/pull/488">pull 488</a>)
......
......@@ -579,13 +579,6 @@ THE SOFTWARE.
<artifactId>owasp-html-sanitizer</artifactId>
<version>r88</version>
</dependency>
<dependency>
<groupId>org.mindrot</groupId>
<artifactId>jbcrypt</artifactId>
<version>0.3m</version>
</dependency>
<!-- offline profiler API to put in the classpath if we need it -->
<!--dependency>
<groupId>com.yourkit.api</groupId>
......
......@@ -59,7 +59,6 @@ import org.kohsuke.stapler.HttpResponses;
import org.kohsuke.stapler.Stapler;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import org.mindrot.jbcrypt.BCrypt;
import org.springframework.dao.DataAccessException;
import javax.servlet.Filter;
......@@ -169,7 +168,7 @@ public class HudsonPrivateSecurityRealm extends AbstractPasswordBasedSecurityRea
@Override
protected Details authenticate(String username, String password) throws AuthenticationException {
Details u = loadUserByUsername(username);
if (!u.isPasswordCorrect(password))
if (!PASSWORD_ENCODER.isPasswordValid(u.getPassword(),password,null))
throw new BadCredentialsException("Failed to login as "+username);
return u;
}
......@@ -450,10 +449,6 @@ public class HudsonPrivateSecurityRealm extends AbstractPasswordBasedSecurityRea
return passwordHash;
}
public boolean isPasswordCorrect(String candidate) {
return PASSWORD_ENCODER.isPasswordValid(getPassword(),candidate,null);
}
public String getProtectedPassword() {
// put session Id in it to prevent a replay attack.
return Protector.protect(Stapler.getCurrentRequest().getSession().getId()+':'+getPassword());
......@@ -574,7 +569,7 @@ public class HudsonPrivateSecurityRealm extends AbstractPasswordBasedSecurityRea
* This abbreviates the need to store the salt separately, which in turn allows us to hide the salt handling
* in this little class. The rest of the Acegi thinks that we are not using salt.
*/
/*package*/ static final PasswordEncoder CLASSIC = new PasswordEncoder() {
public static final PasswordEncoder PASSWORD_ENCODER = new PasswordEncoder() {
private final PasswordEncoder passwordEncoder = new ShaPasswordEncoder(256);
public String encodePassword(String rawPass, Object _) throws DataAccessException {
......@@ -613,44 +608,6 @@ public class HudsonPrivateSecurityRealm extends AbstractPasswordBasedSecurityRea
}
};
/**
* {@link PasswordEncoder} that uses jBCrypt.
*/
private static final PasswordEncoder JBCRYPT_ENCODER = new PasswordEncoder() {
public String encodePassword(String rawPass, Object _) throws DataAccessException {
return BCrypt.hashpw(rawPass,BCrypt.gensalt());
}
public boolean isPasswordValid(String encPass, String rawPass, Object _) throws DataAccessException {
return BCrypt.checkpw(rawPass,encPass);
}
};
/**
* Combines {@link #JBCRYPT_ENCODER} and {@link #CLASSIC} into one so that we can continue
* to accept {@link #CLASSIC} format but new encoding will always done via {@link #JBCRYPT_ENCODER}.
*/
public static final PasswordEncoder PASSWORD_ENCODER = new PasswordEncoder() {
/*
CLASSIC encoder outputs "salt:hash" where salt is [a-z]+, so we use unique prefix '#jbcyrpt"
to designate JBCRYPT-format hash.
'#' is neither in base64 nor hex, which makes it a good choice.
*/
public String encodePassword(String rawPass, Object salt) throws DataAccessException {
return JBCRYPT_HEADER+JBCRYPT_ENCODER.encodePassword(rawPass,salt);
}
public boolean isPasswordValid(String encPass, String rawPass, Object salt) throws DataAccessException {
if (encPass.startsWith(JBCRYPT_HEADER))
return JBCRYPT_ENCODER.isPasswordValid(encPass.substring(JBCRYPT_HEADER.length()),rawPass,salt);
else
return CLASSIC.isPasswordValid(encPass,rawPass,salt);
}
private static final String JBCRYPT_HEADER = "#jbcrypt:";
};
@Extension
public static final class DescriptorImpl extends Descriptor<SecurityRealm> {
public String getDisplayName() {
......
......@@ -2,13 +2,10 @@ package hudson.security;
import org.jvnet.hudson.test.Bug;
import org.jvnet.hudson.test.HudsonTestCase;
import org.jvnet.hudson.test.WithoutJenkins;
import org.jvnet.hudson.test.recipes.LocalData;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import static hudson.security.HudsonPrivateSecurityRealm.*;
/**
* @author Kohsuke Kawaguchi
*/
......@@ -38,15 +35,4 @@ public class HudsonPrivateSecurityRealmTest extends HudsonTestCase {
// verify that we can still login
new WebClient().login("alice", "alice");
}
@WithoutJenkins
public void testHashCompatibility() {
String old = CLASSIC.encodePassword("hello world", null);
assertTrue(PASSWORD_ENCODER.isPasswordValid(old,"hello world",null));
String secure = PASSWORD_ENCODER.encodePassword("hello world", null);
assertTrue(PASSWORD_ENCODER.isPasswordValid(old,"hello world",null));
assertTrue(!secure.equals(old));
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册