我遇到密码散列问题。我想使用salt和1024次迭代来使用sha-256来使用Spring Security对我的用户进行身份验证。但不知何故,我在数据库中的密码与用户输入的密码不匹配。
这是我的代码:
安全-context.xml中
<beans:bean
id="passwordEncoder"
class="org.springframework.security.authentication.encoding.ShaPasswordEncoder" >
<beans:constructor-arg value="256" />
<beans:property
name="iterations"
value="1024" />
</beans:bean>
<beans:bean class="org.springframework.security.authentication.dao.ReflectionSaltSource" id="saltSource">
<beans:property name="userPropertyToUse" value="id"/>
</beans:bean>
<authentication-manager>
<authentication-provider user-service-ref="userLoginDetails" >
<password-encoder ref="passwordEncoder" >
<salt-source ref="saltSource"/>
</password-encoder>
</authentication-provider>
</authentication-manager>
userLoginDetails
@Transactional(readOnly = true)
public class UserLoginDetails implements UserDetailsService {
private EregDaoFactory daoFactory;
@Autowired
public void setDaoFactory(EregDaoFactory daoFactory) {
this.daoFactory = daoFactory;
}
/**
* Retrieves a user record containing the user's credentials and access.
*/
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException,
DataAccessException {
Logger logger = Logger.getLogger(getClass());
logger.setLevel(Level.ALL);
int userId = Integer.parseInt(username);
UzytkownikDao dao = daoFactory.getUzytkownikDao();
LoggedUser user = null;
Uzytkownik dbUser = null;
try {
dbUser = (Uzytkownik) dao.findById(Integer.parseInt(username));
List<SimpleGrantedAuthority> grants = new ArrayList<SimpleGrantedAuthority>();
Collection<Object> userNames = new ArrayList<Object>();
if (dbUser.getRola() == 'U') {
grants.add(new SimpleGrantedAuthority("ROLE_STUDENT"));
userNames = daoFactory.getUczenDao().getNameAndLastName(userId);
} else if (dbUser.getRola() == 'N') {
grants.add(new SimpleGrantedAuthority("ROLE_TEACHER"));
userNames = daoFactory.getNauczycielDao().getNameAndLastName(userId);
} else if (dbUser.getRola() == 'O') {
grants.add(new SimpleGrantedAuthority("ROLE_PARENT"));
userNames = daoFactory.getOpiekunDao().getNameAndLastName(userId);
}
grants.add(new SimpleGrantedAuthority("ROLE_USER"));
Object[] names = userNames.toArray();
user =
new LoggedUser(username, dbUser.getHaslo(), true, true, true, true, grants,
(String) names[0], (String) names[1], dbUser.getRola());
} catch (Exception e) {
logger.error(e.getLocalizedMessage());
throw new UsernameNotFoundException("Error in retrieving user");
}
return user;
}
}
LoggedUser
package ereg.security.userdetails;
public class LoggedUser extends User {
private static final long serialVersionUID = 1L;
private final String id;
private final String imie;
private final String nazwisko;
private final char rola;
private Date lastSuccessfulLogin;
private String lastKnowIpAddress;
public LoggedUser(String username, String password, boolean enabled, boolean accountNonExpired,
boolean credentialsNonExpired, boolean accountNonLocked,
Collection<? extends GrantedAuthority> authorities, String name, String lastName, char rola) {
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked,
authorities);
this.imie = name;
this.nazwisko = lastName;
this.rola = rola;
this.id = username;
}
public String getId() {
return id;
}
public String getImie() {
return imie;
}
public String getNazwisko() {
return nazwisko;
}
public char getRola() {
return rola;
}
public Date getLastSuccessfulLogin() {
return lastSuccessfulLogin;
}
public String getFormattedDate() {
if (lastSuccessfulLogin != null) {
return new SimpleDateFormat("dd/MM/yyyy, HH:mm:ss").format(lastSuccessfulLogin);
} else
return null;
}
public String getLastKnowIpAddress() {
return lastKnowIpAddress;
}
public void setLastSuccessfulLogin(Date lastSuccessfulLogin) {
this.lastSuccessfulLogin = lastSuccessfulLogin;
}
public void setLastKnowIpAddress(String lastKnowIpAddress) {
this.lastKnowIpAddress = lastKnowIpAddress;
}
}
这是哈希密码的程序:
EncryptAllUsersPasswords
private void encryptPasswords() throws Exception {
OneWayEncryptor encryptor = OneWayEncryptor.getInstance();
appContext =
new FileSystemXmlApplicationContext(
"C:/EclipseWorkSpace/myereg/WebContent/WEB-INF/applicationContext.xml");
ds = (DataSource) appContext.getBean("dataSource");
JdbcTemplate jdbc = new JdbcTemplate(ds);
BigDecimal userId = null;
String password = "";
String encrypted = "";
Map<?, ?> row = new HashMap<Object, Object>();
for (Iterator<?> it = jdbc.queryForList("SELECT id, haslo FROM UZYTKOWNIK").iterator(); it.hasNext();) {
row = (Map<?, ?>) it.next();
userId = (BigDecimal) row.get("ID");
password = (String) row.get("HASLO");
encrypted = encryptor.encrypt(password, userId.toString());
System.out.println(userId.toString());
jdbc.execute("UPDATE UZYTKOWNIK SET haslo = '" + encrypted + "' WHERE id = " + userId);
}
}
public static void main(String[] args) {
EncryptAllUserPasswords encrypt = new EncryptAllUserPasswords();
try {
encrypt.encryptPasswords();
} catch (Exception e) {
e.printStackTrace();
}
}
OneWayEncryptor
public final class OneWayEncryptor {
private static final OneWayEncryptor INSTANCE = new OneWayEncryptor();
private static final int ITERATIONS = 1024;
private static final String ALGORITHM = "SHA-256";
private OneWayEncryptor() {
}
public static OneWayEncryptor getInstance() {
return INSTANCE;
}
public String encrypt(String plaintext, String salt) throws NoSuchAlgorithmException,
UnsupportedEncodingException {
MessageDigest messageDigest = MessageDigest.getInstance(ALGORITHM);
messageDigest.reset();
messageDigest.update(salt.getBytes());
byte[] btPass = messageDigest.digest(plaintext.getBytes("UTF-8"));
for (int i = 0; i < ITERATIONS; i++) {
messageDigest.reset();
btPass = messageDigest.digest(btPass);
}
String encodedPassword = byteToBase64(btPass);
return encodedPassword;
}
private String byteToBase64(byte[] bt) throws UnsupportedEncodingException {
return new String(Base64.encodeBase64(bt));
}
}
我认为问题出在最后一个......请帮忙
答案 0 :(得分:2)
实际上,这有效:
public String encrypt(String plaintext, String salt) throws NoSuchAlgorithmException,
UnsupportedEncodingException {
String pass = plaintext + "{" + salt + "}";
MessageDigest messageDigest = MessageDigest.getInstance(ALGORITHM);
messageDigest.reset();
byte[] btPass = messageDigest.digest(pass.getBytes("UTF-8"));
for (int i = 0; i < ITERATIONS - 1; i++) {
messageDigest.reset();
btPass = messageDigest.digest(btPass);
}
String hashedPass = new BigInteger(1, btPass).toString(16);
if (hashedPass.length() < 32) {
hashedPass = "0" + hashedPass;
}
return hashedPass;
}
有人可以告诉我为什么吗?我的意思是为什么当我尝试使用更新(盐)方法时,它确实并且当我切换到连接字符串时它做了。并且我不介意使用“{salt}”,因为这只允许我生成与spring完全相同的哈希。事情就是在它生成错误的哈希之前,即使给定的盐。我用sha256发电机检查了它。有人可以告诉我为什么它在字符串连接后开始工作了吗?