shusheng007编程手记

[版权申明] 非商业目的注明出处可自由转载
出自:shusheng007

概述

本文记录了一些日常工作中遇到的问题以及解决方案,无他。持续更新到不做程序员…

工具篇

IntelliJ IDEA

在Idea中下载源码时,报无法下载源码

在这里插入图片描述

鼠标选中你的项目,右键点击:Open In -> Terminal 在项目路径下打开终端,当然你也可以直接打开命令行窗口,导航到你的项目目录下。

执行以下命令:

mvn dependency:resolve -Dclassifier=sources

等待下载完成即可。

Postman

使用Postman发送Post请求服务端得到了Get请求

Post请求可能被Web服务器,例如Nginx或者Tomcat给识别成Get请求了。只需要强制使用https,像下面这样即可:

https://your-domain:port/**

Git

远端拉取代码报443

今天拉去GitHub上的代码一直报如下错误

unable to access 'https://...': Unknown SSL protocol error in connection to ...:443

解决方案:

错误的原因为证书验证问题,极有可能是因为你使用了代理导致的。

可以使用下面的命令关闭SSL

http.sslVerify=false

下面几种均可,选择一种即可(安全程度不同):

  • global级别关闭
git config --global http.sslVerify false
  • local级别关闭
git config --local  http.sslVerify false
  • 针对某一个url级别关闭
git config --global http.https://github.com.sslVerify false

我这里写的github.com,可替换为我们自己的目标地址

  • 针对某一个操作级别关闭
git -c http.sslVerify=false  git操作命令

可以使用下面的命令来查看http相关的配置

git config --global --get-regexp http.*

JVM

服务端报:PKIX path building failed

通过RestTemplate以HTTPS的方式访问其他服务时,报如下错误:

PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

这是由于RestTemplate校验目标服务端的证书没有通过导致的,可以按照如下方法解决

方法1:给JVM导入目标服务端的证书

  1. 下载目标网站证书

在Google浏览器中打开你要访问的服务的Url, 点击F12看看web开发工具,选择Security,然后查看证书。

在这里插入图片描述

点击Detail,然后点击export导出证书
在这里插入图片描述
选择如下图所示的类型,并保存证书
在这里插入图片描述

  1. 将证书导入JVM中

查找你本机JVM证书仓库地址,在JDK安装目录里面

C:\Program Files\Java\jdk-11.0.16.1\lib\security\cacerts

使用admin权限打开命令行窗口,并执行下面导入证书的命令

keytool -import  -trustcacerts -alias 你的别名 -file "C:\MyJob\projects\job\certificate\api.qa.volvoconnect.com.crt" -keystore "C:\Program Files\Java\jdk-11.0.16.1\lib\security\cacerts" -storepass changeit

-file 你证书的保存地址
-keystore 你本机JVM证书仓库地址

查看证书列表(可选)

keytool -list -keystore "C:\Program Files\Java\jdk-11.0.16.1\lib\security\cacerts" -storepass changeit

当然,我们也可以手动删除cacerts中指定名称的证书:

keytool -delete -alias 你的别名 “C:\Program Files\Java\jdk-11.0.16.1\lib\security\cacerts” -storepass changeit

有时导入证书后仍然不行,我们也可以尝试通过环境变量指定ssl仓库给JVM

javax.net.ssl.trustStore=C:\Program Files\Java\jdk-11.0.16.1\lib\security\cacerts

方法2: 在dev环境下忽略证书验证

如果你只在开发环境中遇到这个问题,可以直接忽略证书,省去很多麻烦。

@Slf4j
@Configuration
public class RestTemplateConfig {

    @Value("${spring.profiles.active:}")
    private String activeProfile;

    @Bean("commonRestTemplate")
    public RestTemplate commonRestTemplate(RestTemplateBuilder builder) {
        builder = builder.setConnectTimeout(Duration.ofSeconds(60))
                .setReadTimeout(Duration.ofSeconds(60));

        if (List.of("dev").contains(activeProfile)) {
            try {
                TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;

                SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom()
                        .loadTrustMaterial(null, acceptingTrustStrategy)
                        .build();

                SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);

                CloseableHttpClient httpClient = HttpClients.custom()
                        .setSSLSocketFactory(csf)
                        .build();

                HttpComponentsClientHttpRequestFactory requestFactory =
                        new HttpComponentsClientHttpRequestFactory();
                requestFactory.setHttpClient(httpClient);
                
                builder = builder.requestFactory(() -> requestFactory);
            } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {
                log.error("ignore certificate failed", e);
            }
        }
        return builder.build();
    }
}

Linux

开启关闭防火墙

查看防火墙状态

systemctl status firewalld

开启防火墙

systemctl start firewalld

关闭防火墙

systemctl stop firewalld

开放端口

  1. 查询指定端口是否已开放

终端执行如下命令,提示yes表示开启;no表示未开启。

firewall-cmd --query-port=端口号/tcp
  1. 开放某个端口
firewall-cmd --add-port=端口号/tcp --permanent

其中--permanent表示永久开放

  1. 重新载入添加的端口:
firewall-cmd --reload

关闭端口

firewall-cmd --permanent --remove-port=端口号/tcp

如何修复磁盘

  1. 确认磁盘
df -Th
  1. 执行修复
xfs_repair -L /dev/sda1

开发篇

Nginx

如何使用docker来安装Nginx

  1. 拷贝配置文件

先使用docker运行一个nginx容器,用于获取初始的配置文件。

docker run --name nginx -p 10080:80 -d nginx:latest

导航到你要挂载nginx配置文件的目录,例如D盘的nginx文件夹

cd D:\nginx

拷贝相关配置文件

docker cp nginx:/etc/nginx/nginx.conf .
docker cp nginx:/etc/nginx/conf.d .
docker cp nginx:/usr/share/nginx/html .

注意不要忘了cp命令后面的那个.,它表示拷贝到当前文件夹。因为我们上一步已经导航到我们的目标目录了,所以拷贝到当前目录即可。

删除临时nginx容器

docker stop nginx && docker rm nginx

上面的命令表示停止并删除nginx容器

  1. 编写Nginx运行的docker-compose文件

我们编写一个 nginx_dc.yml,其内容如下。假设其存储路径为 D:\nginx\nginx_dc.yml

version: '3'

services:
  nginx:
    image: nginx:latest
    container_name: nginx
    ports:
      - 80:80
    volumes:
      - D:\nginx\conf.d:/etc/nginx/conf.d
      - D:\nginx\nginx.conf:/etc/nginx/nginx.conf:ro
      - D:\nginx\logs:/var/log/nginx
      - D:\nginx\html:/usr/share/nginx/html

执行

docker-compose -f D:\nginx\nginx_dc.yml up -d

其中-d表示以detach模式,也就是说当关闭了当前terminal后,容器仍然运行。

Java

如何在后台运行jar文件并打印log

由于SpringBoot内嵌了Tomcat,所以我们可以将其打包成一个Jar,然后直接运行。但目前是容器的时代,直接运行jar的方式变得越来越少,但是真的还有需求,因为我就遇到过。

那我们如何后台运行

假设我们使用SpringBoot写了一个web程序:my-app.jar

前提运行:

java -jar my-app.jar 

关闭终端则程序退出。

后台运行:

nohup java -jar my-app.jar  & 

注意我们在命令的前面加了一个nobub,在后面加了一个&。上面的命令会在当前目录下生成一个日志文件nohub.out,所有日志都会输出到这里。

指定日志文件:

在linux中,使用数字代表输入输出

  • 0:标准输入
  • 1:标准输出
  • 2:错误输出

下面表示普通日志输出到info.log文件,错误日志输出到error.log>info.log1>info.log的省略

nohup java -jar my-app.jar  >info.log 2>error.log & 

不输出日志文件:

下面的命令不输出日志文件,且指定了当前profile为生产环境。

/dev/null 是linux的黑洞文件,所有丢到这个地方的文件都会被吃掉。

nohup java -jar my-app.jar  --spring.profiles.active=prod >/dev/null 2>&1 & 

>/dev/null 2>&1 表示,标准输出,也就是1,输出到黑洞文件。然后 2 重定向到1,那么相应的2也输出到黑洞文件了。那么最后的结果就是1,2都输出到/dev/null 了。

这个写法非常重要,因为我们一般会在springboot程序中配置我们自己的日志路径,以及日志生成策略。例如每天生成一个文件,每个文件大小多少M等等。我们只有按照如上的方法不打印日志,我们的配置才会生效。

运行后,可以使用如下命令查看my-app进程

ps -ef | grep my-app

可使用如下命令杀死进程

kill -9 pid(上一步查出来的程序的进程号)

Lombok

如何注入带@Qualifier的参数到构造函数中

Spring 推荐使用构造函数注入依赖,于是使用Lombok可以简化代码:

@RequiredArgsConstructor
public class AuthService {
    private final UserService userService;
}

但是如果依赖用到了@Qualifier 怎么办呢,如下代码所示

@RequiredArgsConstructor
public class AuthService {
    @Qualifier(value = "userService1")
    private final UserService userService;
}

如果不做任何处理的话其生成的代码如下:

public class AuthService {
    @Qualifier(value = "userService1")
    private final UserService userService;
    
    public UserService(UserService userService){
    	this.userService = userService;
    }
}

可以看到@Qualifier没起作用。

解决方案:

在project的根目录下添加一个lombok的配置文件:lombok.config,文件内容如下:

lombok.copyableAnnotations += org.springframework.beans.factory.annotation.Qualifier

生成的结果如下:

public class AuthService {
    @Qualifier(value = "userService1")
    private final UserService userService;
    
    public UserService(@Qualifier(value = "userService1") UserService userService){
    	this.userService = userService;
    }
}

lombok 版本要高于1.18.4

这个配置的意思是会将@Qualifier拷贝到相应的位置。

安全

如何使用OpenSSL生成自签名证书

以下操作在Linux环境中完成

使用OpenSSL生成自签名证书只需要4步:

  1. 生成RSA密钥
 openssl genrsa -des3 -out shusheng007.key 2048

-des3 表示加密
2048 表示秘钥长度

按Enter键后,需要输入一个密码,例如pw123。记住这个秘密,后面的几步都需要输入

Generating RSA private key, 2048 bit long modulus (2 primes)
.....+++++
..........+++++
e is 65537 (0x010001)
Enter pass phrase for shusheng007.key:

这样,我们就获得了一个秘钥 shusheng007.key

  1. 从上面的秘钥生成一个没有秘密的秘钥

这个无密码秘钥在配置Nginx的时候使用

openssl rsa -in shusheng007.key -out shusheng007_nopass.key

按Enter键后,输入前面的秘密,例如pw123

Enter pass phrase for shusheng007.key:
writing RSA key
  1. 使用第一步生成的秘钥 shusheng007.key 生成CSR

CSR是Certificate Signing Request的英文缩写,即证书请求文件,也就是证书申请者在申请数字证书时由CSP(加密服务提供者)在生成私钥的同时也生成证书请求文件,证书申请者只要把CSR文件提交给证书颁发机构后,证书颁发机构使用其根证书私钥签名就生成了证书公钥文件,也就是颁发给用户的证书

 openssl req -new -key shusheng007.key -out shusheng007.csr

输入秘密后需要输入一些信息,例如国家,城市之类的。按照提示一步一步的输入即可

...
-----
Country Name (2 letter code) [AU]:CN                                                  
State or Province Name (full name) [Some-State]:TJ
Locality Name (eg, city) []:JINNAN
Organization Name (eg, company) [Internet Widgits Pty Ltd]:SNG
Organizational Unit Name (eg, section) []:SNG
Common Name (e.g. server FQDN or YOUR name) []:shusheng007.top
Email Address []:sstx_service@163.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

这里面最关键的就是Common Name 那个选项要输入自己的域名,我这边是shusheng007.top。

  1. 生成证书

使用秘钥 shusheng007.key 和 证书请求文件shusheng007.csr来生成证书。我们选择生成x509,并设置时长为3650天,也就是10年。最后生成了名为shusheng007.crt 的证书

openssl x509 -req -days 3650 -in shusheng007.csr -signkey shusheng007.key -out shusheng007.crt

所以最后总共产生了四个文件

-rw-r--r-- 1 root root 1302 May  8 22:27 shusheng007.crt
-rw-r--r-- 1 root root 1045 May  8 22:24 shusheng007.csr
-rw------- 1 root root 1751 May  8 22:17 shusheng007.key
-rw------- 1 root root 1679 May  8 22:18 shusheng007_nopass.key

有用的其实是shusheng007.crtshusheng007_nopass.key

如何将自签名证书配置到Nginx上

shusheng007.crtshusheng007_nopass.key两个文件拷贝到Nginx服务器上,例如

server {
    # 服务器端口使用443,开启ssl
    listen  443 ssl;
   
    # 域名,多个以空格分开
    server_name  shusheng007.top  www.shusheng007.top;

    # ssl证书地址
    ssl_certificate           /xxx/nginx/cert/shusheng007.crt;  
    ssl_certificate_key  /xxx/nginx/cert/shusheng007_nopass.key; 

    # ssl验证相关配置
    ssl_session_timeout  5m;    #缓存有效期
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;    #加密算法
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;    #安全链接可选的加密协议
    ssl_prefer_server_ciphers on;   #使用服务器端的首选算法
      ...
}

具体步骤请查看 如何在Nginx上启用HTTPS

存在Nginx的情况下还需要给Tomcat配置Https吗?

当给Nginx启用Https后,tomcat就不用配置了。我们在Nginx里通过反向代理将流量通过http转到Tomcat即可。因为Nginx与Tomcat正常情况下都是在内部网络的,所以认为他们直接通信是安全的。

        location / {
          proxy_pass http://youdomain.com:8080;
		  ...	
		 	
        }

更多精彩

敬请期待…

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShuSheng007

亲爱的猿猿,难道你又要白嫖?

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值