SMB Java协议应用

  · SMB 协议

  SMB(Server Message Block)协议,主要用途是文件共享,但除了文件共享还包括:

  · 数据包/版本协商(用于确定服务器和客户端都支持的具有最高功能级别的数据包版本)

  · 确定网络上的其他Microsoft SMB协议服务器或网络浏览

  · 网络打印

  · 文件,目录和共享访问身份验证

  · 文件和记录锁定

  · 文件和目录更改通知

  · 扩展文件属性处理

  · Unicode支持

  · 机会锁(协调客户端和服务器的数据一致性,使服务器和客户端数据同步)

  SMB 是一种请求-响应(客户端-服务端)协议。通过 SMB 协议,客户端应用程序可以在各种网络环境下读、写服务器上的文件,以及对服务器程序提出服务请求。此外通过 SMB 协议,应用程序可以访问远程服务器端的文件、以及打印机等资源。

​  SMB默认使用端口TCP/139和TCP/445端口,SMB协议目前共三个版本,本文对SMB1.0版本协议进行应用实现。

  SMB协议简介在网上有很多介绍,各位可以自行进行百度查看。

  · 创建共享文件

  共享文件创建在Win10系统中,Win10中创建共享文件相对比较简单,选中需要共享的文件夹右键选择‘属性’:
在这里插入图片描述
  首选点击’共享(S)…‘按钮出现右侧界面,在右侧界面,选择对应的用户并设置用户权限,最后点击’共享(H),一直‘下一步’就完成了共享文件的设置。

  需要注意的是由于SMB1.0版本协议已处于落伍边缘,Win10默认是不开启SMB1.0的,需要手动开启,在控制面板‘程序与功能’中选择开启即可:
在这里插入图片描述
  · Maven 依赖

<dependency>
    <groupId>jcifs</groupId>
    <artifactId>jcifs</artifactId>
    <version>1.3.17</version>
</dependency>
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.4</version>
</dependency>

  · Java SMB 工具类

package com.arhorchin.securitit.protocol.smb;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;

import org.apache.log4j.Logger;

import jcifs.smb.NtlmPasswordAuthentication;
import jcifs.smb.SmbFile;
import jcifs.smb.SmbFileInputStream;
import jcifs.smb.SmbFileOutputStream;

public class SmbUtil {

    /**
     * logger.
     */
    private static Logger logger = Logger.getLogger(SmbUtil.class);

    /**
     * SMB下载文件.
     * @param remoteIp 远程IP.
     * @param remoteUrl 远程地址.
     * @param username 远程用户.
     * @param password 远程密码.
     * @param filename 远程文件.
     * @return 共享文件.
     */
    public static byte[] smbDownload(String remoteIp, String remoteUrl, String username, String password,
            String filename) {
        SmbFile remoteFile = null;
        InputStream remoteFileIs = null;
        ByteArrayOutputStream remoteFileBaos = null;
        NtlmPasswordAuthentication remoteAuth = null;

        try {
            remoteAuth = new NtlmPasswordAuthentication(remoteIp, username, password);
            remoteFile = new SmbFile(remoteUrl, remoteAuth);
            if (!remoteFile.exists()) {
                remoteFile.mkdirs();
            }
            remoteFile = new SmbFile(remoteUrl + "//" + filename, remoteAuth);
            remoteFileBaos = new ByteArrayOutputStream();
            remoteFileIs = new BufferedInputStream(new SmbFileInputStream(remoteFile));
            byte[] buffer = new byte[1024];
            while (remoteFileIs.read(buffer) != -1) {
                remoteFileBaos.write(buffer);
                buffer = new byte[1024];
            }

            return remoteFileBaos.toByteArray();
        } catch (Exception ex) {
            logger.error(ex);
            return null;
        } finally {
            try {
                remoteFileIs.close();
                remoteFileBaos.close();
            } catch (Exception ex) {
                logger.error(ex);
            }
        }
    }

    /**
     * SMB上传文件.
     * @param remoteIp 远程IP.
     * @param remoteUrl 远程地址.
     * @param username 远程用户.
     * @param password 远程密码.
     * @param filename 远程文件.
     * @param fileBytes 待上传文件.
     * @return 上传结果.
     */
    public static boolean smbUpload(String remoteIp, String remoteUrl, String username, String password,
            String filename, byte[] fileBytes) {
        SmbFile remoteFile = null;
        BufferedOutputStream remoteFileBos = null;
        NtlmPasswordAuthentication remoteAuth = null;

        try {
            remoteAuth = new NtlmPasswordAuthentication(remoteIp, username, password);
            remoteFile = new SmbFile(remoteUrl, remoteAuth);
            if (!remoteFile.exists()) {
                remoteFile.mkdirs();
            }
            remoteFile = new SmbFile(remoteUrl + "//" + filename, remoteAuth);
            remoteFileBos = new BufferedOutputStream(new SmbFileOutputStream(remoteFile));
            remoteFileBos.write(fileBytes);
            return true;
        } catch (Exception ex) {
            logger.error(ex);
            ex.printStackTrace();
            return false;
        } finally {
            try {
                remoteFileBos.close();
            } catch (Exception ex) {
                logger.error(ex);
            }
        }
    }

    /**
     * SMB删除文件.
     * @param remoteIp 远程IP.
     * @param remoteUrl 远程地址.
     * @param username 远程用户.
     * @param password 远程密码.
     * @param filename 远程文件.
     * @return 删除结果.
     */
    public static boolean smbDelete(String remoteIp, String remoteUrl, String username, String password,
            String filename) {
        SmbFile remoteFile = null;
        NtlmPasswordAuthentication remoteAuth = null;

        try {
            remoteAuth = new NtlmPasswordAuthentication(remoteIp, username, password);
            remoteFile = new SmbFile(remoteUrl, remoteAuth);
            if (!remoteFile.exists()) {
                remoteFile.mkdirs();
            }
            remoteFile = new SmbFile(remoteUrl + "//" + filename, remoteAuth);
            remoteFile.delete();
            return true;
        } catch (Exception ex) {
            logger.error(ex);
            return false;
        }
    }

}

  测试类如下:

package com.arhorchin.securitit.protocol.smb;

import java.io.File;

import org.apache.commons.io.FileUtils;

public class SmbUtilTester {

    public static void main(String[] args) throws Exception {
        String remoteIp = "127.0.0.1";
        String remoteUrl = "smb://127.0.0.1/Storage/";
        String username = "xxxxxx"; // 登录用户名.
        String password = "xxxxxx"; // 登录密码.
        String filename = "demo.pdf";
        byte[] fileBytes = FileUtils.readFileToByteArray(new File("C:/Users/Administrator/Downloads/个人文件/demo.pdf"));
        // 上传文件.
        SmbUtil.smbUpload(remoteIp, remoteUrl, username, password, filename, fileBytes);
        // 下载文件.
        byte[] downBytes = SmbUtil.smbDownload(remoteIp, remoteUrl, username, password, filename);
        System.out.println(downBytes.length);
        // 删除文件.
        SmbUtil.smbDelete(remoteIp, remoteUrl, username, password, filename);
    }

}

  上面测试类执行的同时,观察共享文件夹,可以看到:

  1) 共享文件夹首先上传了一个文件demo.pdf。

  2) 测试类从共享文件夹下载了刚才上传的文件,并输出了文件长度。

  3) 共享文件夹内的文件被删除掉了。

  · 总结

  · jcifs:jcifs依赖只能支持SMB1.0版本协议的实现,在实际应用时需要注意所用协议版本。

  · SmbUtil工具类可以直接复制使用,已经经过简单测试,只需按照文中要求导入Maven依赖即可。

  · SmbUtil中写法已经避免了用户名和密码中包含特殊字符的问题,如果使用完整地址方式访问,无法有效处理用户名和密码中的特殊字符。

猜你喜欢

转载自blog.csdn.net/securitit/article/details/107501066
SMB