SpringBoot项目连接linux服务器数据库两种解决方法(linux直接开放端口访问&本机通过SSH协议访问,以mysql为例)

最近找个springboot脚手架重新熟悉一下springboot相关框架的东西,结果发现好像项目还不能直接像数据库GUI工具一样填几个SSH参数就可以了,于是就给他再整一下看看如何解决

linux开放3306(可修改)端口直接访问

此方法较为方便,无需修改代码,改好后只要把springboot项目中的mysql访问地址改成对应的linux主机ip即可
在这里插入图片描述
在使用GUI数据库工具时我们可以发现刚刚安装了数据库使用ssh通道就可以直接连接了,连基本的配置权限过程都冇,这是因为我们通过SSH连接到linux服务器相当于是远程控制linux主机,并使用linux主机的ip进行数据库操作,并不是我们本机ip直接进行操作的,所以mysql服务器识别的还是localhost(等价于127.0.0.1),是默认配置放行的,并且官方其实也是推荐只留localhost的,不过此处就是提供一种方法供选择。

(1)首先开放mysql的非localhost访问权限,允许非本地ip进行访问
使用root(或者其他高权限用户)访问mysql库内的user表,将对应需要修改的开放对外访问的ip的用户中的host字段修改为%即可,表示通配所有ip进行放行操作。
在这里插入图片描述
另外如果准备开放其他端口而不是3306的话,需要到/etc/my.cnf处进行添加 port=***即可
修改完成后重启mysql数据库服务或者直接刷新权限

mysql -u root -d
flush privileges;

systemctl restart mysqld

(2)开放linux防火墙
当我们有购买过云服务器的话,就可以发现我们需要在外部进行ip直接连接的话,需要在端口控制处添加对应的端口以供外部连接(当然也会配套一些DDOS防卫,流量控制一类的配套服务),在虚拟机的话也是同样需要开启对应的防火墙。
在网上搜寻了一大堆centos/rhel开放linux端口的文章,大部分都是让进行iptables配置,但是按照给出的文件路径,根本没有那个配置文件(/etc/sysconfig/iptables),我:?
后来才发现一位大佬的博客帮忙解了惑 https://www.cnblogs.com/AllWjw/p/15761697.html
总之就是每个centos/rhel大版本防火墙服务不尽相同,需要分开讨论,现在基本上主流Centos7所以使用的是firewalld服务
在这里插入图片描述

firewall-cmd --state ##查看防火墙状态,是否是running
firewall-cmd --add-port=3306/tcp --permanent ##永久添加3306端口
firewall-cmd --reload ##重新载入配置,比如添加规则之后,需要执行此命令
firewall-cmd --list-ports ##查看当前开放的端口

在这里插入图片描述

按顺序执行下来即可,看起来对应的端口已经正常开放了。
先用navicat小试一下看看
在这里插入图片描述
测试直接连接成功,接下来走个springbootApplication直接连接(项目是直接去gitee拉下来的renren-security)
在这里插入图片描述

SpringBoot项目通过SSH通道进行数据库访问

这个的话应该很多人都能在网上搜到现成的代码,无非都是用jcraft这个工具包来进行远程转发,然后写一个连接类和监视类,修改一下配置文件即可,只是这样的话那我应该和上面的内容一样当天就写完这个博客了,这边主要是讲一下我踩得坑。

首先是对概念的认知,我以为的代码连接过程如下
在这里插入图片描述

实际上的运作方式

在这里插入图片描述

于是我的配置是这样的

    String host = "192.168.23.129";
    //服务器公网IP
    int port = 22;
    // 跳板机ssh开放的接口   默认端口 22
    int local_port = 9680;
    // 这个是本地的端口,很重要!!!选取一个没有占用的port即可
    String remote_host = "127.0.0.1";
    // 要访问的mysql所在的host    服务器局域网IP(127.0.0.1也行)
    int remote_port = 3306;
    // 服务器上数据库端口号

application.yml这边但是写了localhost:3306,实际上这里执行时还是会连本地的3306,没走刚刚定义的9680端口建立的SSH隧道

  url: jdbc:mysql://localhost:3306/renren_security?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true

然后信心满满地启动,结果控制台每秒跳一个连接错
在这里插入图片描述
但是启动时还能瞟到有打印出SSH连接成功,在linux服务器查看连接也多出来了SSH连接,同时前端居然还能刷出来个验证码,可以证明这个地方应该程序是启动成功了来着,不过马上验证码就没了,因为开始报连接错误
在这里插入图片描述
看样子SSH是可以连接的没问题,报的错都是Druid连接池的错,难不成是因为创建连接池的时候也需要创建相同数量的SSH连接?于是路子渐渐地就走歪了…
我以为是因为我localport那个地方重复创建,所以只连接成功了一次后面全部都无法连接,原因是因为端口占用导致,于是开始魔改,增加Random类开始处理…

    //int local_port = new Random(5000).nextInt();
    session.setPortForwardingL(new Random(5000).nextInt(), remote_host, remote_port);

结果依旧,SSH连接只走了一次。
隔了一天在网上寻求解决方法,又查了下Jcraft工具的运作方式

应当是由localhost:9680(本机开启端口)作为一个中转通道转发至目标服务器192.168.23.129:3306(我的linux虚拟机)才对,所以在application.yml中的url配置的显式是我们刚刚创建的一个本机的localhost:9680通道,实际上是在通过这个localhost:9680通过隧道代理到192.168.23.129:3306进行操作

所以,这个localport 应该是与application.yml这边的port是需要匹配的,因为这里的localhost:9680到linux服务器的SSH隧道就相当于代理至192.168.23.129:3306的转发者

  url: jdbc:mysql://localhost:9680/renren_security?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
  
  int local_port = 9680;

暂时在防火墙中将3306端口屏蔽,测试一下程序是否还能正常运行
在这里插入图片描述
在这里插入图片描述
程序通过建立SSH通道成功运行!

文章最后虽然这代码到处都有,姑且贴一下(示例项目是renren-security所以url那边配的数据库也是renren-security,如果要连接其他数据库再进行修改)
MyContextListener.java

package io.renren.commons.dynamic.datasource.ssh;

import org.springframework.stereotype.Component;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;


@WebListener
@Component
public class MyContextListener implements ServletContextListener {
    private SSHConnection conexionssh;
    public MyContextListener() {
        super();
    }
    /**
     * //@see ServletContextListener#contextInitialized(ServletContextEvent)
     */
    @Override
    public void contextInitialized(ServletContextEvent arg0) {
        // 建立连接
        System.out.println("Context initialized ... !\n\n\n");
        try {
            conexionssh = new SSHConnection();
            conexionssh.SSHConnection();
            System.out.println("\n\n\n成功建立SSH连接!\n\n\n");
        } catch (Throwable e) {
            System.out.println("\n\n\nSSH连接失败!\n\n\n");
            e.printStackTrace(); // error connecting SSH server
        }
    }
    /**
     * //@see ServletContextListener#contextDestroyed(ServletContextEvent)
     */
    @Override
    public void contextDestroyed(ServletContextEvent arg0) {
        // 断开连接
        System.out.println("Context destroyed ... !\n\n\n");
        try {
            conexionssh.closeSSH(); // disconnect
            System.out.println("\n\n\n成功断开SSH连接!\n\n\n");
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("\n\n\n断开SSH连接出错!\n\n\n");
        }
    }

}

SSHConnection.java

package io.renren.commons.dynamic.datasource.ssh;

import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;

import java.util.Random;

public class SSHConnection {

    String user = "cloverangel";
    // 服务器登录名
    String password = "qq7744110";
    // 登陆密码
    String host = "192.168.23.129";
    //服务器公网IP
    int port = 22;
    // 跳板机ssh开放的接口   默认端口 22

    int local_port = 9680;

    // 这个是本地的端口,很重要!!!选取一个没有占用的port即可
    String remote_host = "127.0.0.1";
    // 要访问的mysql所在的host    服务器局域网IP(127.0.0.1也行)
    int remote_port = 3306;
    // 服务器上数据库端口号
    Session session = null;
    /**
     *    建立SSH连接
     */
    public void SSHConnection() {
        try {
            JSch jsch = new JSch();
            session = jsch.getSession(user, host, port);
            session.setPassword(password);
            session.setConfig("StrictHostKeyChecking", "no");
            // 日志打印自己脑补
            session.connect();
            session.setPortForwardingL(local_port, remote_host, remote_port);
            System.out.println(local_port+"---"+remote_host+"---"+remote_port);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     *    断开SSH连接
     */
    public void closeSSH () throws Exception
    {
        this.session.disconnect();
    }

    public int counter(Integer counter)
    {
        System.out.println(counter);
        return counter+1;
    }
}

application-dev.yml

      url: jdbc:mysql://localhost:9680/renren_security?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true

pom.xml

		<dependency>
			<groupId>com.jcraft</groupId>
			<artifactId>jsch</artifactId>
			<version>0.1.55</version>
		</dependency>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值