我正在学习将oauth2集成到我们的spring boot项目中,以保护我们的API。因此,我从一个可以正常工作的spring-security-oauth2-boot读取基本示例开始,然后当我尝试修改密码编码器以使用无法验证的任何编码器时。
这是我的AuthorizationServerConfiguration:
body {
font-family: Helvetica, FreeSans, sans-serif;
background-image: url('./assets/images/background.jpg');
}
section {
margin-top: 2em;
}
.row {
margin-bottom: 1rem;
}
mat-form-field {
color: @inputfield-text-color;
width: 95%;
margin-bottom: .5em;
.mat-input-element {
background-color: @inputfield-background-color;
border-radius: .3em;
padding: 1em 0.6em 0.2em 0.6em;
line-height: 1.7em;
&:disabled {
background-color: @inputfield-disabled-color;
color: dimgrey;
}
}
.mat-form-field-label-wrapper {
left: 0.6em;
top: 0.3em;
font-size: .8em;
}
}
// here I tried to fix it, but it had no effect:
.input-tooltip-icon {
position: absolute;
z-index: 1;
top: .3em;
right: -.50em;
cursor: context-menu;
color: @button-color;
}
当我使用@Component
@EnableResourceServer
@EnableAuthorizationServer
class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
AuthenticationManager authenticationManager
AuthorizationServerConfiguration(AuthenticationConfiguration authenticationConfiguration) throws Exception {
this.authenticationManager = authenticationConfiguration.getAuthenticationManager()
}
@Override
void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("myclient")
//.secret("{noop}password") <-- this works
.secret("{pbkdf2}5d923b44a6d129f3ddf3e3c8d29412723dcbde72445e8ef6bf3b508fbf17fa4ed4d6b99ca763d8dc")
.authorizedGrantTypes("client_credentials")
.scopes("all")
.accessTokenValiditySeconds(3600)
}
@Override
void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager)
}
}
时,我可以使用curl成功地进行身份验证:
{noop}password
但是,当我打开任何哈希时,我将无法进行身份验证。我尝试过这种方式来验证卷毛,但没有运气:
$ curl myclient:password@localhost:8080/oauth/token?scope=all -d grant_type=client_credentials
{"access_token":"4320fa79-38c2-45b1-a788-5ea1b5ce881a","token_type":"bearer","expires_in":3599,"scope":"all"}
我还将该代码段添加到代码中以生成用于再次检查的密码,这给了我一个不同的哈希值,也对curl进行了测试,也没有运气:
$ curl congero:5d923b44a6d129f3ddf3e3c8d29412723dcbde72445e8ef6bf3b508fbf17fa4ed4d6b99ca763d8dc@localhost:8080/oauth/token?scope=all -d grant_type=client_credentials
{"error":"unauthorized","error_description":"Full authentication is required to access this resource"}
$ curl congero:{pbkdf2}5d923b44a6d129f3ddf3e3c8d29412723dcbde72445e8ef6bf3b508fbf17fa4ed4d6b99ca763d8dc@localhost:8080/oauth/token?scope=all -d grant_type=client_credentials
{"error":"unauthorized","error_description":"Full authentication is required to access this resource"}
我已经调试了spring源代码,发现在密码编码器(Pbkdf2PasswordEncoder以及BcryptPasswordEncoder)中,该密码正通过以下方法解码:
PasswordEncoder passwordEncoder = new Pbkdf2PasswordEncoder()
String encoded = passwordEncoder.encode('password')
println "PASSWORD: $encoded"
$ curl congero:91d1ee4784686a2e2a39c214f5a4b3ebb41e1206e2d1fc770d3ff146b034f8c156ea279c73aa1629@localhost:8080/oauth/token?scope=all -d grant_type=client_credentials
{"error":"unauthorized","error_description":"Full authentication is required to access this resource"}
$ curl congero:{pbkdf2}91d1ee4784686a2e2a39c214f5a4b3ebb41e1206e2d1fc770d3ff146b034f8c156ea279c73aa1629@localhost:8080/oauth/token?scope=all -d grant_type=client_credentials
{"error":"unauthorized","error_description":"Full authentication is required to access this resource"}
此private byte[] decode(String encodedBytes) {
if(this.encodeHashAsBase64) {
return Base64.getDecoder().decode(encodedBytes);
}
return Hex.decode(encodedBytes);
}
看起来是导致密码不匹配的罪魁祸首,这在使用Hex.decode
时不会发生。
你知道我在做什么错吗?我错过任何重要的步骤吗?该文档对我来说还不清楚,因为它没有显示如何逐步自定义配置。
答案 0 :(得分:0)
启用散列时,并不意味着您需要在curl命令中传递编码后的密码,只需传递“ password
”,spring就会对其进行编码并与之比较
"{pbkdf2}5d923b44a6d129f3ddf3e3c8d29412723dcbde72445e8ef6bf3b508fbf17fa4ed4d6b99ca763d8dc"
您需要具有类型Pbkdf2PasswordEncoder
的bean,以便spring在散列和比较期间使用
答案 1 :(得分:0)
您可以使用DelegatingPasswordEncoder
一个密码编码器,它委派给另一个基于 加上前缀标识符。
密码存储格式
密码的一般格式为:
{id}encodedPassword
例如“ id”是用于查找哪个PasswordEncoder的标识符 应该使用“ encodedPassword”作为原始编码密码 所选的PasswordEncoder。 “ id”必须位于 密码,以“ {”开头,以“}”结尾。如果“ id”不能 找到的“ id”将为空。例如,以下可能是 使用不同“ id”编码的密码列表。全部原版 密码是“密码”。
{bcrypt} $ 2a $ 10 $ dXJ3SW6G7P50lGmMkkmwe.20cQQubK3.HZWzG3YB1tlRy.fqvM / BG
{noop}密码 {pbkdf2} 5d923b44a6d129f3ddf3e3c8d29412723dcbde72445e8ef6bf3b508fbf17fa4ed4d6b99ca763d8dc
对于我们上面构建的DelegatingPasswordEncoder:
BCryptPasswordEncoder
。NoOpPasswordEncoder
。Pbkdf2PasswordEncoder
。根据“ id”和映射完成密码匹配 “ id”代表构造函数中提供的PasswordEncoder。
因此,要使其正常工作,您应该声明一个PasswordEncoder
bean(基本上,您可以毫无问题地在密码编码器之间进行切换,您可以免费获得每个新创建的用户的迁移!):
@Bean
PasswordEncoder passwordEncoder(){
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}