如何在没有密码编码的情况下使用 Spring 安全性?
Posted
技术标签:
【中文标题】如何在没有密码编码的情况下使用 Spring 安全性?【英文标题】:How to use Spring security without password encoding? 【发布时间】:2018-12-14 22:42:55 【问题描述】:我目前正在尝试学习 Spring 安全性。我使用 BCryptPasswordEncoder
在持久化到数据库之前对用户密码进行编码
代码:
@Override
public void saveUser(User user)
user.setPassword(bCryptPasswordEncoder.encode(user.getPassword()));
user.setActive(1);
Role userRole = roleRepository.findByRole("ADMIN");
user.setRoles(new HashSet<Role>(Arrays.asList(userRole)));
userRepository.save(user);
然后在身份验证期间也使用它,并且用户按预期获得了身份验证。
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception
auth.
jdbcAuthentication()
.usersByUsernameQuery(usersQuery)
.authoritiesByUsernameQuery(rolesQuery)
.dataSource(dataSource).passwordEncoder(bCryptPasswordEncoder);
然后我从configure()
方法中删除了.passwordEncoder(bCryptPasswordEncoder);
,仍然具有编码密码的用户成功通过身份验证。
然后我从saveUser()
和configure()
方法中删除了密码编码器,并将User
持久化到数据库中(即没有密码编码)并尝试访问经过身份验证的页面,但我得到了AccessedDeniedException
, 但是,即使我从 configure()
方法中删除了 passwordEncoder()
,具有编码密码的用户仍然可以通过身份验证。为什么会这样?
Spring Security 在身份验证期间是否默认使用密码编码器?
如果是这样如何在没有密码编码的情况下使用spring security?
【问题讨论】:
你创建了 BCryptPasswordEncoder bean 吗? @efex09 是的,它与编码密码完美配合,但如果我不使用密码编码,则身份验证失败 为什么我的问题被否决了? 不幸的是,许多投反对票的人懒得解释为什么他们认为这个问题不好。我们可能永远不会知道。 默认启用哪个。实际上,它具有更好的安全性方案,因为您可以在密码中指定要使用的编码(我相信它默认为 Bcrypt)。因此,如果您有一个纯密码前缀noop<the-password>
,它将使用纯编码器。使用 bcrypt
作为 crypt 的前缀(这也是默认值)。见docs.spring.io/spring-security/site/docs/current/reference/…
【参考方案1】:
也许你可以实现这个简单的代码来规避 Spring Encoder
public class PasswordEnconderTest implements PasswordEncoder
@Override
public String encode(CharSequence charSequence)
return charSequence.toString();
@Override
public boolean matches(CharSequence charSequence, String s)
return charSequence.toString().equals(s);
并添加您的 WebSecurityConfig:
@Bean
public PasswordEncoder passwordEncoder()
return new PasswordEnconderTest();
不推荐,但可以实现
【讨论】:
【参考方案2】:使用 Spring Security 5 对密码的加密始终处于启用状态。默认使用的加密是bcrypt
。 Spring Security 5 的巧妙之处在于它实际上允许您在密码中指定用于创建 has 的加密。
为此,请参阅 Spring Security 参考指南中的 Password Storage Format。简而言之,它允许您为算法的众所周知的密钥添加密码前缀。存储格式为<encryption><your-password-hash>
。
不使用任何内容时,它将变为 noopyour-password
(使用 NoOpPasswordEncoder
和 bcrypt$a2......
将使用 BcryptPasswordEncoder
。有多种开箱即用的算法支持,但您也可以定义您的拥有。
要定义您自己的,请创建您自己的PasswordEncoder
并将其注册到带有DelegatingPasswordEncoder
的密钥下。
【讨论】:
您介意将“加密”替换为“哈希”或“编码”或类似的东西吗?这不是加密。 @M. Deinum 在我的应用程序中,管理员需要登录用户帐户并且管理员具有编码密码。那么有没有办法让管理员在登录时绕过此密码编码?请帮助我。即,在我的应用程序中有两种登录方式一个由用户通常通过明文密码发生,该密码在 Spring Boot 中使用密码编码,另一个由管理员使用哈希密码由管理员使用,并且需要绕过 Spring Boot 密码编码。我正在使用 BCryptEncoder。 【参考方案3】:不确定它是否是您所追求的,但我使用了一个便宜的解决方法,所以我不必担心编码我的数据库
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter
@Autowired
DataSource dataSource;
@Autowired
public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery("select username,CONCAT('noop',password),true from
public.\"Users\" where username=?")
.authoritiesByUsernameQuery("select username,role from public.\"Users\" where
username=?");
...
请注意,我先将其与 noop 连接,而不是获取密码,以告诉系统不要使用编码。
可能是一种罪过,但它现在有效。
【讨论】:
【参考方案4】:你试过了吗
@Bean
public static NoOpPasswordEncoder passwordEncoder()
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
然后在配置全局安全
@Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception
auth.jdbcAuthentication().usersByUsernameQuery(usersQuery).dataSource(dataSource)
.authoritiesByUsernameQuery(rolesQuery).passwordEncoder(passwordEncoder());
【讨论】:
以上是关于如何在没有密码编码的情况下使用 Spring 安全性?的主要内容,如果未能解决你的问题,请参考以下文章
是否可以在没有密码的情况下使用 Spring SecurityConfiguration HttpSecurity 登录?
使用Spring Security为实时Grails应用程序增加BCrypt logrounds而不重新编码所有密码是否安全?
如何在没有弹簧安全的情况下使用 api 密钥保护 rest api