0%

ladp简介

LDAP轻量目录访问协议,英文全称是LIGHTWEIGHT DIRECTORY ACCESS PROTOCOL,一般都简称为LDAP.

特点

  • 读写效率非常高

对读操作进行优化的一种数据库,在读写比例大于7比1的情况下,LDAP会体现出极高的性能。这个特性正适合了身份认证的需要。

  • 开放的标准协议

不同于SQL数据库,LDAP的客户端是跨平台的,并且对几乎所有的程序语言都有标准的API接口。即使是改变了LDAP数据库产品的提供厂商,开发人员也不用担心需要修改程序才能适应新的数据库产品。这个优势是使用SQL语言进行查询的关系型数据库难以达到的。

  • 强认证方式

可以达到很高的安全级别。在国际化方面,LDAP使用了UTF-8编码来存储各种语言的字符。

  • OpenLDAP开源实现

OpenLDAP是其中最轻便且消耗系统资源最少的一个。OpenLDAP是开源软件,近年国内很多公司开发的LDAP产品都是基于OpenLDAP开发的。

  • 灵活添加数据类型

LDAP是根据schema的内容定义各种属性之间的从属关系及匹配模式的。例如在关系型数据库中如果要为用户增加一个属性,就要在用户表中增加一个字段,在拥有庞大数量用户的情况下是十分困难的,需要改变表结构。但LDAP只需要在schema中加入新的属性,不会由于用户的属性增多而影响查询性能

  • 数据存储是树结构

整棵树的任何一个分支都可以单独放在一个服务器中进行分布式管理,不仅有利于做服务器的负载均衡,还方便了跨地域的服务器部署。这个优势在查询负载大或企业在不同地域都设有分公司的时候体现尤为明显

  • 总结
    • LDAP 是一种网络协议而不是数据库,而且LDAP的目录不是关系型的,没有RDBMS那么复杂,
    • LDAP不支持数据库的Transaction机制,纯粹的无状态、请求-响应的工作模式。
    • LDAP不能存储BLOB,LDAP的读写操作是非对称的,读非常方便,写比较麻烦,
    • LDAP支持复杂的查询过滤器(filter),可以完成很多类似数据库的查询功能。
    • LDAP使用树状结构,接近于公司组织结构、文件目录结构、域名结构等我们耳熟能详的东东。
    • LDAP使用简单、接口标准,并支持SSL访问。

ldap应用场景

  1. 网络服务:DNS服务
  2. 统一认证服务:Linux PAM (ssh, login, cvs. . . )
  3. Apache访问控制
  4. 各种服务登录(ftpd, php based, perl based, python based. . . )
  5. 个人信息类,如地址簿
  6. 服务器信息,如帐号管理、邮件服务等

route命令

route命令用来显示并设置Linux内核中的网络路由表route命令设置的路由主要是静态路由。要实现两个不同的子网之间的通信,需要一台连接两个网络的路由器,或者同时位于两个网络的网关来实现。

在Linux系统中设置路由通常是为了解决以下问题:

  • 该Linux系统在一个局域网中,局域网中有一个网关,能够让机器访问Internet,那么就需要将这台机器的ip地址设置为Linux机器的默认路由。
  • 直接在命令行下执行route命令来添加路由,不会永久保存,当网卡重启或者机器重启之后,该路由就失效了
  • 可以在/etc/rc.local中添加route命令来保证该路由设置永久有效,这个方法只能在重启电脑的时候生效,重启网络不生效;
  • 推荐在/etc/sysconfig/static-routes编写路由,重启网络或服务器都能生效;
# vim /etc/sysconfig/static-routes
# 这个文件默认不存在
any net 192.168.11.0 gw 192.168.21.1 netmask 255.255.255.0 metric 1 dev eth0

注意,如果本机安装了docker,添加路由后重启网络,会导致docker服务启动添加的路由失效,导致docker服务调用失败,创建新的docker服务会报以下错误,重启docker服务可以解决。systemctl restart docker

[root@localhost ~]# docker run -d -p 9000:80 centos:httpd /bin/sh -c /usr/local/bin/start.sh
d5b2bd5a7bc4895a973fe61efd051847047d26385f65c278aaa09e4fa31c4d76
docker: Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen (6bda693d1143657e46bee0300276aa05820da2b21a3d89441e820d1a274c48b6): (iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --dport 9000 -j DNAT --to-destination 172.17.0.2:80 ! -i docker0: iptables: No chain/target/match by that name.
(exit status 1)).

route语法

# 设置和查看路由表都可以用 route 命令,设置内核路由表的命令格式是:
route  [add|del] [-net|-host] target [netmask Nm] [gw Gw] [[dev] If]
  1. 方法
方法 说明
add 增加指定的路由记录;
del 删除指定的路由记录;
target 目的网络或目的主机;
gw 设置默认网关;
mss 设置TCP的最大区块长度(MSS),单位MB;
netmask 目的地址的网络掩码
window 指定通过路由表的TCP连接的TCP窗口大小;
dev 路由记录所表示的网络接口。
  1. 选项
选项 说明
-A 设置地址类型;
-C 打印将Linux核心的路由缓存;
-v 详细信息模式;
-n 不执行DNS反向查找,直接显示数字形式的IP地址;
-e netstat格式显示路由表;
-net 到一个网络的路由表;
-host 到一个主机的路由表。
  1. Flags标志说明
flag 说明
U Up表示此路由当前为启动状态。
H Host,表示此网关为一主机。
G Gateway,表示此网关为一路由器。
R Reinstate Route,使用动态路由重新初始化的路由。
D Dynamically,此路由是动态性地写入。
M Modified,此路由是由路由守护程序或导向器动态修改。
! 表示此路由当前为关闭状态。
  1. route命令输出说明
输出列 说明
Destination 目标网段或者主机
Gateway 网关地址,*表示目标是本主机所属的网络,不需要路由
Genmask 网络掩码
Flags 标记。
Metric 路由距离,到达指定网络所需的中转数
Ref 路由项引用次数
Use 此路由项被路由软件查找的次数
Iface 该路由表项对应的输出接口

示例

# 显示当前路由
[root@node1 ~]# route 
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         gateway         0.0.0.0         UG    0      0        0 ens33
link-local      0.0.0.0         255.255.0.0     U     1002   0        0 ens33
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
172.18.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-caa257c6f76d
192.168.41.0    0.0.0.0         255.255.255.0   U     0      0        0 ens33
192.168.122.0   0.0.0.0         255.255.255.0   U     0      0        0 virbr0
[root@node1 ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.41.2    0.0.0.0         UG    0      0        0 ens33
169.254.0.0     0.0.0.0         255.255.0.0     U     1002   0        0 ens33
172.17.0.0      0.0.0.0         255.255.0.0     U     0      0        0 docker0
172.18.0.0      0.0.0.0         255.255.0.0     U     0      0        0 br-caa257c6f76d
192.168.41.0    0.0.0.0         255.255.255.0   U     0      0        0 ens33
192.168.122.0   0.0.0.0         255.255.255.0   U     0      0        0 virbr0
# 增加一条到达244.0.0.0的路由。
route add -net 224.0.0.0 netmask 240.0.0.0 dev eth0

# 添加到主机的路由
route add -host 192.168.1.2 dev eth0
# 添加到10.20.30.148的网关
route add -host 10.20.30.148 gw 10.20.30.40
# 添加10.20.30.40的网络
route add -net 10.20.30.40 netmask 255.255.255.248 eth0
# 网络掩码 255.255.255.0简写
route add -net 192.168.1.0/24 eth1
# 增加一条屏蔽的路由,目的地址为224.x.x.x将被拒绝。
route add -net 224.0.0.0 netmask 240.0.0.0 reject
# 删除路由记录
route del -net 224.0.0.0 netmask 240.0.0.0
route del -net 224.0.0.0 netmask 240.0.0.0 reject
# 删除和添加设置默认网关
route del default gw 192.168.120.240
route add default gw 192.168.120.240

设置包转发

CentOS 中默认的内核配置已经包含了路由功能,但默认并没有在系统启动时启用此功能。开启 Linux 的路由功能可以通过调整内核的网络参数来实现。要配置和调整内核参数可以使用 sysctl 命令。例如:要开启 Linux 内核的数据包转发功能可以使用如下的命令。

sysctl -w net.ipv4.ip_forward=1

这样设置之后,当前系统就能实现包转发,但下次启动计算机时将失效。为了使在下次启动计算机时仍然有效,需要将下面的行写入配置文件/etc/sysctl.conf

# vi /etc/sysctl.conf
net.ipv4.ip_forward = 1
# 或者 使用下面的命令
echo net.ipv4.ip_forward=1 >> /etc/sysctl.conf
# 使上面配置生效
sysctl -p 

用户还可以使用如下的命令查看当前系统是否支持包转发。

sysctl net.ipv4.ip_forward

# 或者下面命令 输出1 证明已生效
cat /proc/sys/net/ipv4/ip_forward

iptables SNAT/DNAT服务

  • SNAT : source network address translation, 修改网络包源IP
  • DNAT : destination network address translation, 修改网络包目的IP
  • 修改源IP目的是这个包还能返回到自己这里,在iptables中,SNAT是在出口POSTROUTING链中发挥作用
  • 修改目的IP目的是这个包能够发送出去,让包传递下去,在iptables中,DNAT是在入口PREROUTING链中发挥作用,以便让包进入FORWARD表.

iptables SNAT/DNAT服务使用场景

  • 云上虚拟机作为客户端访问外网服务器, SNAT类似于代理的作用, 客户端通过SNAT服务可以访问外网.
  • 云上虚拟机作为服务端为外网提供服务, DNAT类似于反向代理, 外网请求通过DNAT服务可以将包传到内网服务端.

SNAT/DNAT

lsmod|grep ^ip #查看nat模块
# 载入:modprobe iptable-nat
# 开启上网命令
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j SNAT --to-source 192.168.1.202
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j SNAT --to 192.168.1.202

# 确认查看
iptables -t nat -nL

查看

show variables like '%max_connections%';

数值过小会经常出现ERROR 1040: Too many connections错误

show global status like 'Max_used_connections';

-- Threads_connected: 打开的连接数,Threads_running:激活的 正在使用的连接数
show status like 'Threads%';

-- 查看最大缓存的连接数量,可以适当增加
show variables like 'thread_cache_size';

设置

  1. 临时设置
set global max_connections=1024;

重启失效.

  1. 永久设置
-- 修改mysql配置文件my.cnf,在[mysqld]段中添加或修改max_connections值:
max_connections=512

重启生效.

引入依赖

<dependency>
    <groupId>com.google.zxing</groupId>
    <artifactId>javase</artifactId>
    <version>3.3.0</version>
</dependency>

编写工具类

public class QRCodeUtil {
    // 设置二维码长宽
    private static int width = 400;
    private static int height = 400;
    private static String format = "png";

    // 将文本信息封装到二维码中,并返回图片的Base64编码后的字符串
    public static String encodeQRCode(String text) {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        String result = null;
        try {
            Map<EncodeHintType, Object> hints = new HashMap<>();
            // 设置字符集编码
            hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
            // ErrorCorrectionLevel:误差校正等级,L = ~7% correction、M = ~15% correction、Q = ~25% correction、H = ~30% correction
            // 不设置时,默认为 L 等级,等级不一样,生成的图案不同,但扫描的结果是一样的
            hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
            // 设置二维码边距,单位像素,值越小,二维码距离四周越近
            hints.put(EncodeHintType.MARGIN, 1);
            // 生成二维码矩阵
            BitMatrix bitMatrix = new MultiFormatWriter().encode(text, BarcodeFormat.QR_CODE, width, height, hints);
            // 写入文件
            MatrixToImageWriter.writeToStream(bitMatrix, format, outputStream);
            bitMatrix.clear();
            result = "data:image/png;base64," + Base64.getEncoder().encodeToString(outputStream.toByteArray());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                outputStream.close();
            } catch (IOException e) {
            }
        }
        return result;

    }

    // 通过base64编码后的图片,解析出二维码中的文本信息
    public static String decodeQRCode(String base64) {
        Result result = null;
        BufferedImage image = null;
        ByteArrayInputStream inputStream = new ByteArrayInputStream(Base64.getDecoder().decode(base64));
        try {
            // 读取图片
            image = ImageIO.read(inputStream);
            // 多步解析
            LuminanceSource source = new BufferedImageLuminanceSource(image);
            Binarizer binarizer = new HybridBinarizer(source);
            BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
            // 设置字符集编码
            Map<DecodeHintType, String> hints = new HashMap<>();
            hints.put(DecodeHintType.CHARACTER_SET, "UTF-8");
            // 对图像进行解码
            result = new MultiFormatReader().decode(binaryBitmap, hints);
        } catch (Exception e) {
            System.out.println(e);
        } finally {
            image.getGraphics().dispose();
            try {
                inputStream.close();
            } catch (IOException e) {
            }
        }
        return result.getText();
    }
}

测试

    // 测试准确率还是非常高的
    public static void main(String[] args) {
        // 生成二维码
        System.out.println(encodeQRCode("我叫XX勇~~~"));
        // 解码二维码
        // 注意:需要去掉data:image/png;base64,
        System.out.println(decodeQRCode("xxxxxxxxxx.....xxxxxxxx"));
    }

问题

  • openjdkoracle jdk一些情况下并不兼容;
  • openjdk镜像很小只有一百朵兆,但是oracle jdk搜到的镜像都很大.

步骤

  1. 下载最新的oracle jre 8
https://javadl.oracle.com/webapps/download/AutoDL?BundleId=242050_3d5a2bb8f8d4428bbe94aed7ec7ae784
  1. 上传到linux并解压
[root@node1 jdk8]# tar -xvzf jre-8u251-linux-x64.tar.gz 
[root@node1 jdk8]# pwd
/root/jdk8
[root@node1 jdk8]# ll
总用量 85492
drwxr-xr-x 5 10143 10143       76 7月   9 14:04 jre1.8.0_251
-rw-r--r-- 1 root  root  87543611 7月   9 13:55 jre-8u251-linux-x64.tar.gz
  1. 删除一些说明文档和无用包
[root@node1 jdk8]# cd jre1.8.0_251/

rm -rf COPYRIGHT LICENSE README release THIRDPARTYLICENSEREADME-JAVAFX.txt THIRDPARTYLICENSEREADME.txt Welcome.html
rm -rf   lib/plugin.jar \
           lib/ext/jfxrt.jar \
           bin/javaws \
           lib/javaws.jar \
           lib/desktop \
           plugin \
           lib/deploy* \
           lib/*javafx* \
           lib/*jfx* \
           lib/amd64/libdecora_sse.so \
           lib/amd64/libprism_*.so \
           lib/amd64/libfxplugins.so \
           lib/amd64/libglass.so \
           lib/amd64/libgstreamer-lite.so \
           lib/amd64/libjavafx*.so \
           lib/amd64/libjfx*.so

[root@node1 jre1.8.0_251]# ll
总用量 4
drwxr-xr-x  2 10143 10143  208 7月   9 13:56 bin
drwxr-xr-x 13 10143 10143 4096 7月   9 13:56 lib
drwxr-xr-x  4 10143 10143   47 3月  12 14:33 man
  1. 重新打包
[root@node1 jre1.8.0_251]# tar zcvf jre8.tar.gz *
[root@node1 jre1.8.0_251]# ll
总用量 43896
drwxr-xr-x  2 10143 10143      208 7月   9 13:56 bin
-rw-r--r--  1 root  root  44942683 7月   9 14:04 jre8.tar.gz
drwxr-xr-x 13 10143 10143     4096 7月   9 13:56 lib
drwxr-xr-x  4 10143 10143       47 3月  12 14:33 man
  1. 直接在当前目录下创建Dockerfile
[root@node1 jre1.8.0_251]# vim Dockerfile

编写Dockerfile

FROM docker.io/jeanblanchard/alpine-glibc
MAINTAINER wuzhiyong
ADD jre8.tar.gz /usr/java/jdk/
ENV JAVA_HOME /usr/java/jdk
ENV PATH ${PATH}:${JAVA_HOME}/bin
WORKDIR /opt
  1. 生成镜像
# 生成镜像
[root@node1 jre1.8.0_251]# docker build -t wuzhiyong/java8.0_251 .
Sending build context to Docker daemon  161.1MB
Step 1/6 : FROM docker.io/jeanblanchard/alpine-glibc
 ---> c1bfe6541128
Step 2/6 : MAINTAINER wuzhiyong
 ---> Using cache
 ---> 5e4699308c35
Step 3/6 : ADD jre8.tar.gz /usr/java/jdk/
 ---> 8b6b66ec0f68
Step 4/6 : ENV JAVA_HOME /usr/java/jdk
 ---> Running in 26f286188aa8
Removing intermediate container 26f286188aa8
 ---> 7d1501133f4c
Step 5/6 : ENV PATH ${PATH}:${JAVA_HOME}/bin
 ---> Running in 418be370f8b9
Removing intermediate container 418be370f8b9
 ---> 8a920d8285df
Step 6/6 : WORKDIR /opt
 ---> Running in 107687a0007d
Removing intermediate container 107687a0007d
 ---> e7a62387e585
Successfully built e7a62387e585
Successfully tagged wuzhiyong/java8.0_251:latest
#查看镜像大小
[root@node1 jre1.8.0_251]# docker images | grep java8
wuzhiyong/java8.0_251                                            latest                    e7a62387e585        15 seconds ago      133MB
  1. 上传到镜像仓库,可以下载使用
docker pull hub.deri.org.cn/library/oracle_jdk_1.8_251:latest

引入依赖

<!-- 注意版本号,测试2.0.3版本有严重问题,启动失败 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
    <version>2.1.1.RELEASE</version>
</dependency>

注册邮箱

  • 163,126,qq都行,这边测试126邮箱;
  • 开启IMAP/SMTP服务;
  • 获取授权密码,注意保存.

配置application.yaml

spring:
  mail:
    # 注册的邮箱
    username: xxxxxx@126.com
    # 密码为授权码
    password: XXXXXXXXXXXXXXX
    # smtp服务器地址
    host: smtp.126.com
    # 安全相关配置,非必须
    properties:
      mail:
        smtp:
          auth: true
          starttls:
            enable: true
            required: true

测试发送

@Service
public class MailService {
    // 这个在IDEA中会提示没有bean,注入失败,不用管~
    @Autowired
    JavaMailSender mailSender;

    public void send(){
        // 普通文本邮件
        SimpleMailMessage simpleMailMessage = new SimpleMailMessage();
        //邮件发送方,需要写完整邮箱地址
        simpleMailMessage.setFrom("XXXXX@126.com");
        //邮件接收方邮箱
        simpleMailMessage.setTo("1154365135@qq.com");
        //邮件标题
        simpleMailMessage.setSubject("测试主题~~");
        //邮件内容
        simpleMailMessage.setText("测试内容~~");
        //发送邮件
        mailSender.send(simpleMailMessage);
    }

    public void sendHtml() throws MessagingException {
        // html邮件
        MimeMessage mimeMessage = mailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true);
        //邮件发送方
        helper.setFrom("authservice@126.com");
        //邮件接收方邮箱
        helper.setTo("1154365135@qq.com");
        //邮件标题
        helper.setSubject("测试HTML~~");
        //邮件内容
        helper.setText("<html>\n" +
                "<head>\n" +
                "<meta charset=\"utf-8\">\n" +
                "<title>菜鸟教程(runoob.com)</title>\n" +
                "</head>\n" +
                "<body>\n" +
                "    <h1>我的第一个标题</h1>\n" +
                "    <p style=\"color: blue;\">我的第一个段落。</p>\n" +
                "</body>\n" +
                "</html>", true);
        //发送邮件
        mailSender.send(mimeMessage);
    }

        //附件邮件, 未测试
    public void sendAttachmentMail(String to,String subject,String content,String filePath) throws MessagingException {
        MimeMessage mimeMessage=mailSender.createMimeMessage();
        MimeMessageHelper helper=new MimeMessageHelper(mimeMessage,true);
        helper.setTo(to);
        helper.setSubject(subject);
        helper.setText(content,true);
        helper.setFrom(form);
        FileSystemResource file=new FileSystemResource(new File(filePath));
        String fileName=file.getFilename();
        helper.addAttachment(fileName,file);
        //helper.addAttachment(fileName+"02",file);  如果是多个附件的话,可以这样写。但是开发中一般都是把filepath做成一个数组,这样在这里遍历就可以了
        //helper.addAttachment(fileName+"03",file);

        mailSender.send(mimeMessage);
    }

    //图片邮件,未测试
    public void sendInlineResourceMail(String to,String subject,String content,String rscPath,String rscId) throws MessagingException {
        MimeMessage mimeMessage=mailSender.createMimeMessage();
        MimeMessageHelper helper=new MimeMessageHelper(mimeMessage,true);
        helper.setTo(to);
        helper.setSubject(subject);
        helper.setText(content,true);
        helper.setFrom(form);
        FileSystemResource file=new FileSystemResource(new File(rscPath));
        helper.addInline(rscId,file);

        mailSender.send(mimeMessage);
    }
}