Spring Security:DB 和 applicationContext 中的密码编码
Posted
技术标签:
【中文标题】Spring Security:DB 和 applicationContext 中的密码编码【英文标题】:Spring Security:password encoding in DB and in applicationContext 【发布时间】:2012-01-21 05:13:08 【问题描述】:有配置(applicationContext-security.xml):
<authentication-manager alias="authenticationManager">
<authentication-provider>
<password-encoder hash="sha"/>
<jdbc-user-service data-source-ref="dataSource"/>
</authentication-provider>
</authentication-manager>
从另一边有我的dataSource
(它是JdbcDaoImpl)的SQL:
...
public static final String DEF_USERS_BY_USERNAME_QUERY =
"select username,password,enabled " +
"from users " +
"where username = ?";
...
此代码中现在有关于sha
的字样,因此从标准 Spring Security users
表中选择的密码未编码。
也许,我应该在我的休眠映射配置中为password
列提供一些sha
属性:
<class name="model.UserDetails" table="users">
<id name="id">
<generator class="increment"/>
</id>
<property name="username" column="username"/>
<property name="password" column="password"/>
<property name="enabled" column="enabled"/>
<property name="mail" column="mail"/>
<property name="city" column="city"/>
<property name="confirmed" column="confirmed"/>
<property name="confirmationCode" column="confirmation_code"/>
<set name="authorities" cascade="all" inverse="true">
<key column="id" not-null="true"/>
<one-to-many class="model.Authority"/>
</set>
</class>
现在密码按原样保存到数据库,但应该进行编码。
如何将好友applicationContext
config 和 DB 查询设为相同的密码编码?
【问题讨论】:
【参考方案1】:如果您自己选择散列系统,而不是使用已经包含散列密码的现有数据库构建应用程序,那么您应该确保您的散列算法也使用盐。不要只使用简单的摘要。
一个不错的选择是 bcrypt,我们现在通过 BCryptPasswordEncoder
(使用 jBCrypt 实现)在 Spring Security 3.1 中直接支持它。这会自动生成一个盐并将其与单个字符串中的哈希值连接起来。
一些数据库内置了对散列的支持(例如Postgres)。否则,您需要在将密码传递给 JDBC 之前自己对密码进行哈希处理:
String password = "plaintextPassword";
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String hashedPassword = passwordEncoder.encode(password);
这就是您在创建用户时对密码进行编码所需要做的一切。
对于身份验证,您可以使用以下内容:
<bean id="encoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
<bean id="authProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<property name="userDetailsService" ref="yourJdbcUserService" />
<property name="passwordEncoder" ref="encoder" />
</bean>
【讨论】:
关于盐,我知道,这是我安全挑战的下一阶段)) 如果您使用 bcrypt 之类的东西,它会自动为您处理,因此没有任何挑战 :-)。您不必自己处理盐。 @LukeTaylor 你能展示一下它是如何在 applicationContext-security.xml 中配置的吗? 我想知道 BCryptPasswordEncoder 是如何工作的。它是为所有密码生成一个盐还是为每个密码生成一个单独的盐?如果是这样,它将用户盐存储在哪里? BCrypt 不是加密算法,盐存储在同一个字符串中。也许Wikipedia article on Bcrypt 会有所帮助。【参考方案2】:关于接受的答案的更多解释。希望它可以帮助某人。
在将密码放入数据库之前自己对密码进行哈希处理:
String password = "plaintextPassword";
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String hashedPassword = passwordEncoder.encode(password);
将 BCryptPasswordEncoder bean 添加到您的 security-config.xml
将 passwordEncoder 作为属性添加到 Authentication Provider 类。自动装配它或提供 setter 和 getter 方法。
@AutoWired
private BCryptPasswordEncoder passwordEncoder;
在验证用户登录时获取属性
<bean id="dbAuthenticationProvider" class="mypackage.auth.spring.DBAuthenticationProvider" >
<property name="dataSource" ref="routingDataSource"></property>
<property name="passwordEncoder" ref="encoder" />
<property name="passwordQuery"
value="select password as password from tbl where username=:username">
</property>
</bean>
并且在认证类中匹配两个密码
new BCryptPasswordEncoder().matches(plainTextPasswdFromUserInput, hashedPasswdFromDb)
【讨论】:
matches 方法是我正在寻找的。span> 【参考方案3】:你可以用一种简单的方式在 applicationContext-security.xml 中做类似的事情
<authentication-manager alias="authenticationManager">
<authentication-provider>
<password-encoder ref="encoder"/>
<jdbc-user-service data-source-ref="dataSource"
users-by-username-query="
select username,password, enabled
from principal where username=?"
authorities-by-username-query="
select p.username, a.authority from principal p, authority a
where p.id = a.principal_id and p.username=?"
/>
</authentication-provider>
</authentication-manager>
<beans:bean id="encoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
在 Java 中
public static String encodePasswordWithBCrypt(String plainPassword)
return new BCryptPasswordEncoder().encode(plainPassword);
然后测试一下
System.out.println(encodePasswordWithBCrypt("fsdfd"));
【讨论】:
【参考方案4】:使用 Spring Security 3.1,试试这个:
<authentication-manager alias="authenticationManager">
<authentication-provider user-service-ref="service">
<password-encoder hash="sha"/>
<jdbc-user-service data-source-ref="dataSource"/>
</authentication-provider>
</authentication-manager>
<beans:bean id="dataSource" ...>
...
</beans:bean>
<beans:bean id="service" class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">
<beans:property name="dataSource" ref="dataSource"/>
...
</beans:bean>
新增功能:authentication-provider
指向 service
和 service
指向 datasource
。
编辑:在 Java 中,您必须使用以下代码对密码进行编码:
DigestUtils.sha(request.getParameter("password"));
警告:小心!不要将 SHA 与 MD5 混用!
如果将authentication-provider
的password-encoder
设置为SHA,则需要在Java 中以相同的方式进行编码以保持一致。但是,如果您在 Java 中编码为 MD5,就像您找到的示例一样,请不要忘记将 hash 设置为“md5”。 DigestUtils还提供md5编码器:
DigestUtils.md5(request.getParameter("password"));
【讨论】:
是的,我知道,但你没有问我的问题如何提供,用户密码已编码保存到数据库 好吧,我不知道你说的提供是什么意思,但为了坚持,我使用了DigestUtils。 @sergionni:抱歉,但我不知道 applicationContext 的配置来自动保存编码的密码,正如我所说,我使用了来自 Apache commons 的 DigestUtils。 谢谢您的指点,从来没有听说过摘要。那么,我应该提供摘要以便加密我的密码吗?这个例子:static.springsource.org/spring-security/site/docs/3.0.x/… 啊哈,看来我明白了,我应该在 Java DAO 类中编码我的密码,当我坚持我的UserDetails
实体时,如下:MessageDigest messageDigest = MessageDigest.getInstance("MD5"); ...
这里是完整的解释:***.com/questions/1821082/spring-security-encypt-md5【参考方案5】:
只是使用注释的提示
@Configuration
@EnableWebSecurity
@PropertySource("classpath://configs.properties")
public class SecurityContextConfig extends WebSecurityConfigurerAdapter
@Autowired
@Qualifier("userDetailsService")
private UserDetailsService userDetailsService;
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
auth.userDetailsService(userDetailsService).passwordEncoder(getPasswordEncoder());
@Bean(name = "passwordEncoder")
public PasswordEncoder getPasswordEncoder()
return new BCryptPasswordEncoder();
【讨论】:
【参考方案6】:接受的答案是正确的。 我用 spring 3.1 和 BCrypt 编码算法对其进行了测试。
创建用户时。
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
userEntity.setPassword(passwordEncoder.encode(userEntity.getPassword()));
userDao.save(userEntity);
当用户登录时,请记住,使用纯密码(未散列)。就像:
Authentication request = new UsernamePasswordAuthenticationToken(user.getUserName(), user.getPassword());
Authentication result = authenticationManager.authenticate(request);
SecurityContextHolder.getContext().setAuthentication(result);
这里是安全配置:
<bean id="encoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
<bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
<property name="userDetailsService" ref="userService" />
<property name="hideUserNotFoundExceptions" value="false" />
<property name="passwordEncoder" ref="encoder" />
</bean>
希望它对某人有所帮助!
【讨论】:
【参考方案7】:对于 3.1.x,此映射不适用于身份验证。 工作方式是:
<beans:bean id='bCryptPasswordEncoder' class='org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder'></beans:bean>
<authentication-manager>
<authentication-provider user-service-ref="userDetailsService">
<password-encoder ref="bCryptPasswordEncoder"/>
</authentication-provider>
</authentication-manager>
【讨论】:
以上是关于Spring Security:DB 和 applicationContext 中的密码编码的主要内容,如果未能解决你的问题,请参考以下文章
带有休眠和散列密码的 Spring Security DB 身份验证?
添加了 Spring Security CORS 过滤器 - 从 DB 检索的日期显示在数值中
添加了 Spring Security CORS 过滤器 - 从 DB 检索的日期显示在数值中
spring-boot Actuator 连同 Spring Security 和 Form Basic Auth