简介 SQL 注入是一种专门针对SQL语句的攻击方式。通过把SQL命令插入到web表单提交、输入域名或者页面请求的查询字符串中,利用现有的程序,来非法获取后台的数据库中的信息。在web的测试中涉及到的会比较多些。 注入原理 存在注入的原因是后台在编写程序时,没有对用户输入的数据做过滤。 例: 1、用户在某个输入框提交的参数是123。 浏览器提交的URL为: http://www.xxx.com/index.php?id=123 服务器后台执行SQL语句:select * from table1 where id = 123 此时是没有任何影响的。 2、 如果用户提交的参数是 123;drop table 服务器后台执行SQL语句: select * from table1 where id =123 ; drop table 相当于后台执行了两条SQL语句,查表,并且把table删除, 从而导致了SQL注入 检测注入的方法 目前主要有两种检测方式: 一、手工注入检测流程: 1. 判断是否存在注入点 www.abc.com/index.php?id=2 www.abc.com/index.php?id=2 and 1=1 www.abc.com/index.php?id=2 and 1=2 第2条返回正常, 第1,3条返回不正常说明id参数存在注入漏洞 2. 判定是否存在admin表 www.abc.com/index.php?id=2 and exists(select * from admin) 返回正常,存在admin表 3. 猜admin表中的字段名 www.abc.com/index.php?id=2 and exists(select username from admin) 返回正常 表示admin表存在username字段 4. 检测其他sql操作 二、工具检测: sqlmap: sqlmap是一个开源的渗透测试工具,可以用来进行自动化检测,利用SQL注入漏洞,获取数据库服务器的权限。 1. 下载地址 https://github.com/sqlmapproject/sqlmap.git 2. 常用命令 测试 以一个sqlmap检测URL为例: […]
View Details一、前言 ci/cd 持续集成持续交付,开发人员尝尝会遇到一些重复工作,比如一个asp.net的网站代码,写完之后要发布,然后再将发布内容移动到部署的服务器上再进行部署,就算你只改了一个页面上的一个字,也要将之前的发布部署过程重新做一遍。 CI 解决了这个重复性问题,开发人员只需git push 提交代码,剩下的工作交给CI , 做CI工作的有gitlab-ci/cd Jenkins k8s等,中小项目gitlab-ci比较合适,因为它更轻量级一些,本篇仅讨论gitlab的cicd功能。 二、环境 IP 角色 192.168.10.202(ubuntu) gitlab 192.168.10.208(centos) git,docker,gitlab-runner gitlab git docker 三者的安装 略。且本篇是以docker镜像方式部署 上图为gitlab-ci的过程,其实它只是省略了一些我们的手动发布部署过程,将其自动化,但原来的流程还是一个不能少。所以,我们要进行的第一步,就是手动实现一遍流程。 三、手动实现一遍 (gitlab服务器) 创建代码仓库—> (开发PC) git clone —> (开发pc) 修改代码,添加dockerfile —> (开发pc) git push —> (部署服务器) git pull —> (部署服务器) docker build ,docker run 1、创建代码仓库 在创建之前,需要在使用git的机器上设置好ssh,可以参考之前的https://www.cnblogs.com/hallejuayahaha/p/11996332.html 要注意的是,在部署机器上,gitlab-runner安装好后,需要添加一个gitlab-runner的用户,需要添加这个用的ssh,因为在ci自动化后,在部署服务器上的操作都是由这个用户来做的,所以不仅要添加它的ssh,也要docker 免去sudo的指令。 总之就是让gitlab-runner用户,在做部署过程中,不要受到权限的阻碍。 ******docker免去敲sudo******* 在安装完docker之后,也会出现一个docker用户组,将你要免去敲sudo的用户添加进去,就可以了
1 |
sudo usermod -aG docker gitlab-runner |
添加代码仓库 并将一个.netcore项目创建进去 添加dockerfile文件,仅需在项目上右键,docker支持,vs就可以自动添加。然后git push 这样开发pc端的代码就都提交到gitlab服务器上了, 2、部署端git pull ,docker build , docker run 镜像已经成功启动,打开浏览器,输入ip + 暴露出来的端口8090 PS: .NETCORE web中,startup.cs文件中,有 app.UseHsts(); app.UseHttpsRedirection(); 这两行要注释掉,不然网站回一直往https跳转,没法进入http的80端口 整个手动流程成功。 […]
View Details1.配合使用调用app原生的方法(h5页面不需要回调和数据) 实例1
1 2 3 4 5 6 7 8 9 |
// 通知客户端,token失效 callTokenLostToApp(){ let boswer = vm.config.getBrowser() if(boswer == 'isiOS'){ window.webkit.messageHandlers.tokenExpiredTransmit.postMessage(1); }else if(boswer == 'isAndroid'){ window.tokenExpiredTransmit.jsMethod(1) } }, |
实例2
1 2 3 4 5 6 7 8 9 |
// 关闭页面 closePageApp(cb){ let boswer = vm.config.getBrowser() // IOS 关闭页面 if(boswer == 'isiOS'){ // 这段代码是固定的,必须要放到js中 window.webkit.messageHandlers.closePage.postMessage(1); // 安卓关闭页面 }else if(boswer == 'isAndroid'){ window.closePage.jsMethod(1) } }, |
2.配合使用调用app原生的方法(h5页面需要回调和数据) // 从App获取UUID(手机唯一标识)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
// 从App获取UUID(手机唯一标识) getSystemInfoFromApp(cb){ let boswer = vm.config.getBrowser() // IOS 获取UUID if(boswer == 'isiOS'){ // 这段代码是固定的,必须要放到js中 function setupWebViewJavascriptBridge(callback) { if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); } if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); } window.WVJBCallbacks = [callback]; var WVJBIframe = document.createElement('iframe'); WVJBIframe.style.display = 'none'; WVJBIframe.src = 'wvjbscheme://__BRIDGE_LOADED__'; document.documentElement.appendChild(WVJBIframe); setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0) } /*与OC交互的所有JS方法都要放在此处注册,才能调用通过JS调用OC或者让OC调用这里的JS*/ setupWebViewJavascriptBridge(function(bridge) { /*JS给ObjC提供公开的API,ObjC端通过注册,就可以在JS端调用此API时,得到回调。ObjC端可以在处理完成后,反馈给JS,这样写就是在载入页面完成时就先调用*/ bridge.callHandler('getSystemInfoFromApp', function(responseData) { if(cb && typeof cb == 'function'){ cb(responseData) }else{ return responseData } }) }) // 安卓获取UUID }else if(boswer == 'isAndroid'){ let systemInfo = window.AndroidWebView.getSystemInfoFromApp(); if(cb && typeof cb == 'function'){ cb(systemInfo) }else{ return systemInfo } } }, |
标红字段为调用的app端定义的方法名,需要app端定义方法配合 from:https://www.cnblogs.com/wendyAndJken/p/9318501.html
View Details使用IDEA创建gradle项目后,执行main方法时会自动运行gradle的一些build task,导致启动很慢,如下图: 解决方法: 打开设置页面,进行如下修改: from:https://zhoujun.blog.csdn.net/article/details/103372893
View Details一般情况下,DO是用来映射数据库记录的实体类,DTO是用来在网络上传输的实体类。两者的不同除了适用场景不同外还有就是DTO需要实现序列化接口。从DB查询到数据之后,ORM框架会把数据转换成DO对象,通常我们需要再把DO对象转换为DTO对象。同样的,插入数据到DB之前需要将DTO对象转换为DO对象然后交给ORM框架去执行JDBC。 通常用到的转换工具类BeanUtils是通过反射来实现的,实现源码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
public static <T> T convertObject(Object sourceObj, Class<T> targetClz) { if (sourceObj == null) { return null; } if (targetClz == null) { throw new IllegalArgumentException("parameter clz shoud not be null"); } try { Object targetObj = targetClz.newInstance(); BeanUtils.copyProperties(sourceObj, targetObj); return (T) targetObj; } catch (Exception e) { throw new RuntimeException(e); } } private static void copyProperties(Object source, Object target, Class<?> editable, String[] ignoreProperties) throws BeansException { Assert.notNull(source, "Source must not be null"); Assert.notNull(target, "Target must not be null"); Class<?> actualEditable = target.getClass(); if (editable != null) { if (!editable.isInstance(target)) { throw new IllegalArgumentException("Target class [" + target.getClass().getName() + "] not assignable to Editable class [" + editable.getName() + "]"); } actualEditable = editable; } PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable); List<String> ignoreList = (ignoreProperties != null) ? Arrays.asList(ignoreProperties) : null; for (PropertyDescriptor targetPd : targetPds) { if (targetPd.getWriteMethod() != null && (ignoreProperties == null || (!ignoreList.contains(targetPd.getName())))) { PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName()); if (sourcePd != null && sourcePd.getReadMethod() != null) { try { Method readMethod = sourcePd.getReadMethod(); if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) { readMethod.setAccessible(true); } Object value = readMethod.invoke(source); Method writeMethod = targetPd.getWriteMethod(); if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) { writeMethod.setAccessible(true); } writeMethod.invoke(target, value); } catch (Throwable ex) { throw new FatalBeanException("Could not copy properties from source to target", ex); } } } } } |
也可以通过mapstruct来实现,这种方式是在Mapper接口的包中生成一个对应mapper的实现类,实现类的源码如下。显然这种方式的实现更为普通,看起来没有BeanUtils的实现那么复杂。不过BeanUtils通过反射实现更为通用,可以为各种类型的DTO实现转换。而mapstruct只是帮我们生产了我们不想写的代码。
1 2 3 4 5 6 7 8 9 10 11 12 |
public Task doToDTO(TaskDO taskDO) { if (taskDO == null) { return null; } else { Task task = new Task(); task.setId(taskDO.getId()); //其他字段的set task.setGmtCreate(taskDO.getGmtCreate()); task.setGmtModified(taskDO.getGmtModified()); return task; } } |
对比以上两种方式,显然使用BeanUtils来进行转换时需要写的代码更少,内部的通过反射便可以进行get/set操作。而mapstruct实现上需要写的代码稍微多一点,但是这种方式的性能比通过反射实现更好。下面写一段代码来测试两种方式实现的性能差别。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public void testConvert() { System.out.println("####testConvert"); int num = 100000; TaskDO taskDO = new TaskDO(); long start = System.currentTimeMillis(); for (int i = 0; i < num; i ++) { Task task = ObjectConvertor.convertObject(taskDO, Task.class); } System.out.println(System.currentTimeMillis() - start); //--------------------------------------------- start = System.currentTimeMillis(); for (int i = 0; i < num; i ++) { Task task = taskMapper.doToDTO(taskDO); } System.out.println(System.currentTimeMillis() - start); } |
以上测试代码中分别使用两种方式对同一个DO对象进行n次转换,两次转换的耗时统计如下。单位:ms 次数 1 10 100 1000 10000 100000 1000000 10000000 Mapstruct 0 1 1 1 2 4 8 8 BeanUtil 9 7 11 26 114 500 1469 14586 可见当转换数量级增加时,使用BeanUtil的耗时急剧上升,而使用Mapstruct的耗时则保持在比较低的水平。 在一个系统中,ORM对DB的各种操作几乎都会涉及到DO和DTO之间的转换,参考以上表格的统计结果,更推荐使用Mapstruct。 from:https://www.cnblogs.com/umgsai/p/8570652.html
View Details1、PO即persistant Object 持久对象: 在O/R 映射(即ORM-ObjectRelationMapping)中出现的概念,通常对应数据模型(数据库),是与数据库汇总的表想影射的java对象,最简单的PO就是对应数据库中某个表中的一条记录,多个记录则用PO的集合。PO中不应该包含任何对数据库的操作。 2、DO即Domain Object 领域对象: 是从现实世界中抽象出来的有形或无形的业务实体。 3、TO即Transfer Object数据传输对象: 不同应用程序之间传输的对象 4、DTO即Data Transfer Object:数据传输对象: 泛指用于展示层与服务层之间的数据传输对象 5、VO即value Object: 通常用于业务层之间的数据传递,和PO一样仅包含数据,但是抽象出的业务对象,可以和表对应,用new 关键字创建,GC回收 6、BO即Business Object 业务对象: 主要是将业务逻辑封装为一个对象,这个对象可以包含一个或多个其他对象,如一个简历中包含教育经历、工作经历、社会关系等,可以将一个教育经历对应一个PO、工作经历对应一个PO、设计关系对应一个PO,然后简历一个对应简历的BO兑现处理简历,每个BO包含这个PO这样处理业务逻辑是,可以针对BO去处理。封装业务逻辑的java对象,通过调用DAO方法,结合PO,VO进行业务操作。 7、POJO即Plain Ordinary Java Object: 简单无规则的java对性,即在一些O/R 映射工具中,能做到维护数据库表记录的PO完全是一个符合Java Bean规范的纯java对象 from:https://blog.csdn.net/weixin_44122921/article/details/85038513
View Details将map集合转为json对象时遇到一个问题。map中 updateTime的value为日期格式如"2001-01-01",在使用 JSONObject.toJSON(map).toString() 的时候, 得到的结果 updateTime 的值为 时间戳 解决方法: 使用fastjson 的 JSON.toJSONStringWithDateFormat(Object,dateformat,SerializerFeature.WriteDateUseDateFormat) 方法即可将时间戳转换为自定义格式类型的值 from:https://blog.csdn.net/qq_39564789/article/details/105176845
View DetailsObject转JSON字符串: String jsonStr = JSONObject.toJSONString(object); JSON字符串转JSONObject: JSONObject jsonObject = JSONObject.parseObject(jsonStr); JSON字符串转Object对象 T t = JSON.parseObject(jsonStr,T.class); —–注:JSON字符串是有格式要求的,必须为键值对形式,不是任意的字符串。—– ——————— 作者:KnifeBlade 来源:CSDN 原文:https://blog.csdn.net/qq_29468573/article/details/82190005
View Details在使用fastjson进行数据类型转换时发现,pojo类里面的属性首字母大写,在转成json之后,变成了小写。导致数据存储一直有问题。 转换之后结果为: 导致数据存储失败。(使用json传值进行持久化操作。) 解决方法: 在pojo类的属性get方法上加上你需要的key。 这样转换的json,对应的key就改变为你注解对应的属性名。 from:https://blog.csdn.net/cuuuc233/article/details/80983486
View DetailsJSONObject.toJSONString(Object object, SerializerFeature… features) Fastjson的SerializerFeature序列化属性 QuoteFieldNames———-输出key时是否使用双引号,默认为true WriteMapNullValue——–是否输出值为null的字段,默认为false WriteNullNumberAsZero—-数值字段如果为null,输出为0,而非null WriteNullListAsEmpty—–List字段如果为null,输出为[],而非null WriteNullStringAsEmpty—字符类型字段如果为null,输出为”“,而非null WriteNullBooleanAsFalse–Boolean字段如果为null,输出为false,而非nul
1 2 3 4 5 6 7 8 9 |
Map < String , Object > jsonMap = new HashMap< String , Object>(); jsonMap.put("a",1); jsonMap.put("b",""); jsonMap.put("c",null); jsonMap.put("d","dddddddddd"); String str = JSONObject.toJSONString(jsonMap,SerializerFeature.WriteMapNullValue); System.out.println(str); //输出结果:{"a":1,"b":"","c":null,"d":"dddddddddd"} |
from:http://www.voidcn.com/article/p-ebkhpvlq-bqh.html
View Details