java.lang.ClassCastException:[B>;不能转换为java.lang.String

java.lang.ClassCastException:[B>;不能转换为java.lang.String,java,hibernate,spring,coding-style,Java,Hibernate,Spring,Coding Style,错误似乎出现在第30行,我猜是对象[]参数行。在这种情况下,您需要将字节[]摘要转换为字符串,并使用字符串作为参数 这个答案是在编辑问题之前给出的 在函数中总结: > java.lang.ClassCastException: [B > cannot be cast to java.lang.String > at org.hibernate.type.StringType.toString(StringType.java:44) > at

错误似乎出现在第30行,我猜是
对象[]
参数行。在这种情况下,您需要将
字节[]
摘要转换为字符串,并使用字符串作为参数

这个答案是在编辑问题之前给出的

在函数中总结:

> java.lang.ClassCastException: [B
> cannot be cast to java.lang.String
>         at org.hibernate.type.StringType.toString(StringType.java:44)
>         at org.hibernate.type.NullableType.nullSafeToString(NullableType.java:93)
>         at org.hibernate.type.NullableType.nullSafeSet(NullableType.java:140)
>         at org.hibernate.type.NullableType.nullSafeSet(NullableType.java:116)
>         at org.hibernate.param.PositionalParameterSpecification.bind(PositionalParameterSpecification.java:39)
>         at org.hibernate.loader.hql.QueryLoader.bindParameterValues(QueryLoader.java:491)
>         at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1563)
>         at org.hibernate.loader.Loader.doQuery(Loader.java:673)
>         at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:236)
>         at org.hibernate.loader.Loader.doList(Loader.java:2213)
>         at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2104)
>         at org.hibernate.loader.Loader.list(Loader.java:2099)
>         at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:378)
>         at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:338)
>         at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:172)
>         at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1121)
>         at org.hibernate.impl.QueryImpl.list(QueryImpl.java:79)
>         at org.springframework.orm.hibernate3.HibernateTemplate$29.doInHibernate(HibernateTemplate.java:856)
>         at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:373)
>         at org.springframework.orm.hibernate3.HibernateTemplate.find(HibernateTemplate.java:847)
>         at com.intermedix.services.LoginService.authenticate(LoginService.java:30)
>         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.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:301)
>         at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
>         at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
>         at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
>         at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
>         at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
>         at $Proxy31.authenticate(Unknown Source)
>         at com.intermedix.ui.LoginDailog.checkLogin(LoginDailog.java:106)
>         at com.intermedix.ui.LoginDailog.access$0(LoginDailog.java:102)
>         at com.intermedix.ui.LoginDailog$2.handleAction(LoginDailog.java:88)
>         at com.vaadin.event.ActionManager.handleAction(ActionManager.java:228)
>         at com.vaadin.event.ActionManager.handleActions(ActionManager.java:198)
>         at com.vaadin.ui.Panel.changeVariables(Panel.java:345)
>         at com.vaadin.ui.Window.changeVariables(Window.java:1073)
>         at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.handleVariables(AbstractCommunicationManager.java:1094)
>         at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.doHandleUidlRequest(AbstractCommunicationManager.java:590)
>         at com.vaadin.terminal.gwt.server.CommunicationManager.handleUidlRequest(CommunicationManager.java:266)
>         at com.vaadin.terminal.gwt.server.AbstractApplicationServlet.service(AbstractApplicationServlet.java:476)
>         at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
>         at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
>         at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:390)
>         at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
>         at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
>         at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
>         at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
>         at org.mortbay.jetty.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:230)
>         at org.mortbay.jetty.handler.HandlerCollection.handle(HandlerCollection.java:114)
>         at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
>         at org.mortbay.jetty.Server.handle(Server.java:326)
>         at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
>         at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:943)
>         at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:756)
>         at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
>         at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
>         at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:410)
>         at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
当然,相关的
try
/
catch
仍然存在

尝试从习惯
e.printStackTrace()
转变为使用java.utils.logging.Logger或log4j写入日志文件

尝试在函数中只返回一次。如果代码保持不变,请在函数开头定义
Login login1=null
,然后在else块中赋值。结尾的返回应该是
return login1
(可能是null或某个值)


对于仍有代码需要实现的部分(例如error dude),应该使用
//TODO:
进行注释。大多数IDE(如eclipse/netbeans)都会自动将这些注释作为任务进行查找。

看起来像是在传递需要字符串的字节数组

尝试
{login.getEmail(),新字符串(摘要)};
而不是
{login.getEmail(),摘要};


参考http://download.oracle.com/javase/1.4.2/docs/api/java/lang/String.html#String%28byte[%29

数据库的密码列似乎是Java中映射为
字符串的类型(
varchar
),因此hibernate无法将字节
数组
转换为
字符串

您可以将行更改为以下内容:

byte[] digest = getMessageDigest(login.getPassword());
login1 = verifyPassword(login.getEmail(), digest);
但是它可能不起作用,因为不管编码是什么,摘要中肯定包含不可映射到字符的字节。您可能应该使用a将二进制blob映射到字符串

另一个解决方案是更改dabase方案,并将
密码
字段设置为二进制,而不是
varchar

在这两种情况下,您都需要知道
密码
字段是如何插入数据库的

关于代码的一些备注:

我觉得奇怪的是,您通过从数据库中选择一行用户名和密码来检查密码。我认为更合理的做法是仅使用用户进行选择,然后根据数据库中返回的密码验证提供的密码

您使用散列函数来确保您的密码不会以明文形式存储在数据库中。这很好。但是,您的方案有一个大的缺陷:如果多个用户拥有相同的密码,则散列密码在数据库中是相同的。因此,如果您可以访问数据库并知道一个用户的密码,那么它将是真实的很容易找到共享此密码的所有用户。为了构建更安全的密码,您应该使用包含一些与此错误相关的密码编码方案。

。 在我的例子中,我在测试中模拟了String类

我有:

 String digest = new String(md.digest());
 String query = "SELECT L FROM Login AS L WHERE L.email=? AND L.password=?";
 Object[] parameters = { login.getEmail(), digest };
我把它改成:

mockkStatic(Base64::class)
every { String(Base64.decode(text, 0)) } returns token

因此,
String
类的行为符合需要。

是否出现编译器错误?警告?运行时异常?我已更新了问题本身,因为我得到了预期的结果。错误似乎出现在该文件的第30行。哪一行是第30行?不会起作用,因为摘要肯定不包含字符字节序列。@Nishant感谢您的帮助共享。
new String(“Any String”)
这解决了我的问题。再加上一个。我不明白使用额外的salt来存储密码哈希的意义。如果你不选择“模糊安全性”无论如何,你都必须提供所有信息来重建哈希?你能给我一个链接来了解更多关于这个建议的信息吗?@mtraut在这种情况下,salt的主要好处是确保哈希密码的唯一性。@mtraut在这种情况下,salt的主要好处是确保哈希密码的唯一性。salt是在对密码进行散列时随机选择,并在散列密码前添加。您可以查看一个实现示例。它选择
MD5
作为算法并多次加密同一密码,您将看到每次散列密码都不同。在此散列方案中,salt是
$
$apr1$
之后。查看答案中的链接以了解更多信息。我知道salt的作用-我怀疑的是,至少在您提到的情况下,在散列密码存储的情况下,这会提高安全性。从计算上讲,比较一组字节或首先提取salt,重新隐藏已知的pa没有太大区别然后进行ssword和比较(与蛮力攻击进行比较)。是的,你说得很对。这完全取决于你想检查多少已知密码。如果你有一个默认密码,以及检查什么,如果某些用户忘记更改密码,salt不会有太大的区别。另一方面,如果你计划对一个有数百个用户的数据库进行字典攻击,salt会发出信号非常重要的区别:一个2天的攻击会变成一个200天的攻击,有100个用户。
mockkStatic(Base64::class)
every { String(Base64.decode(text, 0)) } returns token
mockkStatic(Base64::class)
every { Base64.decode(text, 0) } returns token.toByteArray()