web-dev-qa-db-ja.com

java.lang.ClassCastException:[BをJava.lang.Stringにキャストできません

FieldLoginIdとPasswordを使用してエンティティクラスを作成しました。

Iamはpasswrdを暗号化し、AES_ENCRYPTを使用してデータベースに保存します。

復号化されたパスワードのみを取得したい。したがって、OPen JPA2.0でNAtiveQueryisを使用して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

クエリとリクエストを処理する際の間違いを教えてください。

7
user1909657

同様の質問: どのようなJavaタイプは "[B"?

MySQLの_AES_DECRYPT_はnotではなくStringを返しますが、「[B」で示されるバイトの配列を返します。結果を_byte[]_にキャストし、そこから文字列を作成します。

パスワードを解読する必要さえないようです。 validateUserしたいだけですよね? -その場合、他の人が指摘しているように、安全なハッシュを使用する必要があります。

MySQLは、必要な 関数 :MD5(安全でないと見なされる)、SHA1(ほぼ標準)、およびSHA2(SHA1よりもさらに安全)をすでに提供しているため、これを簡単に行うことができます。

したがって、スキームは基本的に次のようになります。

insert into loginDetails (..., passwordHashSalt, passwordHash) values ( ..., ?1, SHA1(CONCAT( ?1, ?2 )) )、ここで_?1_は一意の「salt」に設定されます。これはたとえばユーザー名自体であり、_?2_は実際のパスワードです。ソルトもDBに保存する必要があり、「ユーザー/パスワードごとに一意である必要がある」ことに注意してください。したがって、ユーザー名はそのための自然な選択です。

次に、指定されたパスワードを確認するには、次の操作を実行できます。

select 'OK' from loginDetails where ... and passwordHash = SHA1(CONCAT( passwordHashSalt, ?1 ))、ここで_?1_は検証されるパスワードです。

詳細については、インターネットで「パスワードハッシュ」を検索してください。たとえば、 ここ または ここ を参照してください。

これらのハッシュ操作は、必要に応じて、代わりにデータベースクライアントコードで実行することもできます。

8
JimmyB