SVNKit支持SSH连接
SVNKit这个开源工具,用于Java语言访问SVN库,咋看的时候很方便,其实坑特别多。我在这里只想跟大家说一句,如果你还没有用过,请不要在生产环境使用这个东西了,兼容性问题搞死你(替换方案是直接用svn命令行,自己组参数调用,然后解析返回数据)。如果你已经入坑,好吧,有问题可以一起交流。
本文讲述SVNKit认证方面的知识,包括常用的http、https格式的svn地址,同时支持svn+ssh格式的svn地址。废话不说,上代码:
1 package lekko.svn; 2 3 import org.tmatesoft.svn.core.SVNException; 4 import org.tmatesoft.svn.core.SVNURL; 5 import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager; 6 import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory; 7 import org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryFactoryImpl; 8 import org.tmatesoft.svn.core.wc.*; 9 10 import java.io.File; 11 12 /** 13 * 默认版本访问的SVNKit工厂 14 * @author lekko 15 */ 16 public class SvnKitFactory { 17 18 public static ISVNOptions OPTION = SVNWCUtil.createDefaultOptions(true); 19 private static ISVNAuthenticationManager AUTH; 20 21 private static SvnKitFactory _instance = new SvnKitFactory2(); 22 23 private SvnKitFactory() { 24 init(); 25 } 26 27 /** 28 * 单例SVN连接类 29 */ 30 public static SvnKitFactory getInstance() { 31 return _instance; 32 } 33 34 /** 35 * 快速获取连接 36 */ 37 public SVNClientManager getClient() { 38 if (AUTH != null) { 39 return SVNClientManager.newInstance(OPTION, AUTH); 40 } 41 return SVNClientManager.newInstance(OPTION); 42 } 43 44 /** 45 * 对SVNKit连接进行认证,并获取连接 46 * @param username 用户名 47 * @param pwd 密码 48 * @param sshFilePath OpenSSH密钥 49 */ 50 public SVNClientManager getAuthClient(String username, String pwd, String sshFilePath) { 51 File dir = SVNWCUtil.getDefaultConfigurationDirectory(); 52 AUTH = SVNWCUtil.createDefaultAuthenticationManager(dir, username, pwd.toCharArray(), new File(sshFilePath), new char[] {}, true); 53 return SVNClientManager.newInstance(OPTION, AUTH); 54 } 55 56 private void init() { 57 // HTTP、HTTPS网络 58 DAVRepositoryFactory.setup(); 59 // SSH网络 60 SVNRepositoryFactoryImpl.setup(); 61 } 62 63 public static void main(String[] args) throws SVNException { 64 SvnKitFactory factory = SvnKitFactory.getInstance(); 65 SVNClientManager manager = factory.getAuthClient("lekko", "", "C:/Users/Public/Documents/lekko.openssh"); 66 SVNWCClient client = manager.getWCClient(); 67 SVNURL url = SVNURL.parseURIEncoded("svn+ssh://lekko@www.webxxx.com/xxx/xxx_rep/test_proj"); 68 SVNInfo info = client.doInfo(url, SVNRevision.HEAD, SVNRevision.HEAD); 69 System.out.println("OK " + info); 70 } 71 }
这里我需要说明几个点:
1、main方法只是用来测试的,可以不要。
2、关于“getAuthClient”的参数,username是必须的,pwd(密码)可以是空字符串“”,sshFilePath(SSH私钥文件路径)也可以是空字符串“”。但是pwd和sshFilePath分别有不同的认证作用,前者是用于HTTP、HTTPS的,后者是用于SSH的。缺少哪个,对应的链接方式就不能正常认证了。
3、Windows用户要特别注意,SSH私钥必须是OpenSSH格式的,如果你是用PuTTYGen生成的密钥,记得转成OpenSSH,不然SVNKit也不能成功使用它进行认证的。
4、SVNKit对用户名与密码是有缓存的,一般缓存的目录与系统的svn命令行一致:
- Windows在C:\Users\用户名\AppData\Roaming\Subversion\auth目录下
- Linux在~/.subversion/auth目录下
5、正由于SVNKit有缓存,所以实际上不需要每次都调用“getAuthClient”方法进行账号认证。我这里推荐大家的调用是这样,在系统初始化时,先调用一次“getClient”,并进行一次doInfo操作,如果异常再使用“getAuthClient”方法进行认证,后续也只需要使用“getClient”方法,效率更高一些。上代码:
1 try { 2 SVNClientManager manager = SvnKitFactory.getInstance().getClient(); // 尝试使用缓存 4 manager.getWCClient().doInfo(SVNURL.parseURIEncoded(url), null, SVNRevision.HEAD); 5 } catch (SVNException e) { 6 int code = e.getErrorMessage().getErrorCode().getCode(); 7 if (code == 170001) { 8 try { 9 SVNClientManager manager = SvnKitFactory.getInstance().getAuthClient(username, pwd, sshfile); // 进行认证 10 manager.getWCClient().doInfo(SVNURL.parseURIEncoded(url), null, SVNRevision.HEAD); 11 } catch (SVNException ex) { 12 logger.error("Auth fail", ex); 13 } 14 } else { 15 _logger.error("Auth fail", e); 16 } 17 }
可以把它封到你程序启动的时候,或者在失败时弹个框让用户输入什么的。