我已经使用Field LoginId和Password编写了一个权限类。
Iam使用AES_ENCRYPT加密passwrd并在db中加载它。
我想只检索解密的密码。所以,我在OPEN JPA 2.0中使用NAEDQueryis使用AES_DECRYPT。
我写的查询是:
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;
}
即使在这里,我也得到了同样的例外:
java.lang.ClassCastException: [B cannot be cast to java.lang.Object
您能告诉我处理请求的查询和错误是什么错误。
答案 0 :(得分:7)
类似的问题:What kind of Java type is "[B"?
MySQL的AES_DECRYPT
不返回String
而是返回一个字节数组,用“[B”表示。将结果转换为byte[]
并从中构建字符串。
看起来你甚至不需要解密密码;你只想validateUser
,对吧? - 在这种情况下,正如其他人所指出的那样,应该使用安全哈希值。
你可以轻松地使用MySQL,因为它已经提供了必要的functions:MD5(被认为是不安全的),SHA1(非常标准)和SHA2(甚至比SHA1更安全)。
所以你的方案基本上可能是这样的:
insert into loginDetails (..., passwordHashSalt, passwordHash) values ( ..., ?1, SHA1(CONCAT( ?1, ?2 )) )
,其中?1
设置为唯一的“salt”,例如可能是用户名本身,?2
是实际密码。请注意,salt也必须存储在DB中,并且“必须”对每个用户/密码都是唯一的;因此,用户名是一个自然的选择。
然后,要验证给定的密码,您可以执行以下操作:
select 'OK' from loginDetails where ... and passwordHash = SHA1(CONCAT( passwordHashSalt, ?1 ))
,其中?1
是要验证的密码。
有关详细信息,请在互联网上搜索“密码哈希”,例如参见here或here。
如果需要,也可以在数据库客户端代码中完成这些散列操作。