Java创建sftp账户并设置秘钥

sftp服务器配置

点击此处

依赖
<!-- https://mvnrepository.com/artifact/com.jcraft/jsch -->
<dependency>
    <groupId>com.jcraft</groupId>
    <artifactId>jsch</artifactId>
    <version>0.1.54</version>
</dependency>

<!-- https://mvnrepository.com/artifact/ch.ethz.ganymed/ganymed-ssh2 -->
<dependency>
    <groupId>ch.ethz.ganymed</groupId>
    <artifactId>ganymed-ssh2</artifactId>
    <version>build210</version>
</dependency>
ssh2工具类
package com.tianshl;

import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.InputStreamReader;

/**
 * @author tianshl
 * @version 2018/5/22 下午1:29
 */
@Component
public class Ssh2Utils {
    private Connection connection;
    
    /**
     * 登录
     */
    public void login(String host, String username, String password) throws Exception {
        connection = new Connection(host);
        connection.connect();

        if(!connection.authenticateWithPassword(username, password)){
            throw new Exception("管理员账号或密码错误");
        }
    }

    /**
     * 退出
     */
    public void logout() {
        try {
            if (connection != null) connection.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 执行指令
     */
    public String execCommand(final String command) {
        final StringBuilder sb = new StringBuilder(256);
        // 连接的通道
        Session session = null;
        try {
            // 创建session
            session = connection.openSession();

            // 这句非常重要,开启远程的客户端
            session.requestPTY("vt100", 80, 24, 640, 480, null);

            // 开启后睡眠4秒
            // Thread.sleep(4000);

            // 执行命令
            session.execCommand(command);

            // 起始时间,避免连通性陷入死循环
            long start = System.currentTimeMillis();

            BufferedReader br = new BufferedReader(new InputStreamReader(new StreamGobbler(session.getStdout())));

            char[] arr = new char[512];
            int read;

            while (true) {
                // 将结果流中的数据读入字符数组
                read = br.read(arr, 0, arr.length);

                // 推延5秒就退出[针对连通性测试会陷入死循环]
                if (read < 0 || (System.currentTimeMillis() - start) > 5000) break;

                // 将结果拼装进StringBuilder
                sb.append(new String(arr, 0, read));
            }
        } catch (Throwable e) {
            e.printStackTrace();
        } finally {
            // 关闭通道
            if (session != null) session.close();
        }
        return sb.toString();
    }
}
service

package com.tianshl;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.List;
import java.util.Map;

/**
 * service for sftp
 */
@Service
@Transactional
public class SftpService {

    // sftp 服务器地址 
    @Value("${sftp.host}")
    private String host;

    // sftp 服务器管理员账号
    @Value("${sftp.root.username}")
    private String username;
    
    // sftp 服务器管理员密码
    @Value("${sftp.root.password}")
    private String password;

    // ssh2工具类
    private final Ssh2Utils ssh2Utils;

    public SftpService(Ssh2Utils ssh2Utils) {
        this.ssh2Utils = ssh2Utils;
    }

    /**
     *  创建linux用户 创建相关目录 以及 权限设置
     */
    private JSONObject createUser (Ssh2Utils ssh2Utils, String sftpUsername) {

        // 返回信息
        JSONObject resp = new JSONObject();
        resp.put("success", false);

        // 家目录
        String home = "/sftp/" + sftpUsername;
        
        // 创建账号
        try {

            // 创建账号命令
            String stdOut = ssh2Utils.execCommand("useradd -d " + home + " -m -g sftp -s /bin/false " + sftpUsername);
            // 用户名已存在
            if (stdOut.contains("useradd: user '" + sftpUsername + "' already exists")) {
                ssh2Utils.logout();
                resp.put("success", false);
                resp.put("msg", "账户名称'" + sftpUsername + "'已存在,请更换其他名称.");
                return resp;
            }

            List<String> command = Lists.newArrayList();
            // 设置家目录属主
            command.add("chown root:sftp " + home);

            // 设置家目录权限
            command.add("chmod 755 " + home);

            // 创建目录 (.ssh秘钥相关, data存放数据文件)
            command.add("mkdir " + home + "/{.ssh,data}");

            // 新增的目录设置属主
            command.add("chown " + sftpUsername + ":sftp " + home + "/{.ssh,data}");

            // 新增目录设置权限
            command.add("chmod 777 " + home + "/data");
            command.add("chmod 700 " + home + "/.ssh");

            // 执行以上指令
            ssh2Utils.execCommand(String.join(";", command));

        } catch (Exception e) {
            e.printStackTrace();

            resp.put("msg", "创建账号失败");
            return resp;
        }

        resp.put("success", true);
        return resp;
    }

    /**
     *  生成秘钥
     */
    private JSONObject genSecretKey(Ssh2Utils ssh2Utils, String sftpUsername) {

        // 返回信息
        JSONObject resp = new JSONObject();
        resp.put("success", false);

        String sshDirectory = String.format("/sftp/%s/.ssh", sftpUsername);

        // 指令集
        List<String> command = Lists.newArrayList();
        // 删除旧的私钥
        command.add(String.format("rm -f %s/id_rsa*", sshDirectory));
        // 生成新的秘钥(私钥+公钥)
        command.add(String.format("ssh-keygen -f %s/id_rsa -P '' -C '%s'", sshDirectory, sftpUsername));
        // 添加公钥至authorized_keys
        command.add(String.format("cat %s/id_rsa.pub >> %s/authorized_keys", sshDirectory, sshDirectory));
        // 设置权限
        command.add(String.format("chmod 600 %s/authorized_keys", sshDirectory));
        // 设置属主
        command.add(String.format("chown %s:sftp %s/*", sftpUsername, sshDirectory));

        // 执行以上指令
        try {
            ssh2Utils.execCommand(String.join(";", command));
        } catch (Exception e) {
            e.printStackTrace();
            resp.put("msg", "生成秘钥失败");
            return resp;
        }

        resp.put("success", true);
        return resp;
    }

    /**
     *  添加秘钥
     */
    private JSONObject addSecretKey(Ssh2Utils ssh2Utils, String sftpUsername, String pubKey) {

        // 返回信息
        JSONObject resp = new JSONObject();
        resp.put("success", false);

        String sshDirectory = String.format("/sftp/%s/.ssh", sftpUsername);

        try {
            // 将公钥添加至authorized_keys
            ssh2Utils.execCommand(String.format("echo '%s' >> %s", pubKey, String.format("%s/authorized_keys", sshDirectory)));
        } catch (Exception e) {
            e.printStackTrace();

            resp.put("msg", "添加秘钥失败");
            return resp;
        }

        resp.put("success", true);
        return resp;
    }

    /**
     *  更新秘钥
     */
    public BaseDto changeSecretKey(String sftpUsername, HttpServletResponse response, MultipartFile secretKey) {
    
        try {
            // 登录sftp服务器
            ssh2Utils.login(host, username, password);

            JSONObject resp;
            // 生成秘钥
            if (secretKey == null) {
                // 为我生成一个秘钥
                resp = genSecretKey(ssh2Utils, sftpUsername);
                if (resp.getBoolean("success")) {
                    downloadSecretKey(id, response);
                }
            } else {
                // 使用我自己的秘钥
                resp = addSecretKey(ssh2Utils, sftpUsername, new String(secretKey.getBytes()));
            }
            if (!resp.getBoolean("success")) {
                ssh2Utils.logout();
                return BaseDto.error(resp.getString("msg"), null);
            }

            ssh2Utils.logout();

        } catch (Exception e){
            e.printStackTrace();
        }

        return BaseDto.success("设置成功", null);
    }
    
    /**
     *  下载秘钥
     */
    public BaseDto downloadSecretKey(String sftpUsername, HttpServletResponse response){
        
        String sshDirectory = String.format("/sftp/%s/.ssh", sftpUsername);

        // 下载秘钥
        try {
            // 登录sftp服务器
            ssh2Utils.login(host, username, password);
            // 获取私钥文件内容
            String secret = ssh2Utils.execCommand(String.format("cat %s/id_rsa", sshDirectory));
            // 私钥内容结束标志
            String end = "-----END RSA PRIVATE KEY-----";
            // 截取私钥内容 (去除其他无关的日志打印内容)
            secret = secret.substring(0, secret.lastIndexOf(end) + end.length());

            // 以附件形式下载私钥
            response.setContentType("text/plain");
            response.setHeader("Content-Disposition", "attachment; filename=\"id_rsa\"");

            PrintWriter pw = response.getWriter();
            pw.write(secret);
            pw.close();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                ssh2Utils.logout();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 新增sftp账户
     */
    public BaseDto save(String sftpUsername, MultipartFile secretKey) {
        // 校验名称
        if (StringUtils.isRealBlank(sftpUsername)) {
            return BaseDto.error("账户名称不能为空!", null);
        }

        try {
            // 登录sftp服务器
            ssh2Utils.login(host, username, password);

            // 创建账号
            JSONObject resp = createUser(ssh2Utils, sftpUsername);
            if (!resp.getBoolean("success")) {
                return BaseDto.error(resp.getString("msg"), null);
            }

            // 生成秘钥
            if (secretKey == null) {
                // 为我生成一个秘钥
                resp = genSecretKey(ssh2Utils, sftpUsername);
                if (resp.getBoolean("success")) return null;
                
            } else {
                // 使用我自己的秘钥
                resp = addSecretKey(ssh2Utils, sftpUsername, new String(secretKey.getBytes()));
            }
            
            if (!resp.getBoolean("success")) {
                return BaseDto.error(resp.getString("msg"), null);
            }

        } catch (Exception e){
            e.printStackTrace();
        } finally {
            try {
                ssh2Utils.logout();
            } catch (Exception e) {}
        }

        return BaseDto.success("创建成功", null);
    }

转载于:https://my.oschina.net/tianshl/blog/1836883

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值