[版权申明] 非商业目的注明出处可自由转载
出自: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导入目标服务端的证书
- 下载目标网站证书
在Google浏览器中打开你要访问的服务的Url, 点击F12看看web开发工具,选择Security,然后查看证书。
点击Detail,然后点击export导出证书
选择如下图所示的类型,并保存证书
- 将证书导入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
开放端口
- 查询指定端口是否已开放
终端执行如下命令,提示yes表示开启;no表示未开启。
firewall-cmd --query-port=端口号/tcp
- 开放某个端口
firewall-cmd --add-port=端口号/tcp --permanent
其中--permanent
表示永久开放
- 重新载入添加的端口:
firewall-cmd --reload
关闭端口
firewall-cmd --permanent --remove-port=端口号/tcp
如何修复磁盘
- 确认磁盘
df -Th
- 执行修复
xfs_repair -L /dev/sda1
开发篇
Nginx
如何使用docker来安装Nginx
- 拷贝配置文件
先使用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容器
- 编写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.log
是1>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步:
- 生成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
- 从上面的秘钥生成一个没有秘密的秘钥
这个无密码秘钥在配置Nginx的时候使用
openssl rsa -in shusheng007.key -out shusheng007_nopass.key
按Enter键后,输入前面的秘密,例如pw123
Enter pass phrase for shusheng007.key:
writing RSA key
- 使用第一步生成的秘钥
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。
- 生成证书
使用秘钥 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.crt
和 shusheng007_nopass.key
如何将自签名证书配置到Nginx上
将shusheng007.crt
和 shusheng007_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;
...
}
更多精彩
敬请期待…