对于一个小项目,我正在使用JSP和JDBC来建立一个虚拟网站(当前仅在我的笔记本电脑上本地运行)。它主要是为了与上述技术以及HTML和CSS联系。
我现在是希望用户能够登录该网站。我之前使用未在数据库中加密的密码成功测试了它。出于明显的安全原因,我想使用PostgreSQL的'pgcrypto'扩展名对数据库中的密码进行加密。
我通过pgAdmin进行了所有设置,并在那里成功测试了所有SQL。插入的用户仅用于测试目的,以后我将不再使用该用户。
CREATE EXTENSION pgcrypto
CREATE TABLE s68.USERS(
userid SERIAL NOT NULL PRIMARY KEY,
username VARCHAR (150) NOT NULL ,
password VARCHAR NOT NULL,
usergrp VARCHAR (20) NOT NULL,
CONSTRAINT chk_usergrp CHECK(usergrp IN('admin','trainer','news'))
);
INSERT INTO s68.users(username,password,usergrp)
VALUES ('admin',crypt('admin', gen_salt('bf')),'admin');
不幸的是,当我尝试通过JDBC运行SQL以便登录时,出现以下SQLException:
org.postgresql.util.PSQLException: ERROR: function crypt(character varying, character varying) does not exist Hinweis: No function matches the given name and argument types. You might need to add explicit type casts. Position: 63 at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2422) at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2167) at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:306) at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:441) at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:365) at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:155) at org.postgresql.jdbc.PgPreparedStatement.executeQuery(PgPreparedStatement.java:118) at beans.LoginBean.checkUseridPasswordSicher(LoginBean.java:50) at beans.LoginBean.checkUseridPassword(LoginBean.java:26) at org.apache.jsp.jsp.LoginAppl_jsp._jspService(LoginAppl_jsp.java:170) at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70) at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:444) at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:386) at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:330) at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:494) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:651) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:407) at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:754) at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1376) at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) at java.lang.Thread.run(Unknown Source)
这是我的函数代码,用于检查用户名和密码是否正确:
public boolean checkUseridPassword() throws NoConnectionException, SQLException{
String sql = "SELECT username from users "
+ "where username = ? and password = crypt(?, password)";
System.out.println(sql);
Connection dbConn = new PostgreSQLAccess().getConnection();
PreparedStatement prep = dbConn.prepareStatement(sql);
prep.setString(1, this.getUsername());
prep.setString(2, this.getPassword());
ResultSet dbRes = prep.executeQuery();
return dbRes.next();
}
我在pgAdmin中使用的数据库,用户和架构与在JDBC中相同。
尽管最初的问题是在两年前,但我也遇到过同样的问题。最后,我解决了在pgcrypto函数上创建显式“公共”模式的问题。使用pgAdmin时,我没有显式的模式连接,并且一切正常。但是,使用JDBC时,我连接了其他默认模式,因此看不到加密函数。就我而言,我设置了公共模式并强制转换了参数(前字符随文本而变化),问题得以解决。public.crypt(text_to_encrypt :: text,salt_text :: text)