我无法通过Java REST API连接到Snowflake。遵循有关使用JDBC驱动程序连接到Snowflake的Snowflake文档,但在Eclipse控制台上收到以下错误:
net.snowflake.client.jdbc.SnowflakeSQLException:用户名错误或 指定了密码。在 net.snowflake.client.core.SessionUtil.newSession(SessionUtil.java:577) 〜[snowflake-jdbc-3.9.2.jar:3.9.2]在 net.snowflake.client.core.SessionUtil.openSession(SessionUtil.java:266) 〜[snowflake-jdbc-3.9.2.jar:3.9.2]在 net.snowflake.client.core.SFSession.open(SFSession.java:510) 〜[snowflake-jdbc-3.9.2.jar:3.9.2]在 net.snowflake.client.jdbc.SnowflakeConnectionV1.initialize(SnowflakeConnectionV1.java:135) 〜[snowflake-jdbc-3.9.2.jar:3.9.2]在 net.snowflake.client.jdbc.SnowflakeConnectionV1。(SnowflakeConnectionV1.java:117) 〜[snowflake-jdbc-3.9.2.jar:3.9.2]在 net.snowflake.client.jdbc.SnowflakeDriver.connect(SnowflakeDriver.java:137) 〜[snowflake-jdbc-3.9.2.jar:3.9.2]在 java.sql.DriverManager.getConnection(未知来源)〜[na:1.8.0_151] 在java.sql.DriverManager.getConnection(未知来源) 〜[na:1.8.0_151]在 com.system.monitor.registry.RegistryRepository.findAll(RegistryRepository.java:70) 〜[classes /:na]在 com.system.monitor.registry.RegistryRepository $$ FastClassBySpringCGLIB $$ 1199dc92.invoke() 〜[classes /:na]在 org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) 〜[spring-core-5.2.0.RELEASE.jar:5.2.0.RELEASE]在 org.springframework.aop.framework.CglibAopProxy $ CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:769) 〜[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) 〜[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]在 org.springframework.aop.framework.CglibAopProxy $ CglibMethodInvocation.proceed(CglibAopProxy.java:747) 〜[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]在 org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) 〜[spring-tx-5.2.0.RELEASE.jar:5.2.0.RELEASE]在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) 〜[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]在 org.springframework.aop.framework.CglibAopProxy $ CglibMethodInvocation.proceed(CglibAopProxy.java:747) 〜[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]在 org.springframework.aop.framework.CglibAopProxy $ DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689) 〜[spring-aop-5.2.0.RELEASE.jar:5.2.0.RELEASE]在 com.system.monitor.registry.RegistryRepository $$ EnhancerBySpringCGLIB $$ b552203e.findAll() 〜[classes /:na]在 com.system.monitor.registry.RegistryController.getAllRegistries(RegistryController.java:19) 〜[classes /:na]在sun.reflect.NativeMethodAccessorImpl.invoke0(本机 方法)〜[na:1.8.0_151]在 sun.reflect.NativeMethodAccessorImpl.invoke(未知来源) 〜[na:1.8.0_151]在 sun.reflect.DelegatingMethodAccessorImpl.invoke(未知来源) 〜[na:1.8.0_151],位于java.lang.reflect.Method.invoke(未知源) 〜[na:1.8.0_151]在 org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) 〜[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]在 org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) 〜[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]在 org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) 〜[spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]在 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:888) 〜[spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]在 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793) 〜[spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]在 org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) 〜[spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]在 org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) 〜[spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]在 org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) 〜[spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]在 org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) 〜[spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]在 org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) 〜[spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]在 javax.servlet.http.HttpServlet.service(HttpServlet.java:634) 〜[tomcat-embed-core-9.0.27.jar:9.0.27]在 org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) 〜[spring-webmvc-5.2.0.RELEASE.jar:5.2.0.RELEASE]在 javax.servlet.http.HttpServlet.service(HttpServlet.java:741) 〜[tomcat-embed-core-9.0.27.jar:9.0.27]在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) 〜[tomcat-embed-core-9.0.27.jar:9.0.27]在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 〜[tomcat-embed-core-9.0.27.jar:9.0.27]在 org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) 〜[tomcat-embed-websocket-9.0.27.jar:9.0.27]在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 〜[tomcat-embed-core-9.0.27.jar:9.0.27]在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 〜[tomcat-embed-core-9.0.27.jar:9.0.27]在 org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) 〜[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]在 org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) 〜[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 〜[tomcat-embed-core-9.0.27.jar:9.0.27]在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 〜[tomcat-embed-core-9.0.27.jar:9.0.27]在 org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) 〜[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]在 org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) 〜[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 〜[tomcat-embed-core-9.0.27.jar:9.0.27]在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 〜[tomcat-embed-core-9.0.27.jar:9.0.27]在 org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) 〜[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]在 org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) 〜[spring-web-5.2.0.RELEASE.jar:5.2.0.RELEASE]在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) 〜[tomcat-embed-core-9.0.27.jar:9.0.27]在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) 〜[tomcat-embed-core-9.0.27.jar:9.0.27]在 org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) 〜[tomcat-embed-core-9.0.27.jar:9.0.27]在 org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-9.0.27.jar:9.0.27]在 org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:526) [tomcat-embed-core-9.0.27.jar:9.0.27]在 org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) [tomcat-embed-core-9.0.27.jar:9.0.27]在 org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.27.jar:9.0.27]在 org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) [tomcat-embed-core-9.0.27.jar:9.0.27]在 org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) [tomcat-embed-core-9.0.27.jar:9.0.27]在 org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408) [tomcat-embed-core-9.0.27.jar:9.0.27]在 org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-9.0.27.jar:9.0.27]在 org.apache.coyote.AbstractProtocol $ ConnectionHandler.process(AbstractProtocol.java:861) [tomcat-embed-core-9.0.27.jar:9.0.27]在 org.apache.tomcat.util.net.NioEndpoint $ SocketProcessor.doRun(NioEndpoint.java:1579) [tomcat-embed-core-9.0.27.jar:9.0.27]在 org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.27.jar:9.0.27]在 java.util.concurrent.ThreadPoolExecutor.runWorker(未知来源) [na:1.8.0_151]在 java.util.concurrent.ThreadPoolExecutor $ Worker.run(未知源) [na:1.8.0_151]在 org.apache.tomcat.util.threads.TaskThread $ WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.27.jar:9.0.27]在java.lang.Thread.run(未知 来源)[na:1.8.0_151]
我已按照Snowflake文档中指定的步骤进行操作:https://docs.snowflake.net/manuals/user-guide/jdbc.html
我正在使用RSA密钥对按照文档中的说明对Snowflake进行身份验证。 我还已经将公钥映射到我正在使用的Snowflake用户,仍然面临此问题。 我怀疑密钥解密是否是问题。
以下是我用来连接到Snowflake的代码:
public class TestSnowflakeConnection {
public static void main(String[] args)
throws Exception
{
DriverManager.registerDriver(new net.snowflake.client.jdbc.SnowflakeDriver());
File f = new File("D:\\....\\Auth-Keys\\rsa_key.p8");
FileInputStream fis = new FileInputStream(f);
DataInputStream dis = new DataInputStream(fis);
byte[] keyBytes = new byte[(int) f.length()];
dis.readFully(keyBytes);
dis.close();
String encrypted = new String(keyBytes);
String passphrase = System.getenv("----");
encrypted = encrypted.replace("-----BEGIN ENCRYPTED PRIVATE KEY-----", "");
encrypted = encrypted.replace("-----END ENCRYPTED PRIVATE KEY-----", "");
EncryptedPrivateKeyInfo pkInfo = new EncryptedPrivateKeyInfo(Base64.getMimeDecoder().decode(encrypted));
PBEKeySpec keySpec = new PBEKeySpec(passphrase.toCharArray());
SecretKeyFactory pbeKeyFactory = SecretKeyFactory.getInstance(pkInfo.getAlgName());
PKCS8EncodedKeySpec encodedKeySpec = pkInfo.getKeySpec(pbeKeyFactory.generateSecret(keySpec));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey encryptedPrivateKey = keyFactory.generatePrivate(encodedKeySpec);
String url = "jdbc:snowflake://<account>.snowflakecomputing.com";
Properties prop = new Properties();
prop.put("user", "username");
prop.put("account", "xxx.xxx.xx-southeast-1.aws");
prop.put("privateKey", encryptedPrivateKey);
Connection conn = DriverManager.getConnection(url, prop);
Statement stat = conn.createStatement();
ResultSet res = stat.executeQuery("select 1");
res.next();
System.out.println(res.getString(1));
conn.close();
}
}
任何帮助将不胜感激!!!!!
答案 0 :(得分:1)
几个问题:
alter user...
命令将公钥分配给Snowflake用户时,是否确定要排除-----BEGIN ENCRYPTED PRIVATE KEY-----
和-----END ENCRYPTED PRIVATE KEY-----
吗? 如果您使用密码短语 did 加密了私钥,那么如果要从Snowflake复制Java代码,则需要确保将密码短语放在名为PRIVATE_KEY_PASSPHRASE
的环境变量中文档。
在您的代码中,您有以下内容:
String passphrase = System.getenv("----");
这是在名为----
的环境变量中寻找加密私钥的密码,这似乎不正确吗?
答案 1 :(得分:0)
Here is the working copy of the code .
--------------------------------------------------------------------------------
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.time.Instant;
import java.util.Base64;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import javax.crypto.EncryptedPrivateKeyInfo;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.PBEKeySpec;
import net.snowflake.ingest.SimpleIngestManager;
import net.snowflake.ingest.connection.HistoryRangeResponse;
import net.snowflake.ingest.connection.HistoryResponse;
public class SDKTest {
private static final String PRIVATE_KEY_FILE = "<Path to your p8 file>/rsa_key.p8";
public static class PrivateKeyReader {
public static PrivateKey get(String filename) throws Exception {
File f = new File(filename);
FileInputStream fis = new FileInputStream(f);
DataInputStream dis = new DataInputStream(fis);
byte[] keyBytes = new byte[(int) f.length()];
dis.readFully(keyBytes);
dis.close();
String encrypted = new String(keyBytes);
String passphrase = <YOUR_PASSPHRASE>;
encrypted = encrypted.replace("-----BEGIN ENCRYPTED PRIVATE KEY-----", "");
encrypted = encrypted.replace("-----END ENCRYPTED PRIVATE KEY-----", "");
EncryptedPrivateKeyInfo pkInfo = new EncryptedPrivateKeyInfo(Base64.getMimeDecoder().decode(encrypted));
PBEKeySpec keySpec = new PBEKeySpec(passphrase.toCharArray());
SecretKeyFactory pbeKeyFactory = SecretKeyFactory.getInstance(pkInfo.getAlgName());
PKCS8EncodedKeySpec encodedKeySpec = pkInfo.getKeySpec(pbeKeyFactory.generateSecret(keySpec));
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PrivateKey encryptedPrivateKey = keyFactory.generatePrivate(encodedKeySpec);
return encryptedPrivateKey;
}
}
private static HistoryResponse waitForFilesHistory(final SimpleIngestManager manager, Set<String> files)
throws Exception {
ExecutorService service = Executors.newSingleThreadExecutor();
class GetHistory implements Callable<HistoryResponse> {
private Set<String> filesWatchList;
GetHistory(Set<String> files) {
this.filesWatchList = files;
}
String beginMark = null;
public HistoryResponse call() throws Exception {
HistoryResponse filesHistory = null;
while (true) {
Thread.sleep(5000);
HistoryResponse response = manager.getHistory(null, null, beginMark);
if (response.getNextBeginMark() != null) {
beginMark = response.getNextBeginMark();
}
if (response != null && response.files != null) {
for (HistoryResponse.FileEntry entry : response.files) {
// if we have a complete file that we've
// loaded with the same name..
String filename = entry.getPath();
if (entry.getPath() != null && entry.isComplete() && filesWatchList.contains(filename)) {
if (filesHistory == null) {
filesHistory = new HistoryResponse();
filesHistory.setPipe(response.getPipe());
}
filesHistory.files.add(entry);
filesWatchList.remove(filename);
// we can return true!
if (filesWatchList.isEmpty()) {
return filesHistory;
}
}
}
}
}
}
}
GetHistory historyCaller = new GetHistory(files);
// fork off waiting for a load to the service
Future<HistoryResponse> result = service.submit(historyCaller);
HistoryResponse response = result.get(2, TimeUnit.MINUTES);
return response;
}
public static void main(String[] args) {
final String account = "<Snowflake Account Name >";
final String hostName = "<Snowflake Account URL>";
final String user = "<Snowflake Account Username>";
final String pipe = "<Snowflake Pipe Path>";
try {
final long oneHourMillis = 1000 * 3600L;
String startTime = Instant.ofEpochMilli(System.currentTimeMillis() - 4 * oneHourMillis).toString();
PrivateKey privateKey = PrivateKeyReader.get(PRIVATE_KEY_FILE);
//PublicKey publicKey = PublicKeyReader.get(PUBLIC_KEY_FILE);
@SuppressWarnings("deprecation")
SimpleIngestManager manager = new SimpleIngestManager(account, user, pipe, privateKey, "https", hostName, 443);
Set<String> files = new TreeSet<>();
files.add("<filename>");
manager.ingestFiles(manager.wrapFilepaths(files), null);
HistoryResponse history = waitForFilesHistory(manager, files);
System.out.println("Received history response: " + history.toString());
String endTime = Instant.ofEpochMilli(System.currentTimeMillis()).toString();
HistoryRangeResponse historyRangeResponse = manager.getHistoryRange(null, startTime, endTime);
System.out.println("Received history range response: " + historyRangeResponse.toString());
} catch (Exception e) {
e.printStackTrace();
}
}
}
-----------------------------------------------------------------------------