南充網(wǎng)站建設(shè)服務(wù)商現(xiàn)在如何進(jìn)行網(wǎng)上推廣
文章目錄
- 前言
- 一、FTP、SFTP是什么?
- 1.FTP
- 2.SFTP
- 二、安裝FTP
- 1.安裝vsftp服務(wù)
- 2.啟動(dòng)服務(wù)并設(shè)置開機(jī)自啟動(dòng)
- 3.開放防火墻和SELinux
- 4.創(chuàng)建用戶和FTP目錄
- 4.修改vsftpd.conf文件
- 5.啟動(dòng)FTP服務(wù)
- 6.問題
- 二、安裝SFTP
- 1、 創(chuàng)建用戶
- 2、配置ssh和權(quán)限
- 3、建立目錄并賦予權(quán)限
- 4、啟動(dòng)并測(cè)試
- 三、ftp、sftp結(jié)合springboot
- 1、ftp整合springboot
- 2、sftp整合springboot
- 總結(jié)
前言
在一般項(xiàng)目開發(fā)工程中,我們大多數(shù)會(huì)使用文件服務(wù),比如上傳圖片、各種文檔之類的。
供我們選擇的方式很多,比如第一種直接通過Java的File對(duì)象存儲(chǔ)在本地,然后部署時(shí)候修改linux環(huán)境下的路徑,這種方式簡(jiǎn)單粗暴;
第二種就是在連網(wǎng)的情況下,直接使用OSS對(duì)象存儲(chǔ),比如阿里云OSS對(duì)象存儲(chǔ),當(dāng)然這種是要花錢的,如果不花錢的話,
也可以自己本地搭建一個(gè)OSS本地對(duì)象存儲(chǔ);
第三種就是我們今天要說的,在Linux服務(wù)器上面通過ftp服務(wù)、sftp服務(wù)搭建一個(gè)文件服務(wù),其實(shí)本質(zhì)上第一種類似,直接讀取磁盤上面的文件;然后我們通過springboot程序來讀取操作;
一、FTP、SFTP是什么?
1.FTP
- FTP 是不安全的,因?yàn)樗趥鬏斶^程中使用明文傳輸密碼和數(shù)據(jù),容易受到竊聽和攻擊。
- FTP 默認(rèn)使用端口21進(jìn)行控制連接,和端口20進(jìn)行數(shù)據(jù)連接。
- FTP 提供了基本的文件上傳和下載功能,以及簡(jiǎn)單的目錄操作。
- 適合于內(nèi)部網(wǎng)絡(luò)環(huán)境或者傳輸不敏感的數(shù)據(jù),對(duì)安全性要求不高的場(chǎng)景。
- FTP有主動(dòng)和被動(dòng)模式兩種,簡(jiǎn)單講,主動(dòng)就是客戶端隨機(jī)開了端口,然后服務(wù)器端主動(dòng)連接,然后傳輸數(shù)據(jù);被動(dòng)就是服務(wù)器先開了一個(gè) 大于 1024 小于65535的端口,然后客戶主動(dòng)去連接,然后傳輸數(shù)據(jù);至于更詳細(xì)的參考其它說明文章。
2.SFTP
- SFTP 基于SSH協(xié)議,所有的數(shù)據(jù)傳輸都被加密,包括身份驗(yàn)證信息和傳輸?shù)奈募?nèi)容,因此提供了更高的安全性。
- SFTP 默認(rèn)使用SSH的端口(通常是22),只需要一個(gè)端口來完成所有的傳輸。
- SFTP 不僅支持文件傳輸,還可以進(jìn)行更多高級(jí)的文件管理操作,比如權(quán)限管理和符號(hào)鏈接的操作。
- 適合于需要保證數(shù)據(jù)傳輸安全性的場(chǎng)景,特別是在Internet環(huán)境中傳輸敏感數(shù)據(jù)或者需要進(jìn)行復(fù)雜文件管理的情況下。
總結(jié)來說,選擇使用FTP還是SFTP取決于你的具體需求,特別是對(duì)于數(shù)據(jù)安全性的要求。如果需要更高的安全性和更豐富的功能,建議選擇SFTP。
二、安裝FTP
1.安裝vsftp服務(wù)
yum -y install vsftpd
服務(wù)器需要聯(lián)網(wǎng)。
2.啟動(dòng)服務(wù)并設(shè)置開機(jī)自啟動(dòng)
systemctl start vsftpd # 啟動(dòng)vsftpd
systemctl enable vsftpd.service # 設(shè)置開機(jī)自啟動(dòng)
3.開放防火墻和SELinux
主要是為了減少麻煩的產(chǎn)生,關(guān)閉防火墻和selinux,等搭建成功可以開啟防火墻和相應(yīng)的端口。
systemctl stop firewalld.service #關(guān)閉防火墻
systemctl disable firewalld.service #并設(shè)置開機(jī)自啟# 修改 /etc/selinux/config 將SELINUX=enforcing改為disabled
vim /etc/selinux/config
setenforce 0 #使修改后的配置文件生效
4.創(chuàng)建用戶和FTP目錄
ftpuser1和ftpuser1為該FTP服務(wù)創(chuàng)建的用戶,而/web/www/html作為兩個(gè)用戶的訪問目錄(限制)。
創(chuàng)建文件目錄并配置權(quán)限:
mkdir -p /web/www/html
chmod -R 775 /web/www/html
創(chuàng)建ftp組以及用戶:
我們創(chuàng)建的team1和team2用戶,為了系統(tǒng)安全考慮,當(dāng)然不希望能讓這兩個(gè)賬號(hào)的登錄系統(tǒng),要使得FTP組的用戶不能的登錄系統(tǒng),則需要為FTP用戶統(tǒng)一建立在不能登錄系統(tǒng)的shell中,就拿 /sbin/nologin 來實(shí)現(xiàn);
-g:指定所屬組
-d:指定家目錄
-M:不創(chuàng)建家目錄
-s:不登錄系統(tǒng)
#創(chuàng)建組ftp
groupadd ftpgroup # 創(chuàng)建用戶
useradd -g ftpgroup -d /web/www/html -M -s /sbin/nologin ftpuser1
useradd -g ftpgroup -d /web/www/html -M -s /sbin/nologin ftpuser2
#為用戶創(chuàng)建密碼
passwd ftpuser1@123456
passwd ftpuser2@123456# 修改/web/www/html目錄為ftpgroup組
chown root:ftpgroup /web/www/html
4.修改vsftpd.conf文件
先將/etc/vsftpd/vsftpd.conf配置文件備份(防止后面出錯(cuò)后沒法還原),然后進(jìn)行修改:
cd /etc/vsftpd/
cp vsftpd.conf vsftpd.conf.backup
vim vsftpd.conf
進(jìn)入該配置文件后,將101、102、104行的內(nèi)容去掉注釋:
將剩下注釋的內(nèi)容全部刪除后剩下的內(nèi)容:
解釋常用的:
anonymous_enable=YES #是否開啟匿名用戶,因?yàn)檫@里指定用戶所以修改為NO
local_enable=YES #是否允許本地用戶登錄,默認(rèn)允許
write_enable=YES #是否允許賬號(hào)有寫的權(quán)限
local_umask=022 :掩碼
#本地用戶創(chuàng)建文件目錄都會(huì)默認(rèn)777-022=755,最終文件目錄的權(quán)限為755
#然而創(chuàng)建文件會(huì)默認(rèn)666-022=644,最終創(chuàng)建的文件權(quán)限為644
dirmessage_enable=YES # 進(jìn)入某個(gè)目錄會(huì)提示
根據(jù)實(shí)驗(yàn)要求創(chuàng)建的兩個(gè)用戶只能在受限于/web/www/html文件目錄下,跟以下兩條命令的搭配效果有關(guān):
chroot_local_user=YES
chroot_list_enable=NO # 激活chroot功能
#在文件 /etc/vsftpd/chroot_list 中列出的用戶不能切換到其他目錄
chroot_list_file=/etc/vsftpd/chroot_list #設(shè)置鎖定用戶在根目錄列表的文件
添加配置文件:
除了以上的還需添加以下的配置
local_root=/web/www/html #設(shè)置本地用戶的根目錄
allow_writeable_chroot=YES #允許 chroot限制,否則出現(xiàn)連接錯(cuò)誤。
最終文件配置信息 :
創(chuàng)建 /etc/vsftpd/chroot_list 文件:
vim /etc/vsftpd/chroot_list
添加 ftpsuer1和 ftpsuer2注意換行
5.啟動(dòng)FTP服務(wù)
systemctl restart vsftpd
# 在客戶端上需要先安裝 ftp 服務(wù)
yum -y install ftp
6.問題
問題1
、安裝vsftpd時(shí)候,可能包yum源的問題,更換阿里云、或者其它的yum源即可;問題2
、Security: Bad IP connecting 錯(cuò)誤
ftp客戶端軟件連接vsftpd服務(wù)報(bào)此錯(cuò)誤,大概原因是在連接中變換了IP地址。
解決辦法:
vim /etc/vsftpd/vsftpd.conf
# 添加:
pasv_promiscuous=YES
# 保存后退出,重啟 vsftpd
systemctl restart vsftpd
pasv_promiscuous選項(xiàng)參數(shù)說明:
此選項(xiàng)激活時(shí),將關(guān)閉PASV模式的安全檢查。該檢查確保數(shù)據(jù)連接和控制連接是來自同一個(gè)IP地址。
小心打開此選項(xiàng)。此選項(xiàng)唯一合理的用法是存在于由安全隧道方案構(gòu)成的組織中。默認(rèn)值為NO。
合理的用法是:在一些安全隧道配置環(huán)境下,或者更好地支持FXP時(shí)(才啟用它)。
FTP模式與數(shù)據(jù)端口:
FTP 分為兩類,PORT FTP和PASV FTP,PORT FTP是一般形式的FTP。這兩種FTP在建立控制連接時(shí)操作是一樣的,都是由客戶端首先和FTP服務(wù)器的控制端口(默認(rèn)值為21)建立控制鏈接,并通過此鏈接進(jìn)行傳輸操作指令。它們的區(qū)別在于使用數(shù)據(jù)傳輸端口(ftp- data)的方式。PORT FTP由FTP服務(wù)器指定數(shù)據(jù)傳輸所使用的端口,默認(rèn)值為20。PASV FTP由FTP客戶端決定數(shù)據(jù)傳輸?shù)亩丝凇?PASV FTP這種做法,主要是考慮到存在防火墻的環(huán)境下,由客戶端與服務(wù)器進(jìn)行溝通(客戶端向服務(wù)器發(fā)出數(shù)據(jù)傳輸請(qǐng)求中包含了數(shù)據(jù)傳輸端口),決定兩者之間的數(shù)據(jù)傳輸端口更為方便一些。
問題3
: ftp登錄時(shí),解決報(bào)錯(cuò)530,500,421等錯(cuò)誤
第一步:cat /etc/passwd 查看是否是之前添加的用戶,并確定是否存在。
若沒有創(chuàng)建成功,則使用useradd -s /sbin/nologin team1等用戶
然后通過設(shè)置密碼來passwd team1
第二步驟:如果報(bào)錯(cuò):530 Login incorrect. Login failed.
cat /etc/passwd,查看你登陸的賬戶主目錄和登陸shell對(duì)應(yīng)的是什么,我的是/sbin/nologin
用戶名:口令:用戶標(biāo)識(shí)號(hào):組標(biāo)識(shí)號(hào):注釋性描述:主目錄:登錄Shell;
查看cat /etc/shells是否有你用戶的主目錄和登陸shell ,沒有進(jìn)行添加,保存,退出。
我的也是開始沒有,然后添加了一行;
最后一點(diǎn)
: 一定要注意文件夾和文件得所屬,一定是剛才新建得用戶的,不然沒有權(quán)限的錯(cuò)誤,
如500 OOPS: vsftpd: refusing to run with writable root inside chroot() Login failed. 或者 421 Service not available, remote server has closed connection。
二、安裝SFTP
基本語(yǔ)法:
-c comment 指定一段注釋性描述。備注文字保存在passwd的備注欄中。
-d 目錄 指定用戶主目錄,如果此目錄不存在,則同時(shí)使用-m選項(xiàng),可以創(chuàng)建主目錄。
-g 用戶組 指定用戶所屬的用戶組。
-G 用戶組,用戶組 指定用戶所屬的附加組。
-s Shell文件 指定用戶的登錄Shell。
-u 用戶號(hào) 指定用戶的用戶ID號(hào),如果同時(shí)有-o選項(xiàng),則可以重復(fù)使用其他用戶的標(biāo)識(shí)號(hào)。
-D:變更預(yù)設(shè)值。
-e:指定賬號(hào)的有效期限,缺省表示永久有效。
-f:指定在密碼過期后多少天即關(guān)閉該賬號(hào)。
-m:自動(dòng)建立用戶的登入目錄。
-M:不要自動(dòng)建立用戶的登入目錄。
-n:取消建立以用戶名稱為名的群組。
-r:建立系統(tǒng)賬號(hào)。
說明
:sftp采用的是ssh加密隧道,安裝性方面較ftp強(qiáng),而且依賴的是系統(tǒng)自帶的ssh服務(wù),但速度較ftp慢。
1、 創(chuàng)建用戶
我們要建立一個(gè)專門管理sftp的用戶或者用戶組,方便我們管理權(quán)限。 如果有多個(gè)sftp用戶建議新建用戶組,此次試驗(yàn)我只用一個(gè)用戶,為了方便用用戶名的方式去進(jìn)行。
groupadd sftpgroup
useradd -s /sbin/nologin -g sftpgroup -M sftp_user
passwd sftp_user # sftpuse@123456
2、配置ssh和權(quán)限
關(guān)閉SElinux:
vim /etc/sysconfig/selinux
# 找到并修改這行為
SELINUX=disabled
tips
:SELINUX默認(rèn)是開啟的,這樣重啟sshd會(huì)提示權(quán)限不夠,設(shè)置為disabled需要重啟生效。
修改sshd配置文件:
將Subsystem sftp /usr/libexec/sftp-server 注釋掉,在文件末尾添加以下幾行:
vim /etc/ssh/sshd_configSubsystem sftp internal-sftp
X11Forwarding no
AllowTcpForwarding noMatch User sftp_user
ChrootDirectory /data
ForceCommand internal-sftp
如下圖:
3、建立目錄并賦予權(quán)限
mkdir /data
usermod -d /data sftp_user
# 根目錄必須是root
chown root:root /data
chmod 755 /data/
# 或者
chown -R sftp_root:root /data/
# 在data下創(chuàng)建file文件夾存放我們上長(zhǎng)傳的文件
mkdir -p /data/file
# 必須更改用戶的所屬
chown -R sftp_user:sftpgroup /data/file/
上面說了,因?yàn)槭褂昧薈hrootDirectory /data作為qhlh的sftp根目錄。
ChrootDirectory設(shè)置的目錄權(quán)限及其所有的上級(jí)文件夾權(quán)限,屬主和屬組必須是root;
ChrootDirectory設(shè)置的目錄權(quán)限及其所有的上級(jí)文件夾權(quán)限,只有屬主能擁有寫權(quán)限,也就是說權(quán)限最大設(shè)置只能是755;
由于/data是root創(chuàng)建的,權(quán)限755,如果sftp_user直接sftp過去沒有權(quán)限寫入,因此,需要/data下創(chuàng)建新目錄并給與sftp_user權(quán)限;
4、啟動(dòng)并測(cè)試
systemctl restart sshd.service# sftp本地登錄
sftp sftp_user@192.168.1.160
# 上傳
put /opt/test.txt
# 下載
get test.txt /opt
效果如下圖:
問題
:
Write failed: Broken pipe > Couldn‘t read packet: Connection reset by peer SFTP服務(wù)器連接出現(xiàn)的問題
Write failed: Broken pipe
Couldn’t read packet: Connection reset by peer
這個(gè)問題的原因是ChrootDirectory的權(quán)限問題,你設(shè)定的目錄必須是root用戶所有,否則就會(huì)出現(xiàn)問題。
所以請(qǐng)確保sftp用戶根目錄的所有人是root, 權(quán)限是 750 或者 755。
注意以下兩點(diǎn)原則:
目錄開始一直往上到系統(tǒng)根目錄為止的目錄擁有者都只能是 root,用戶組可以不是 root。
目錄開始一直往上到系統(tǒng)根目錄為止都不可以具有群組寫入權(quán)限。
三、ftp、sftp結(jié)合springboot
注意:整合這一塊,只提供關(guān)鍵信息,就不完全提供代碼了。
1、ftp整合springboot
搭建單體springboot項(xiàng)目框架,引入基本依賴:
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency><groupId>commons-net</groupId><artifactId>commons-net</artifactId><version>3.9.0</version>
</dependency>
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-io</artifactId><version>1.3.2</version>
</dependency>
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-lang3</artifactId><version>3.12.0</version>
</dependency>
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId>
</dependency>
項(xiàng)目目錄結(jié)構(gòu):
配置連接信息:
Java配置:
FTPClient配置:
FtpService接口:
FtpService接口實(shí)現(xiàn):
@RequiredArgsConstructor
@Service
public class FtpServiceImpl implements FtpService {private final FTPClient ftpClient;@Overridepublic boolean uploadFile(MultipartFile file) {try {String remoteFilePath = "/w/n";// 設(shè)置Passive Modethis.ftpClient.enterLocalPassiveMode();// 設(shè)置緩沖區(qū)大小為1MBthis.ftpClient.setBufferSize(1024 * 1024);this.ftpClient.setFileType(FTP.BINARY_FILE_TYPE);this.createRemoteDirectory(this.ftpClient, remoteFilePath);// 切換工作目錄boolean success = this.ftpClient.changeWorkingDirectory(remoteFilePath);if (!success) {System.out.println("切換工作目錄失敗:" + remoteFilePath);return false;}if (file.isEmpty()) {System.out.println("上傳的文件不能為空");return false;}String remoteFileName = this.md5(Objects.requireNonNull(file.getOriginalFilename()));success = this.ftpClient.storeFile(remoteFileName, file.getInputStream());if (success) {System.out.println("文件上傳成功");} else {System.out.println("文件上傳失敗");}return success;} catch (IOException e) {e.printStackTrace();System.out.println("文件上傳失敗:" + e.getMessage());return false;}}// 其它實(shí)現(xiàn)}
測(cè)試:
API接口層:
2、sftp整合springboot
目錄結(jié)構(gòu)和上面的一樣:
引入sftp的依賴:
<!-- SFTP -->
<dependency><groupId>com.jcraft</groupId><artifactId>jsch</artifactId><version>0.1.55</version>
</dependency>
配置連接信息:
接口和實(shí)現(xiàn):
SftpUtils工具類:
@Slf4j
@Component
public class SftpUtils {@Resourceprivate SftpProperties sftpProperties;/*** 創(chuàng)建SFTP連接*/public ChannelSftp createSftp() throws JSchException {JSch jsch = new JSch();log.info("Try to connect sftp[" + sftpProperties.getUsername() + "@" + sftpProperties.getHost() + "]");Session session = createSession(jsch, sftpProperties.getHost(), sftpProperties.getUsername(), sftpProperties.getPort());session.setPassword(sftpProperties.getPassword());session.setConfig("StrictHostKeyChecking", "no");// 默認(rèn)情況下,JSch庫(kù)本身并沒有會(huì)話超時(shí)時(shí)間。// 為了避免長(zhǎng)時(shí)間無活動(dòng)連接占用資源或因網(wǎng)絡(luò)問題導(dǎo)致連接掛起而不被釋放,通常建議設(shè)置會(huì)話超時(shí),(單位:毫秒)session.setTimeout(30000);session.connect();log.info("Session connected to {}.", sftpProperties.getHost());Channel channel = session.openChannel(sftpProperties.getProtocol());channel.connect();log.info("Channel created to {}.", sftpProperties.getHost());return (ChannelSftp) channel;}/*** 創(chuàng)建 Session*/public Session createSession(JSch jsch, String host, String username, Integer port) throws JSchException {Session session = null;if (port <= 0) {session = jsch.getSession(username, host);} else {session = jsch.getSession(username, host, port);}if (session == null) {throw new RuntimeException(host + "session is null");}return session;}/*** 關(guān)閉連接*/public void disconnect(ChannelSftp sftp) {try {if (sftp != null) {if (sftp.isConnected()) {sftp.disconnect();} else if (sftp.isClosed()) {log.error("sftp 連接已關(guān)閉");}if (sftp.getSession() != null) {sftp.getSession().disconnect();}}} catch (JSchException e) {log.error("sftp 斷開連接失敗,原因:{}", e.getMessage(), e);}}}
單元測(cè)試:
注意
:連接的時(shí)候,確保端口和IP可以訪問。
總結(jié)
最后,終于完了,內(nèi)容還是有點(diǎn)多,有些細(xì)節(jié)未考慮到,勿噴。