天天看點

利用Apache ftp server 為你的程式提供FTP服務

先來簡單介紹一下apache ftp server吧,顧名思義這個是Apache下的一個東東,個人感覺還是很新的,到現在才是1.0.X,不過還是相信Apache的品牌效應,這個東東用起來還是很友善的,通過配置檔案可以對ftp服務相關參數進行靈活配置,能夠支援基于配置檔案和資料庫的兩種使用者權限管理,另外還支援SSL協定和數字證書機制。

下面是官網的簡單介紹:

The Apache FtpServer is a 100% pure Java FTP server. It's designed to be a complete and portable FTP server engine solution based on currently available open protocols. FtpServer can be run standalone as a Windows service or Unix/Linux daemon, or embedded into a Java application. We also provide support for integration within Spring applications and provide our releases as OSGi bundles.

接下來我就按三部分介紹apache ftp server的使用。

1.       獨立部署apache ftp server作為系統服務

2.       作為為window系統的服務

3.       結合spring配置嵌入我們自己的系統

注:因為Apache FTP Server名字寫起來太長,以下簡稱為AFS.

1.       獨立部署AFS

1.1    安裝AFS http://mina.apache.org/ftpserver/

我用的版本是1.0.4, 本文就以該版本為例。無需安裝下載下傳後直接解壓即可。

       因為是純java編寫的程式,是以程式部分windows和linux,解壓後在程式的bin目錄下有這樣一系列的可執行檔案。其中ftpd.bat和ftpd.sh分别是windows平台和linux下的啟動指令。

1.2 啟動AFS

AFS啟動時可以指定使用的具體的配置檔案,例如:

bin/ftpd.bat res/conf/ftpd-typical.xml

如果未指定配置檔案,那麼會預設用自帶的res/conf/ftpd-full.xml檔案作為配置檔案。

到此為止,一個ftp server就已經運作起來了。

1.3 AFS的配置

1.3.1 AFS配置檔案詳解

 以AFS自帶的配置檔案ftpd-full.xml為例加以介紹。ftpd-full.xml路徑為$AFS_HOME\res\conf\ftpd-full.xml.

檔案内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<server xmlns="http://mina.apache.org/ftpserver/spring/v1"
	xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="
	   http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
	   http://mina.apache.org/ftpserver/spring/v1 http://mina.apache.org/ftpserver/ftpserver-1.0.xsd	
	   "
	id="myServer">
	<!--
		Use this section to define custom listeners, or to redefine the
		default listener, aptly named "default"
	-->
	<listeners>
		<nio-listener name="default" port="2222" implicit-ssl="true"
			idle-timeout="60" local-address="1.2.3.4">
			<ssl>
				<keystore file="mykeystore.jks" password="secret"
					key-password="otherSecret" />
				<truststore file="mytruststore.jks" password="secret" />
			</ssl>
			<data-connection idle-timeout="60">
				<active enabled="true" local-address="1.2.3.4" local-port="2323"
					ip-check="true" />
				<passive ports="123-125" address="1.2.3.4" external-address="1.2.3.4" />
			</data-connection>
			<blacklist>1.2.3.0/16, 1.2.4.0/16, 1.2.3.4</blacklist>
		</nio-listener>
	</listeners>
	<!--
		Use this section to define your Ftplets, they are configured like
		regular Spring beans
	-->
	<ftplets>
		<ftplet name="ftplet1">
			<beans:bean class="org.apache.ftpserver.examples.MyFtplet">
				<beans:property name="foo" value="123" />
			</beans:bean>
		</ftplet>
	</ftplets>
	<!-- The user manager, choose one -->
	<file-user-manager file="users.properties"
		encrypt-passwords="true" />
	<!--<db-user-manager>
		<data-source>
			<beans:bean class="some.datasoure.class" />
		</data-source>
		<insert-user>INSERT INTO FTP_USER (userid, userpassword,
			homedirectory, enableflag, writepermission, idletime, uploadrate,
			downloadrate) VALUES ('{userid}', '{userpassword}',
			'{homedirectory}',
			{enableflag}, {writepermission}, {idletime},
			{uploadrate},
			{downloadrate})
		</insert-user>
			<update-user>UPDATE FTP_USER SET
				userpassword='{userpassword}',homedirectory='{homedirectory}',enableflag={enableflag},writepermission={writepermission},idletime={idletime},uploadrate={uploadrate},downloadrate={downloadrate}
				WHERE userid='{userid}'
		</update-user>
			<delete-user>DELETE FROM FTP_USER WHERE userid = '{userid}'
		</delete-user>
			<select-user>SELECT userid, userpassword, homedirectory,
				enableflag, writepermission, idletime, uploadrate, downloadrate,
				maxloginnumber, maxloginperip FROM
				FTP_USER WHERE userid = '{userid}'
		</select-user>
			<select-all-users>SELECT userid FROM FTP_USER ORDER BY userid
		</select-all-users>
			<is-admin>SELECT userid FROM FTP_USER WHERE userid='{userid}'
				AND
				userid='admin'
		</is-admin>
			<authenticate>SELECT userpassword from FTP_USER WHERE
				userid='{userid}'</authenticate>
	</db-user-manager> -->
	<!-- The file system -->
	<native-filesystem case-insensitive="false"
		create-home="true" />
	<!--
		Use this section to define custom commands. Custom commands can also
		override already existing commands
	-->
	<commands use-default="false">
		<command name="MYHELP">
			<beans:bean class="org.apache.ftpserver.examples.MYHELP" />
		</command>
	</commands>
	<!-- Define the available languages -->
	<messages languages="se, no ,da" />
</server>      

1.3.1.1 server的配置

 這一部分在官網寫的很清楚,可以檢視http://mina.apache.org/ftpserver/configuration.html。在這裡本人憑借英語四級的水準鬥膽翻譯一下。

屬性 描述 必填 預設值
id 配置的server在該XML檔案中的唯一辨別
max-logins 最大同時線上使用者數 10
max-anon-logins 最大同時線上匿名使用者數 10
anon-enabled 是否啟動匿名登入 true
max-login-failures 最大登入失敗次數,達到該次數後連接配接自動斷開。 3
login-failure-delay 失敗登入後連接配接延遲時間(以毫秒為機關)。防止惡意使用者暴力破解密碼。 500

1.3.1.2 listeners 配置

 Listeners元件是負責在ftp server指定的端口上監聽client端建立連接配接和執行指令。一個AFS可以同時有多個listeners。Listeners以name屬性作為唯一辨別,預設的listener的name為”default”.

Attribute Description Required Default value
name Listener名稱,如果設定listener名稱為“default”,那麼該listener的設定會覆寫預設的listner。
port Listener監聽的端口 21
local-address Server 綁定的本地服務位址 All available
implicit-ssl 是否實作SSL的支援 false
idle-timeout 空閑連接配接保持連接配接狀态的時長(機關為秒). 300

1.3.2 AFS權限控制

 AFS的權限控制有兩種方式:檔案控制和資料庫控制。

1.3.2.1 檔案控制權限的配置

通過檔案控制隻需在server的配置檔案中添加以下配置

<file-user-manager file="users.properties" encrypt-passwords="true" />

其中users.properties檔案權限控制檔案,encrypt-passwords可以指定密碼存儲的方式,有效值包括“clear”(明文),“md5”,”salted”,這個salted不知道是什麼意思,應該和MD5類似吧,估計也是一種加密标準,而且官方鼓勵使用salted.

AFS在安裝時就提供了一個預設的users.properties檔案,配置項一目了然。

1.3.2.1 資料庫控制權限

資料庫對使用者的權限的管理與通過檔案類似,不同就是把對使用者的配置移到了資料庫的表裡面。而且AFS提供了建表的sql語句,檔案存放在res下的ftp-db.sql。

關于此處的相關配置可以參見上面的完成配置執行個體,該部分的需要配置insert-user,update-user,delete-user,select-user,select-all-users,is-admin,authenticate。一般情況下我們都會用我們不會單獨用AFS來增删改使用者,但是update-user、delete-user和insert-user一個都不能少,不然AFS啟動時校驗通不過。另外我們通常會希望AFS的使用者管理與我們的應用系統采用統一管理,也就是不再為AFS建立專用的使用者管理表,這時候我們可以通過修改select-user、is-admin、authenticate等配置項來完成。不要以為随便改寫查詢sql都可以哦,AFS在處理這幾個查詢時是通過類似rs.getString(列名)的形式獲得記錄的,也就是說無論我們怎麼修改sql,但是資料列名或者别名一定要和AFS提供的預設查詢語句比對上,不然會有無效列名的錯誤。

關于AFS的配置大概就這些,總的來說各個配置項還是很直覺的。現在我們就可以執行bin\ftpd.sh啟動AFS了。

2.作為window系統的服務

如果是在windows平台的話,AFS還可以注冊為windows的系統服務來運作。方法也很簡單,直接執行:

<yourhome>bin\service install

運作成功後,進到windows的服務管理視窗就可以看到我們新注冊的名為Apache FtpServer的服務了。當然服務名是可以指定的,隻需:

<yourhome>bin\service install <your服務名>

此時建立的服務名就為Apache Ftp Servef <你指定的服務名>

如果我們想注冊服務時用特定的配置檔案可以執行如下指令:

<yourhome>bin\service install <your服務名> <你需要執行的檔案路徑>

解除安裝已經注冊的windows服務隻需:

<yourhome>bin\service remove <your服務名(不輸入為預設)>

3.結合spring配置嵌入我們自己的系統

以上我們介紹的是獨立部署AFS,其實AFS還可以結合spring嵌入到我們的應用程式中。

修改web.xml檔案添加spring的相關配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" 
	xmlns="http://java.sun.com/xml/ns/j2ee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 
	http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
	
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>classpath*:/applicationContext*.xml</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
</web-app>      

 src目錄下建立spring配置檔案applicationContext-ftpserver.xml

配置方法與前面提到的server配置參數相同,隻是此時的server作為spring的一個bean來處理。格式如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans
	xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
	">
	<description>ftpserver demo</description>
	<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="java:comp/env/jdbc/etlui"/>
    </bean>
	<server xmlns="http://mina.apache.org/ftpserver/spring/v1"
			xmlns:beans="http://www.springframework.org/schema/beans" 
			xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
			xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
	   		http://mina.apache.org/ftpserver/spring/v1 http://mina.apache.org/ftpserver/ftpserver-1.0.xsd"
	    id="demoserver" 	
	    max-logins="500"
		anon-enabled="false"
		max-anon-logins="123"
		max-login-failures="124"
		login-failure-delay="125">
--具體配置參數
</server>
<bean id="ctroller" class="com.harvey.ftpd.ServiceController" init-method="init">
		<property name="server">
			<ref bean="demoserver"/>
		</property>
		<property name="server2">
			<ref bean="demoserver2"/>
		</property>
		
	</bean>
</beans>      

其中ServiceController代碼如下:

public class ServiceController {
	private FtpServer server = null;
	
	public void init() {
		try {
			server.start();
		} catch (FtpException e) {
			e.printStackTrace();
		}
		System.out.println("system exit");
	}

	public FtpServer getServer() {
		return server;
	}

	public void setServer(FtpServer server) {
		this.server = server;
	}

}           

現在我們就可以将AFS納入到我們的應用程式的管理範疇之内。

另外再說些其他的,因為server作為spring的一個bean來處理,是以可以配置多個server,也就是為主機配置多個AFS server,雖然可以這樣的配置,但是覺得也沒有這種必要,隻是覺得好玩可以配一下。