2012-12-24 162 views
4

我写了一个带有Field LoginId和Password的实体类。java.lang.ClassCastException:[B不能转换为java.lang.String

Iam使用AES_ENCRYPT加密passwrd并在db中对其进行加密。

我只想检索解密的密码。所以,即时使用AES_DECRYPT在OPen JPA 2.0中使用NAtiveQueryis。

查询我写的是:

Query q = em.createNativeQuery("select AES_DECRYPT(l.password,?2) from loginDetails l where l.loginID = ?1"); 
q.setParameter(1, loginId); 
q.setParameter(2, getKey()); 
String s = q.getSingleResult(); 

但即时得到以下异常:

java.lang.ClassCastException: [B cannot be cast to java.lang.String 
at com.rcs.chef.validation.UserValidation.decryptedPasswordForID(UserValidation.java:99) 
at com.rcs.chef.validation.UserValidation.validateUser(UserValidation.java:81) 
at com.rcs.chef.validation.UserValidation.activate(UserValidation.java:72) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
at java.lang.reflect.Method.invoke(Method.java:597) 
at org.apache.aries.blueprint.utils.ReflectionUtils.invoke(ReflectionUtils.java:226) 
at org.apache.aries.blueprint.container.BeanRecipe.invoke(BeanRecipe.java:824) 
at org.apache.aries.blueprint.container.BeanRecipe.runBeanProcInit(BeanRecipe.java:636) 
at org.apache.aries.blueprint.container.BeanRecipe.internalCreate(BeanRecipe.java:724) 
at org.apache.aries.blueprint.di.AbstractRecipe.create(AbstractRecipe.java:64) 
at org.apache.aries.blueprint.container.BlueprintRepository.createInstances(BlueprintRepository.java:219) 
at org.apache.aries.blueprint.container.BlueprintRepository.createAll(BlueprintRepository.java:147) 
at org.apache.aries.blueprint.container.BlueprintContainerImpl.instantiateEagerComponents(BlueprintContainerImpl.java:640) 
at org.apache.aries.blueprint.container.BlueprintContainerImpl.doRun(BlueprintContainerImpl.java:331) 
at org.apache.aries.blueprint.container.BlueprintContainerImpl.run(BlueprintContainerImpl.java:227) 

我甚至试过这样:

Query q = em.createNativeQuery("select AES_DECRYPT(l.password,?2) from loginDetails l where l.loginID = ?1"); 
q.setParameter(1, loginId); 
q.setParameter(2, getKey()); 
List<Object> s = q.getResultList(); 

String s1 = null; 
for(Object o : s){ 
    s1= (String) o; 
} 

即使在这里也即时通讯gettng的同例外情况:

java.lang.ClassCastException: [B cannot be cast to java.lang.Object 

你能告诉我什么是查询和处理请求的错误。

+0

为什么使用数据库来做到这一点,当Java有图书馆为你做到这一点? – fge

+1

不要加密密码。密码应该安全_hashed_;应该永远不可能检索密码。 – SLaks

+0

为什么在数据库提供这种开箱即用的方式时使用Java库,以便密码甚至不必离开数据库? – JimmyB

回答

6

类似的问题:What kind of Java type is "[B"?

MySQL的AES_DECRYPT确实返回一个String而是一个字节数组,由 “[B” 表示。将结果投射到byte[]并从中构建您的字符串。

看起来你甚至不需要解密密码;你只是想validateUser,对吧? - 在这种情况下,正如其他人所指出的那样,应该使用安全哈希。因为它已经提供了必要的functions:MD5(被认为是不安全的),SHA1(非常标准的)和SHA2(甚至比SHA1更安全),所以你可以很容易地用MySQL做到这一点。

所以你的基本方案可能看起来像:

insert into loginDetails (..., passwordHashSalt, passwordHash) values (..., ?1, SHA1(CONCAT(?1, ?2))),其中?1被设置为独特的“盐”,这可能是例如用户名本身,?2是实际的密码。请注意,salt也必须存储在数据库中,并且'必须'对每个用户/密码都是唯一的;因此,用户名是一个自然的选择。

然后,要验证一个给定的密码,你可以这样做:

select 'OK' from loginDetails where ... and passwordHash = SHA1(CONCAT(passwordHashSalt, ?1)),其中?1是要被验证的密码。

欲了解更多信息在互联网上搜索'密码散列',见例如herehere

如果需要,那些散列操作也可以在您的数据库客户端代码中完成。

+0

加密密码并使用DB功能保存它们不是一个好设计? – user1909657

+0

请看我最后的编辑:) – JimmyB

相关问题