public Login authenticate(Login login) {
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
String password = login.getPassword();
try {
md.update(password.getBytes("UTF-16"));
byte[] digest = md.digest();
String query = "SELECT L FROM Login AS L WHERE L.email=? AND L.password=?";
Object[] parameters = { login.getEmail(), digest };
List<Login> resultsList = (getHibernateTemplate().find(query,parameters));
if (resultsList.isEmpty()) {
//error dude
}
else if (resultsList.size() > 1) {
//throw expections
}
else {
Login login1 = (Login) resultsList.get(0);
return login1;
}
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
异常
> 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)
答案 0 :(得分:6)
似乎数据库的密码列是在Java中映射为String
的类型(最有可能是varchar
)。因此,hibernate无法将您的字节array
转换为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 };
但它可能无法正常工作,因为无论编码如何,摘要肯定都包含不能映射到字符的字节。您应该使用base64 encoding将二进制blob映射到String。
另一种解决方案是更改您的数据库方案,并将password
字段设为二进制而不是varchar
。
在这两种情况下,您都需要知道如何在数据库中插入password
字段。
对您的代码的一些评论:
我发现您通过用户名和密码从数据库中选择一行来检查密码,这一点很奇怪。我更合乎逻辑地选择仅使用用户,然后根据数据库上返回的密码验证提供的密码。
您使用哈希函数来确保您的密码不会以纯文本格式存储在数据库中。非常好。但是,您的方案存在大缺陷:如果多个用户具有相同的密码,则散列密码在数据库中将是相同的。因此,如果您有权访问数据库并知道一个用户的密码,那么找到共享此密码的所有用户将非常容易。为了构建更安全的东西,您应该使用包含一些salt的密码编码方案。
答案 1 :(得分:2)
看起来像是[传递一个需要字符串的字节数组。
尝试{ login.getEmail(), new String(digest) };
而不是{ login.getEmail(), digest };
参考 http://download.oracle.com/javase/1.4.2/docs/api/java/lang/String.html#String%28byte []%29
答案 2 :(得分:0)
错误似乎在第30行,我猜是Object[]
参数行。在这种情况下,您需要将byte[]
摘要转换为String并使用该字符串作为参数。
在问题编辑之前给出了这个答案。
在函数中包装:
byte[] digest = getMessageDigest(login.getPassword());
login1 = verifyPassword(login.getEmail(), digest);
当然相关的try
/ catch
仍在那里。
尝试从习惯e.printStackTrace()
转移到使用java.utils.logging.Logger或log4j写入日志文件。
尝试在函数中只返回一个。如果保持代码相同,请在函数开头定义Login login1=null
,然后在else块中分配。最后的回报应该是return login1
(这将是null或某个值)。
您仍需要实施代码的部分(例如错误花花公子)应该使用//TODO:
进行评论。像eclipse / netbeans这样的大多数ide会自动将这些注释作为任务发现。
答案 3 :(得分:0)
与该错误有关。 就我而言,我正在测试中嘲笑String类。
我有:
mockkStatic(Base64::class)
every { String(Base64.decode(text, 0)) } returns token
我将其更改为:
mockkStatic(Base64::class)
every { Base64.decode(text, 0) } returns token.toByteArray()
因此String
类表现出所需的行为。