首页
归档
友链
关于
Search
1
网易云音乐黑胶会员月月免费赠送
4,211 阅读
2
十年之约RSS聚合订阅服务上线
3,958 阅读
3
工资发放日的区别
2,896 阅读
4
rsyslogd内存占用过高解决方案
2,632 阅读
5
Nginx反代MinIO后,上传文件签名异常
2,468 阅读
零碎
标本
码海
工具
其他
登录
Search
标签搜索
北京
摄影
生活
Java
旅行
学习笔记
教程
服务器
Linux
日记
软件
SpringBoot
服务
Windows
数据库
福利
Spring
系统
SQL
php
萧瑟
累计撰写
209
篇文章
累计收到
1,522
条评论
首页
栏目
零碎
标本
码海
工具
其他
页面
归档
友链
关于
搜索到
47
篇与
码海
的结果
2023-06-11
druid连接池实现数据库加密
无论是公司的项目还是个人的项目,我们都会选择将源码上传到 Git 服务器(GitHub、Gitee 或是自建服务器),但只要将源码提交到公网服务器就会存在源码泄漏的风险,而数据库配置信息作为源码的一部分,一旦出现源码泄漏,那么数据库中的所有数据都会公之于众,其产生的不良后果无法预期。于是为了避免这种问题的产生,我们至少要对数据库的密码进行加密操作,这样即使得到了源码,也不会造成数据的泄露。怎么实现加密? 对于 Java 项目来说,要想快速实现数据库的加密,最简单可行的方案就是使用阿里巴巴提供的 Druid 来实现加密。交互流程执行命令这里我们以 1.2.18 版本为例,各位也可以选择其他版本,命令基本都是一样的。 java -cp [druid-1.2.18.jar仓库路径] [com.alibaba.druid.filter.config.ConfigTools] [密码]命令示例java -cp D:\druid\druid-1.2.18.jar com.alibaba.druid.filter.config.ConfigTools 123456 执行结果: privateKey:MIIBVgIBADANBgkqhkiG9w0BAQEFAASCAUAwggE8AgEAAkEAloMI1R+5QNFTDAUvZ5KCkq+qauA2IJbiYR0ghk9ssWm7lPooZEOipCa88W0rya/4oaOt6i0iVlS/EmtmMCTZ7QIDAQABAkEAjWMyXOKcJ+N7XANS8LyUpC8Yq6VLs3mJ1yiBcSoTNORpTxndFog/BXUXQP6yTkNHk+Nc5sxdGvl42y3mywiRAQIhAMhiyFRwWWdImzPR+fC8n6s3+B341jy3AWMrixXMAJydAiEAwEjAp9LTgS0fIoEtlz6KYbVnsionIIof1JKAbsJjKZECIQCuthHcLSiF+LP49nZpAsxjyCS4XSDNRvIauPhHRNqzsQIhAJuBux1+6cLMxSNYqZBp6ex/k2+Jm787Nebq3Ke22g+hAiBi9IOPYlm40BAp9jkr2Z2/yqV1E0ppfqigUbFNIpp79g== publicKey:MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJaDCNUfuUDRUwwFL2eSgpKvqmrgNiCW4mEdIIZPbLFpu5T6KGRDoqQmvPFtK8mv+KGjreotIlZUvxJrZjAk2e0CAwEAAQ== password:YJHHitRl6unpzMi4dfxDOUH7R0kSB/32Wxu0D+xRA5ijmmaO8whHSlCAm3iQ9OqtJXwPU/NzcKmGx/QvhRxnHg==截图示例替换配置文件spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource druid: url: jdbc:mysql://localhost:3306/test?useSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai username: root #生成后的密文 password: YJHHitRl6unpzMi4dfxDOUH7R0kSB/32Wxu0D+xRA5ijmmaO8whHSlCAm3iQ9OqtJXwPU/NzcKmGx/QvhRxnHg== filters: config connect-properties: config.decrypt: true #生成的公钥 config.decrypt.key: MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJaDCNUfuUDRUwwFL2eSgpKvqmrgNiCW4mEdIIZPbLFpu5T6KGRDoqQmvPFtK8mv+KGjreotIlZUvxJrZjAk2e0CAwEAAQ==
2023年06月11日
212 阅读
1 评论
2023-06-08
Joe 主题对接腾讯 LBS 展示 IP 属地(二)
书接上回,我们在主题中对接腾讯LBS IP查询服务后,会有一个bug:如果某篇文章评论过多,则某些评论IP定位数据无法显示,这个是因为腾讯LBS服务个人开发者的并发量限制为5次/秒。在上一个教程发布后,也有大佬发现了这个问题,不过这个问题我顺手就解决了,但是解决方案没有分享出来,因为需要改typecho系统的代码。这个已经脱离技术小白的范围,请合理折腾,折腾前记得备份数据。{anote icon="fa-internet-explorer" href="https://blog.yanqingshan.com/130.html" type="success" content="Joe 主题对接腾讯 LBS 展示 IP 属地"/}原理这一次折腾的原理是,我们在数据库中添加一个字段作为IP属地信息的一个冗余信息;当用户评论时,获取用户IP地址,调用腾讯LBS服务进行查询,将查询到的数据写入数据库中,这样就避免并发量超出限制。执行sql语句23.06.10:根据Typecho数据库设计文档又更新了一下sql语句ALTER TABLE `typecho_comments` ADD COLUMN `ipRegion` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'IP中文地址' AFTER `parent`, DROP PRIMARY KEY, ADD PRIMARY KEY (`coid`) USING BTREE;上面sql就是在字段coid后增加一个ipRegion的字段,并且添加一个备注信息。修改代码我们打开网站根目录,路径:/var/Widget/Base/Comments.php 这个文件是系统评论对外提供的方法,包括插入数据和查询数据等方法,有能力的同学,可以翻翻代码,基本上面都有注释;大概55行,也就是增加评论 的方法首行,增加以下代码,将key和sign_key修改为自己申请的就可以。$ipRegion = ''; $cip = empty($comment['ip']) ? $this->request->getIp() : $comment['ip']; $key = '配置自己申请的key'; //签名校验的KEY $sign_key = '配置自己申请的sign_key'; $sign = md5('/ws/location/v1/ip?ip='.$cip.'&key='.$key.$sign_key); $url = 'https://apis.map.qq.com/ws/location/v1/ip?ip='.$cip.'&key='.$key.'&sig='.$sign; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_AUTOREFERER, 1); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_HTTPGET, true); curl_setopt($ch, CURLOPT_REFERER, $url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'); $content = curl_exec($ch); curl_close($ch); if($content) { $json = json_decode($content,true); if($json['status'] == 0 ){ $resjson = $json['result']['ad_info']; if($resjson['nation'] == '中国'){ if($resjson['province']=='北京市'||$resjson['province']=='天津市'||$resjson['province']=='上海市'||$resjson['province']=='重庆市'){ $ipRegion = $resjson['city']; }else{ $ipRegion = $resjson['province'].$resjson['city']; } }else{ $ipRegion = $resjson['nation'].$resjson['province'].$resjson['city'].$resjson['district']; } } }上面代码增加完后,大概在108行,也就是构建插入结构 那行注释里面增加一个参数,把下面代码放在[]中,'ipRegion' => $ipRegion, 在381行后,插入下面,这个就是把查询对象增加一个输出值'table.comments.ipRegion'基本上请求和写入已经完成,我们再改一下后台管理界面,把这个ip属地也添加到页面上,这样后台也方便查询打开admin/manage-comments.php136行后增加以下代码<br /><span><?php $comments->ipRegion(); ?>最后我们再来修改主题的评论,这里以Joe主题为例文件路径joe/public/comment.php<?php $comments->ipRegion(); ?> 找到合适位置显示IP属地,我是放在112行的<div class="agent"> <?php $comments->ipRegion(); ?> <?php _getAgentOS($comments->agent); ?> · <?php _getAgentBrowser($comments->agent); ?> </div>最终效果如下
2023年06月08日
519 阅读
7 评论
2023-04-28
Java 使用JDBC备份数据库中的表和数据
实现思路加载数据库驱动程序并建立数据库连接。使用JDBC API查询需要备份的表格和数据。在输出文件中以适当的格式编写SQL语句来创建表格。用适当的格式编写INSERT语句将行数据写入输出文件。5. 关闭所有数据库连接和输出文件。实现代码package com.yanqingshan.admin.jdbc; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import java.io.FileWriter; import java.io.IOException; import java.sql.*; import java.util.ArrayList; import java.util.List; /** * 通过JDBC备份 库表数据 * * @author yanqs * @date 2023年04月28日 9:31 */ @Slf4j @SpringBootTest class BuildSql { @Test void testBuildSql() throws ClassNotFoundException, SQLException, IOException { String dbUrl = "jdbc:mysql://192.168.57.110:3306/boot-startup"; String username = "test"; String password = "123456"; // 加载JDBC驱动程序 Class.forName("com.mysql.cj.jdbc.Driver"); // 建立数据库连接 Connection conn = DriverManager.getConnection(dbUrl, username, password); // 创建Statement对象 Statement stmt = conn.createStatement(); // 查询所有表格名字 ResultSet result = stmt.executeQuery("SHOW TABLES"); // 备份的SQL文件 FileWriter writer = new FileWriter("backup.sql"); // 循环遍历所有表 存表 List<String> tableNameList = new ArrayList<>(); while (result.next()) { tableNameList.add(result.getString(1)); } for (String tableName : tableNameList) { log.info("开始备份“{}”表结构", tableName); // 在输出文件中写入创建表格SQL语句 ResultSet rs = stmt.executeQuery("SHOW CREATE TABLE " + tableName); if (rs.next()) { writer.write("\n\n" + rs.getString(2) + ";\n\n"); } // 循环遍历表格中的所有行来写入数据 rs = stmt.executeQuery("SELECT * FROM " + tableName); int columnCount = rs.getMetaData().getColumnCount(); log.info("开始生成“{}”表数据", tableName); while (rs.next()) { writer.write("INSERT INTO " + tableName + " VALUES ("); for (int i = 1; i <= columnCount; i++) { writer.write("'" + rs.getString(i) + "'"); if (i < columnCount) { writer.write(","); } } writer.write(");\n"); } } // 关闭所有连接 writer.close(); result.close(); stmt.close(); conn.close(); log.info("备份完成"); } }实现效果
2023年04月28日
278 阅读
4 评论
2023-04-23
Java+Selenium学习笔记
Selenium介绍Selenium是一个用于Web应用程序自动化测试工具,背后有google 维护源代码,支持全部主流浏览器,支持主流的编程语言,包括:java,Python,C#,PHP,Ruby等特点开源、免费多浏览器支持:FireFox、Chrome、IE、Opera、Edge;多平台支持:Linux、Windows、MAC;多语言支持:Java、Python、Ruby、C#、JavaScript、C++;对Web页面有良好的支持;简单(API 简单)、灵活(用开发语言驱动);支持分布式测试用例执行。chromeDriver驱动下载:http://chromedriver.storage.googleapis.com/index.html下载的驱动要和自己安装的谷歌浏览器版本相互匹配项目依赖包最新版可以在mvnrepository查找,链接如下<!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java --> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>${selenium.version }</version> </dependency> 使用手册1 导航1.1 打开网页driver.get("https://www.baidu.com") driver.navigate.to("https://www.baidu.com") // 区别:get是有逻辑的跳转,而navigate.to是直接跳转到该页面,没有任何逻辑 // 参考:https://blog.csdn.net/gaokao2011/article/details/171699691.2 获取当前页面url//返回的是字符串 String url = driver.getCurrentUrl(); //https://www.baidu.com System.out.println(url); 1.3 返回上一页driver.navigate.back();1.4 前进下一页面driver.navigate.forward();1.5 刷新当前页面driver.navigate.refresh();1.6 获取当前页面的titleString title = driver.getTitle(); //返回字符串 System.out.println(title); //百度一下,你就知道2 窗口、Tabs当driver打开一个新窗口时,若想操作新窗口上的元素,则需要将driver切换到新窗口2.1 获取当前窗口句柄//返回字符串 String currentWindowHandle = driver.getWindowHandle();2.2 获取所有窗口句柄//返回字符串集合 Set<String> allWindowHandles = driver.getWindowHandles(); 2.3 切换到新窗口//newHandle为要切换的新窗口的句柄 driver.switchTo().window(newHandle); 2.4 关闭窗口或tabsdriver.close();2.5 会话结束时退出浏览器driver.quit();3 Frames and IFrames当页面上有iframe和frame元素时,若想操作iframe和frame下的html元素,则需要切换driver3.1 切换到指定iframe或frameWebElement element_iframe = driver.findElement(By.id("iframe1")); driver.switchTo().frame(element_iframe);3.2 切换回父页面driver.switchTo().defaultContent();4 window管理4.1 获取窗口大小int width = driver.manage().window().getSize().getWidth(); int height = driver.manage().window().getSize().getHeight(); Dimension size = driver.manage().window().getSize(); int width = size.getWidth(); int height = size.getHeight();4.2 设置窗口大小driver.manage().window().setSize(new Dimension(1024,768));4.3 获取窗口位置int x = driver.manage().window().getPosition().getX(); int y = driver.manage().window().getPosition().getY(); Point position = driver.manage().window().getPosition(); int x = position.getX(); int y = position.getY();5 设置窗口5.1 设置窗口位置driver.manage().window().setPositon(new Point(0,0));5.2 最大化窗口driver.manage().window().maximize();5.3 全屏窗口driver.manage().window().fullscreen();6 定位driver.find 或 element.findfindElement(By.id("XXX")) findElement(By.name("XXX")) findElement(By.className("XXX")) findElement(By.cssSelector("XXX")) findElement(By.linkText("XXX")) findElement(By.partialLinkText("XXX")) findElement(By.tagName("XXX")) findElement(By.xpath("XXX")) findElements(By.id("XXX")) findElements(By.name("XXX")) findElements(By.className("XXX")) findElements(By.cssSelector("XXX")) findElements(By.linkText("XXX")) findElements(By.partialLinkText("XXX")) findElements(By.tagName("XXX")) findElements(By.xpath("XXX"))7 执行js脚本//声明一个js执行器 JavascriptExecutor js = (JavascriptExecutor) driver; js.executeScript("alert(123)");
2023年04月23日
290 阅读
0 评论
2022-12-26
Vue集成OnlyOffice组件实现在线预览
最近有个项目需要预览上传的附件(如:PDF、Excel、Word 等),且效果要好,Vue 插件中也有对应的插件:表格使用 xlsx 、文档使用 docx-prrview 、pdf 则使用 iframe 内嵌网页实现,公司的 OA 也是这样实现的,但是效果极差,之前使用 zfile 搭建私有网盘发现了一个 OnlyOffice 组件,实属不错,刚好对接一下,实现了附件预览。
2022年12月26日
1,905 阅读
1 评论
2022-12-22
Java mybatis中#和$的区别
在mybatis中#和$的主要区别是:#传入的参数在SQL中显示为字符串,$传入的参数在SqL中直接显示为传入的值. #方式能够很大程度防止sql注入,$方式无法防止Sql注入; 1、传入的参数在SQL中显示不同#传入的参数在SQL中显示为字符串(当成一个字符串),会对自动传入的数据加一个双引号。例:使用以下SQLselect id,name,age from student where id =#{id} 当我们传递的参数id为 "1" 时,上述 sql 的解析为: select id,name,age from student where id ="1"$传入的参数在SqL中直接显示为传入的值例:使用以下SQLselect id,name,age from student where id =${id} 当我们传递的参数id为 "1" 时,上述 sql 的解析为: select id,name,age from student where id =12、#可以防止SQL注入的风险(语句的拼接);但$无法防止Sql注入。3、$方式一般用于传入数据库对象,例如传入表名。4、大多数情况下还是经常使用#,一般能用#的就别用$;但有些情况下必须使用$,例:MyBatis排序时使用 order by 动态参数时需要注意,用$而不是#。
2022年12月22日
144 阅读
0 评论
2022-12-09
Java 工具类Util中的@Value注解注入为空解决方案
Java 工具类Util中的@Value注解注入为空 解决方案
2022年12月09日
328 阅读
0 评论
2022-09-11
oracle.jdbc.driver.OracleDriver is deprecated.Having use oracle.jdbc.OracleDriver.
最近的状态就是忙、加班、加班。刚刚闲下来,想起来今天项目中遇到一个异常,有些强迫症就想把它解决了,顺便水篇文章。oracle.jdbc.driver.OracleDriver is deprecated.Having use oracle.jdbc.OracleDriver.这个原因是:oracle.jdbc.driver.OracleDriver连接过时了,改成oracle.jdbc.OracleDriver即可.水完文章睡觉,明天继续加班。
2022年09月11日
804 阅读
4 评论
2022-08-07
Oracle定义DES加密解密及MD5加密函数
最近在研究公司的中台,通过 数据库服务化 提供接口对外使用,部分敏感数据需要加密,且根据密文可解密,这让我就发现了数据库加密函数,现在分享给大家。DES加密函数create or replace function encrypt_des(p_text varchar2, p_key varchar2) return varchar2 is v_text varchar2(4000); v_enc varchar2(4000); raw_input RAW(128) ; key_input RAW(128) ; decrypted_raw RAW(2048); begin v_text := rpad( p_text, (trunc(length(p_text)/8)+1)*8, chr(0)); raw_input := UTL_RAW.CAST_TO_RAW(v_text); key_input := UTL_RAW.CAST_TO_RAW(p_key); dbms_obfuscation_toolkit.DESEncrypt(input => raw_input,key => key_input,encrypted_data =>decrypted_raw); v_enc := rawtohex(decrypted_raw); dbms_output.put_line(v_enc); return v_enc; end;DES解密函数create or replace function decrypt_des(p_text varchar2,p_key varchar2) return varchar2 is v_text varchar2(2000); begin dbms_obfuscation_toolkit.DESDECRYPT(input_string => UTL_RAW.CAST_TO_varchar2(p_text),key_string =>p_key, decrypted_string=> v_text); v_text := rtrim(v_text,chr(0)); dbms_output.put_line(v_text); return v_text; end;MD5加密函数CREATE OR REPLACE FUNCTION MD5(passwd IN VARCHAR2) RETURN VARCHAR2 IS retval varchar2(32); BEGIN retval := utl_raw.cast_to_raw(DBMS_OBFUSCATION_TOOLKIT.MD5(INPUT_STRING => passwd)) ; RETURN retval; END;函数使用示例DES加密:select encrypt_des('', '密文');DES解密:select decrypt_des('', '密文')MD5加密:md5('');结尾语此函数未对null和空数据进行判断,可能会出现错误,请自行调整业务需求
2022年08月07日
594 阅读
4 评论
2022-06-08
SpringCloud Nacos命名空间配置
今天研究公司自己的SpringCloud框架,发现好多配置都搞的环境变量,因为开发周期短,又不能给开发细说,所以需要内置写死,这样就方便大伙快速开发,但是一直有一个问题,服务注册到Nacos一直注册不到配置的命名空间,而是注册到默认的public空间下了。使用万能的度娘,查到的资料和配置文件,都是一样的内容,但还是注册不到自定义的命名空间下。后来请教了研发中心的大佬们,才解决这个问题。顺便做一个配置文件的小记录,分享给大家,希望也能解决各位的问题(本人小菜鸡,欢迎各位指导)。spring: application: name: @artifactId@ cloud: nacos: discovery: server-addr: ${NACOSENDPOINTS:nacos-address:8848} namespace: ${NACOS_NAMESPACE:${spring.profiles.active}} config: server-addr: ${spring.cloud.nacos.discovery.server-addr} file-extension: yml shared-configs: - application.${spring.cloud.nacos.config.file-extension} namespace: ${NACOS_NAMESPACE:${spring.profiles.active}}与度娘查到的资料唯一不同的是在discovery下增加一个namespace命名空间。
2022年06月08日
505 阅读
7 评论
1
2
3
...
5