代码审计实战积累

代码审计实战积累,第1张

记录在代码审计过程中,学习到的知识
估计内容会比较乱,也不知道怎么分类,就记录给自己看吧

传参

一、springMVC

springMVC获取请求参数:https://www.cnblogs.com/taozhiyaoyao99/p/15151811.html

@RequestMapping注解的作用就是将请求地址url和处理请求的控制器方法关联起来,建立映射关系。
位置:写在类,或方法上。
value属性:是一个字符串类型的数组,表示该请求映射能够匹配多个请求地址url 所对应的请求。
method属性:是一个RequestMethod类型的数组,表示该请求映射能够匹配 多种请求方式的请求 。
params属性:是一个字符串类型的数组,可以通过四种表达式设置请求参数 和请求映射的匹配关系。
“param”:要求请求映射所匹配的请求必须携带param请求参数。举例:username
“!param”:要求请求映射所匹配的请求必须不能携带param请求参数。
“param=value”:要求请求映射所匹配的请求必须携带param请求参数且param=value。
“param!=value”:要求请求映射所匹配的请求必须携带param请求参数但是param!=value。举例:password!=123456
headers属性:通过请求的请求头信息匹配请求映射,也有以上四种方式。举例:headers={“host=localhost:8080”}

注意:对于处理指定请求方式的控制器方法,SpringMVC中提供了@RequestMapping的派生注解@GetMapping、@PostMapping、@PutMapping、@DeleteMapping
可以直接使用以上注解代替method参数!

1.1 获取请求参数

1、通过ServletAPI获取
将HttpServletRequest作为控制器方法的形参,此时HttpServletRequest类型的参数表示封装了当前请求的请求报文的对象。

2、通过控制器方法的形参获取请求参数
在控制器方法的形参位置,设置和请求参数同名的形参,当浏览器发送请求,匹配到请求映射时,在 DispatcherServlet中就会将请求参数赋值给相应的形参。

3、@RequestParam

https://blog.csdn.net/sswqzx/article/details/84195043

url
将请求参数和控制器方法的形参创建映射关系
三个属性:
value:指定为形参赋值的请求参数的参数名
required:是否必须传输此请求参数,默认值为true
defaultValue:不管required属性值为true或false,当value所指定的请求参数没有传输或传输的值 为""时,则使用默认值为形参赋值

也可以接收对象类型

https://www.cnblogs.com/blackblack/p/13904187.html

int addPeople(@RequestParam People people) {}
//这时候使用@RequestParam注解修饰参数 只要前台传的参数名称和people类中的属性名一致就可以自动封装进People实体类

4、@RequestHeader
将请求头信息和控制器方法的形参创建映射关系
三个属性:value、required、defaultValue,用法同上
5、@CookieValue
将cookie数据和控制器方法的形参创建映射关系
三个属性:value、required、defaultValue,用法同上

6、通过POJO获取请求参数
可以在控制器方法的形参位置设置一个实体类类型的形参,此时若浏览器传输的请求参数的参数名和实体类中的属性名一致,那么请求参数就会为此属性赋值

二、@requestBody

内容基于Spring boot

@RequestBody的使用:https://blog.csdn.net/justry_deng/article/details/80972817/

@RequestBody主要用来接收前端传递给后端的json字符串中的数据的(请求体中的数据的);
一般用于处理非 Content-Type: application/x-www-form-urlencoded编码格式的数据,比如:application/json、application/xml等类型的数据。

get无请求体,使用请求体传参的是POST请求,所以使用@RequestBody接收数据时,一般都用POST方式进行提交。

在后端的同一个接收方法里,@RequestBody与@RequestParam()可以同时使用,@RequestBody最多只能有一个,而@RequestParam()可以有多个。

注:
如果后端参数是一个对象,且该参数前是以@RequestBody修饰的,那么前端传递json参数时,必须满足以下要求:

后端@RequestBody注解对应的类在将HTTP的输入流(含请求体)装配到目标类(即:@RequestBody后面的类)时,
会根据json字符串中的key来匹配对应实体类的属性,
如果匹配一致且json中的该key对应的值符合(或可转换为)

实体类的对应属性的类型要求时,会调用实体类的setter方法将值赋给该属性。

json字符串中,如果value为""的话,后端对应属性如果是String类型的,那么接受到的就是"",
如果是后端属性的类型是Integer、Double等类型,那么接收到的就是null。
json字符串中,如果value为null的话,后端对应收到的就是null。
如果某个参数没有value的话,在传json字符串给后端时,要么干脆就不把该字段写到json字符串中;
要么写value时, 必须有值,null  或""都行。


示例:
1、@RequestBody直接以String接收前端传过来的json数据:
后端对应的Controller:


测试

2、@RequestBody以简单对象接收前端传过来的json数据:
后端对应的Controller:

测试

还有好些个例子,看原文吧

三、@para

为什么要用@para
@para注解的用法解析:https://blog.csdn.net/qq_21040559/article/details/109105301

@Param是MyBatis所提供的(org.apache.ibatis.annotations.Param),作为Dao层的注解,
用于传递参数,从而可以与SQL中的的字段名相对应,
一般在2=<参数数量<=5时使用最佳

public List<Role> findRoleByAnnotation(@Param("roleName") String roleName, @Param("note") String note);

用法一、XML形式


用法二、注解形式

VO,DTO,PO对象

代码审计过程中,会发现有很多名称相似的类,如xxxVO,xxxDTO,xxxPO,然后他们之间又转来转去的,给人绕晕

https://blog.csdn.net/WB1224678/article/details/88891014

VO 是Value Object 的缩写,值对象,位于视图层,每一个字段与视图层所需要的字段对应。

DTO是Data Transfer Object 的缩写,数据传输对象,在视图层和服务层之间传输用来转换从PO到VO,或者从VO到PO的中间对象。

PO 是Persistent Object 的缩写,持久化对象,位于持久层,每一个字段,与数据库相对应。

对象转换

MapStruct优雅的转换bean对象:https://blog.csdn.net/czx2018/article/details/114696724

将业务相关的各种PO,VO,DTO对象互相转换,比较常用的工具类就是 BeanUtil ,但是BeanUtil有两个问题:1、底层使用了反射,效率不高。2、无法自定义转换规则,例如其中一个bean中的datetime是Date类型,而另一个bean中的datetime是String类型,这就无法转换过去了。
推荐bean转换工具:MapStruct

1、引入依赖
2、准备实体类

// VO类
@Data
public class DogVO {
    private int id;
    private String name;
    private int weight;
    private Date birthday;}
// PO类
@Data
public class DogPO {
    private int id;
    private String name;
    private int weight;
    private Date birthday;}

3、编写 DogConvertor 接口

@Mapper  //注意这里的注解是org.mapstruct.Mapper,不要引入错了,mybatis包也有个的@Mapper注解
public interface DogConvertor {
    DogConvertor INSTANCE = Mappers.getMapper(DogConvertor.class);
    /**
     * 将VO转为PO
     * @param vo
     * @return
     */
    DogPO voToPO(DogVO vo);
}

4、测试

    public static void main(String[] args) {
        //创建一个VO类
        DogVO dogVO = new DogVO();
        dogVO.setId(1);
        dogVO.setName("旺财");
        dogVO.setWeight(20);
        dogVO.setBirthday(new Date());
        //将VO类转换为PO类,实际上就是创建一个PO类,并将VO类的属性值都拷贝过去
        DogPO dogPO = DogConvertor.INSTANCE.voToPO(dogVO);
        System.out.println(dogPO);
    }

其他 *** 作:

1、属性名不同的转换

@Mapping(source = "name", target = "dogName")
    DogPO voToPO(DogVO vo);

2、属性类型不同的转换

    @Mappings({
            @Mapping(source = "name", target = "dogName"),
            @Mapping(target = "birthday", expression = "java(cn.hutool.core.date.DateUtil.format(vo.getBirthday(), \"yyyy-MM-dd HH:mm:ss\"))")
    })
    DogPO voToPO(DogVO vo);

3、多个bean合为一个bean
新建TailVO,有狗狗尾巴属性,同时DogPO里也增添这个属性

@Data
@AllArgsConstructor
public class TailVO {
    private int length;
}
    @Mappings({
            @Mapping(source = "vo.name", target = "dogName"), //由于多了一个参数,所以这里的必须要指定vo.name
            @Mapping(target = "birthday", expression = "java(cn.hutool.core.date.DateUtil.format(vo.getBirthday(), \"yyyy-MM-dd HH:mm:ss\"))"),
            @Mapping(source = "tailVO.length", target = "tailLength")
    })
    DogPO voToPO(DogVO vo, TailVO tailVO);
加密

密码加密 bcrypt模块的基本使用:https://www.it610.com/article/1304594116109176832.htm

看代码时不懂,以为bcrypt.genSalt(10)里的10数值是个固定的盐还是啥的,看着有点简单觉得好像有风险,搜搜才知道,10代表了复杂度

Lambda表达式

https://blog.csdn.net/qq_37465368/article/details/82908646
http://blog.oneapm.com/apm-tech/226.html

一种匿名函数(对 Java 而言这并不完全正确,但现在姑且这么认为)
没有声明的方法,也即没有访问修饰符、返回值声明和名字。
方法只使用一次,而且定义很简短,就不必在类中费力写声明与方法了。

Java 中的 Lambda 表达式通常使用 (argument) -> (body) 语法书写,例如:
(arg1, arg2...) -> { body }
(type1 arg1, type2 arg2...) -> { body }

以下是一些 Lambda 表达式的例子:
(int a, int b) -> {  return a + b; }
() -> System.out.println("Hello World"); 
(String s) -> { System.out.println(s); }
() -> 42
() -> { return 3.1415 };

assert断言

https://www.jianshu.com/p/3f2be2af12a4

unit.framework包下的Assert提供了多个断言方法.。
主用于比较测试传递进去的两个参数

使用比较简单,主要有以下函数:
1、Assert.assertEquals([String message],T expected,T actual)
比较两个参数是否相等,
message是可选的消息,假如加入了该参数,则发生错误时会报告该消息。

2、Assert.assertNotEquals([String message],T expected,T actual)
比较两个参数是否不相等。

3、Assert.assertSame([String message],T expected,T actual)
以expected==actual运算的结果来判断。

expected.equals(actual) 和 expected==actual 的差别在于。
如果expected没有重写java.lang.Object的equals方法,那么就是两个java对象的内存地址比较,比较结果和 expected==actual的结果相同。
如果expected重写了equals方法(比如GregorianCalendar,BigDecimal类),那么比较的结果不一定和expected==actual的结果相同。

4、Assert.assertNotSame([String message],T expected,T actual)
以expected != actual运算的结果来判断。

5、Assert.assertTrue([String message],boolean condition)
如果表达式condition结果为真,则测试通过,message为可选信息,若有则condition结果为假时显示message的内容

6、Assert.assertFalse([String message],boolean condition)
如果表达式condition结果为假,则测试通过

7、Assert.assertArrayEquals([String message], Object[] expected, Object[] actual)
以最直接的方式比较数组:如果数组长度相同,且每个对应的元素相同,则两个数组相等,否则不相等。

8、Assert.assertNotNull([String message], Object object)
断言object为空

9、Assert.assertNotNull([String message], Object object)
断言object不为空

10、Assert.assertThat([String reason],T actual, Matcher matcher)
其中actual为需要测试的变量,matcher为使用Hamcrest的匹配符来表达变量actual期望值的声明;
assertThat是Junit 4.4加入的新方法,理论上讲程序员可以只使用 assertThat 一个断言语句,结合 Hamcrest 提供的匹配符,就可以表达全部的测试思想。

cors跨域

cors漏洞简介:https://blog.csdn.net/qq_35569814/article/details/101068142

源码里显示,响应包Access-Control-Allow-Origin的值为请求包内origin字段的值。

 httpResponse.setHeader("Access-Control-Allow-Origin", origin);

该漏洞同时需要Access-Control-Allow-Credentials值为true,默认为true。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/756399.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-30
下一篇 2022-04-30

发表评论

登录后才能评论

评论列表(0条)

保存