Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
FIY695
jenkins
提交
9bdaf8da
J
jenkins
项目概览
FIY695
/
jenkins
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
jenkins
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
9bdaf8da
编写于
6月 19, 2012
作者:
N
Nicolas De Loof
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Revert "Revert "Improved the mechanism of how we store passwords hashed.""
上级
f52c7f7d
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
69 addition
and
2 deletion
+69
-2
changelog.html
changelog.html
+3
-0
core/pom.xml
core/pom.xml
+7
-0
core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java
...main/java/hudson/security/HudsonPrivateSecurityRealm.java
+45
-2
test/src/test/java/hudson/security/HudsonPrivateSecurityRealmTest.java
.../java/hudson/security/HudsonPrivateSecurityRealmTest.java
+14
-0
未找到文件。
changelog.html
浏览文件 @
9bdaf8da
...
...
@@ -87,6 +87,9 @@ 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>
)
...
...
core/pom.xml
浏览文件 @
9bdaf8da
...
...
@@ -579,6 +579,13 @@ 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>
...
...
core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java
浏览文件 @
9bdaf8da
...
...
@@ -59,6 +59,7 @@ 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
;
...
...
@@ -168,7 +169,7 @@ public class HudsonPrivateSecurityRealm extends AbstractPasswordBasedSecurityRea
@Override
protected
Details
authenticate
(
String
username
,
String
password
)
throws
AuthenticationException
{
Details
u
=
loadUserByUsername
(
username
);
if
(!
PASSWORD_ENCODER
.
isPasswordValid
(
u
.
getPassword
(),
password
,
null
))
if
(!
u
.
isPasswordCorrect
(
password
))
throw
new
BadCredentialsException
(
"Failed to login as "
+
username
);
return
u
;
}
...
...
@@ -449,6 +450,10 @@ 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
());
...
...
@@ -569,7 +574,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.
*/
public
static
final
PasswordEncoder
PASSWORD_ENCODER
=
new
PasswordEncoder
()
{
/*package*/
static
final
PasswordEncoder
CLASSIC
=
new
PasswordEncoder
()
{
private
final
PasswordEncoder
passwordEncoder
=
new
ShaPasswordEncoder
(
256
);
public
String
encodePassword
(
String
rawPass
,
Object
_
)
throws
DataAccessException
{
...
...
@@ -608,6 +613,44 @@ 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
()
{
...
...
test/src/test/java/hudson/security/HudsonPrivateSecurityRealmTest.java
浏览文件 @
9bdaf8da
...
...
@@ -2,10 +2,13 @@ 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
*/
...
...
@@ -35,4 +38,15 @@ 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.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录