java安全编码指南之:表达式规则说明
作者:flydean程序那些事 发布时间:2021-06-01 17:48:44
简介
在java编写过程中,我们会使用到各种各样的表达式,在使用表达式的过程中,有哪些安全问题需要我们注意的呢?一起来看看吧。
注意表达式的返回值
我们在使用JDK库的时候,一定要注意认真的读一下JDK中方法的含义和它的返回值。
有些返回值可能表示这个操作是否成功,有的返回值可能是方法操作的结果。我们看两个常见的例子:
public void deleteFileWrong(){
File file= new File("/tmp/www.jb51.net.txt");
file.delete();
System.out.println("File delete success!");
}
public void deleteFileRight(){
File file= new File("/tmp/www.jb51.net.txt");
if(file.delete()){
System.out.println("File delete success!");
}
}
先看一个文件删除的例子,delete方法是有返回值的,所以我们在调用delete方法之后,一定要判断一下返回值,看是否删除成功。
再看一个常见的String中字符替换的例子:
public void stringReplaceWrong(){
String url="www.jb51.net";
url.replace("www","WWW");
System.out.println("replaced url..."+url);
}
public void stringReplaceRight(){
String url="www.jb51.net";
url=url.replace("www","WWW");
System.out.println("replaced url..."+url);
}
我们要记住,String是不可变的,所以它的replace方法,会返回一个替换过后的String,但是原String是不变的,所以我们需要将返回值重新赋值。
注意避免NullPointerException
NullPointerException应该是最最常见的运行时异常了。怎么避免这个异常呢?
我们要做的就是在调用object的方法时候,一定要判断这个object是不是为空。
在JDK8之后,我们引入了Stream操作:
public void streamWrong(Collection<Object> collection){
collection.stream().filter(obj->obj.equals("www.jb51.net"));
}
Stream操作的过程中,我们需要注意stream中的元素是否为空。
有时候,我们可能觉得已经判断是为空了,但是条件判断不准确,导致未知的异常,看下面这个例子:
public int countWrong(Collection<Object> collection, Object object){
int count=0;
if(collection ==null){
return count;
}
for(Object element: collection){
if((element ==null && object== null)
|| element.equals(object)){
count++;
}
}
return count;
}
这个例子是用来查找collection中到底有多少元素和object相同,如果两者都为空,也记为相同。
但是上面的例子有一个漏洞,它没有考虑element ==null 而 object !=null的情况,所以会导致NullPointerException的生成。
我们需要这样修改:
public int countRight(Collection<Object> collection, Object object){
int count=0;
if(collection ==null){
return count;
}
for(Object element: collection){
if((element ==null && object== null)
|| (element !=null && element.equals(object))){
count++;
}
}
return count;
}
数组相等的判断
如果我们需要比较两个数组是否相等,其实我们想比较的是两个数组中的元素是否相等。
我们知道数组是一个特殊的Object,那么数组对象也有一个equals方法,考虑下面的例子:
public boolean compareWrong(){
int[] array1 = new int[10];
int[] array2 = new int[10];
return array1.equals(array2);
}
返回的结果是false,因为数组直接使用了Object中定义的equals方法,我们看下该方法的定义:
public boolean equals(Object obj) {
return (this == obj);
}
可以看到,该方法比较的是两个地址是否相等。所以我们的到了false结果。
其实,我们可以使用Arrays.equals工具类中的方法来进行两个数组的比较:
public boolean compareRight(){
int[] array1 = new int[10];
int[] array2 = new int[10];
return Arrays.equals(array1, array2);
}
基础类型的封装类间的比较
在java中,我们知道有一些基础类型像boolean, byte,char, short, int他们会有相对应的封装类型:Boolean,Byte,Character,Short,Integer等。
我们可以直接将基础类型的值赋值给封装类型,封装类型会自行进行转换。
考虑下面的例子:
Boolean boolA=true;
Boolean boolB=true;
System.out.println(boolA==boolB);
结果是多少呢?
答案是true。为什么两个不同对象的比较会是true呢?
在回答这个问题之前,我们看一下字符串的比较:
String stringA="www.jb51.net";
String stringB="www.jb51.net";
System.out.println(stringA==stringB);
这个我们大家应该都知道,因为String有一个字符串常量池,直接从字符串常量构建的String对象,其实是同一个对象。
同样的对于Boolean和Byte来说,如果直接从基础类值构建的话,也是同一个对象。
而对于Character来说,如果值的范围在\u0000 to \u007f,则属于同一个对象,如果超出了这个范围,则是不同的对象。
对于Integer和Short来说,如果值的范围在-128 and 127,则属于同一个对象,如果超出了这个范围,则是不同的对象。
再考虑下面的例子:
Boolean boolA=true;
Boolean boolC=new Boolean(true);
System.out.println(boolA==boolC);
输出的结果是false,因为boolC使用了new关键字,构建了一个新的对象。
集合中类型不匹配
现在java集合可以通过指定类型,从而只存储特定类型的对象。考虑下面的一个例子:
public void typeMismatch(){
HashSet<Short> shortSet= new HashSet<>();
for(int i=0;i<10;i++){
shortSet.add((short)i);
shortSet.remove(i);
}
System.out.println(shortSet.size());
}
上面代码我们定义了一个Short的集合,然后将0-9添加进去,接着我们又调用了remove方法把i从集合删除。
但是最后输出结果是10,表明我们并没有删除成功。为什么呢?
看下HashSet的remove方法:
public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}
remove方法的参数是Object,我们传入的i是int类型的,跟short不匹配,所以导致删除失败。
我们需要这样修改:
public void typeMatch(){
HashSet<Short> shortSet= new HashSet<>();
for(int i=0;i<10;i++){
shortSet.add((short)i);
shortSet.remove((short)i);
}
System.out.println(shortSet.size());
}
Asset的副作用
我们会使用Asset语句在代码中做调试使用,在使用的过程中需要注意Asset语句不要对系统的业务逻辑产生副作用,也就是说即使Asset语句不运行,也不会修改代码的业务逻辑。
看下面的例子:
public void assetWrong(ArrayList<Integer> list){
assert list.remove(0)>0;
}
上的代码我们从list中删除第一个元素,并判断删除的元素是否大于0.
上面的代码如果assert语句不执行的话,会导致业务逻辑也不执行,所以需要修改成下面这样:
public void assetRight(ArrayList<Integer> list){
int result=list.remove(0);
assert result>0;
}
本文的例子:
learn-java-base-9-to-20/tree/master/security
补充知识:Slow HTTP Denial of Service Attack 漏洞解决
解决漏洞需要修改tomcat conf 下 server.xml 文件
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="2000" redirectPort="8443" URIEncoding="UTF-8"/> connectionTimeout="20"
来源:https://blog.csdn.net/superfjj/article/details/108461665


猜你喜欢
- java中对数组进行排序使用Array.sort() 这个默认是升序@Test public void index4(){ &n
- 使用ManagedWifi查看当前Wifi信号并选择wifiusing System;using System.Collections.Ge
- 最近因为项目的国际化的需要,需要对整个项目的100来个插件做国际化,这是一件痛苦的事情,因为纯体力劳动。为了省点工作量,想着能不能写个程序批
- 背景在很多时候我们代码中的一些逻辑操作并不能够硬编码到代码中,我们可能希望通过配置来完成这个操作,所以这个时候我们就需要有一些脚本语言能够处
- 日志过滤对于一个网站日志,首先要对它进行过滤,删除一些不必要的信息,我们通过scala语言来实现,清洗代码如下,代码要通过别的软件打包为ja
- 由于Android对单个应用所施加的内存限制,比如16MB,这导致加载Bitmap的时候很容易出现内存溢出,本文主要包含2个方面的内容分析B
- 算法描述堆排序算法的描述如下:将待排序的数组调整为最大堆,此时未排序的长度 N 为数组的长度,调整的过程就是倒序将数组的
- 记录一下在项目中用纯 YML(application.yml 或者 application.properties)文件、Java 代码配置
- 背景数据之间两两趋势比较在数据分析应用中是非常常见的应用场景,如下所示:模拟考批次班级学生语文数学英语202302三年一班张小明130145
- 访问Controller返回400BadRequest问题SpringMVC使用自定义类型接收参数时, form提交会返回400 Bad R
- 本文实例为大家分享了Android实现歌词滚动效果的具体代码,供大家参考,具体内容如下自定义TextViewpublic class Ver
- 需求: 给定一个URL地址, 例如: http://www.cncounter.com/tools/shorturl.php, 解析对应的I
- 代码import javax.mail.internet.InternetAddress;import javax.mail.interne
- AsnyncLocal与ThreadLocal都是存储线程上下文的变量,但是,在实际使用过程中两者又有区别主要的表现在:AsyncLocal
- 最近在项目开发中,使用spring boot+mybatis的架构,数据库设计主键id时定义为bigint类型,使用mybatis的自动生成
- 最近在做图片相关的应用,所以就各方积累到一些常用的操作,一般来说会有多种方式来实现这一功能,比如 1.采用色度变换 2.
- 实现HandlerInterceptor接口或者继承HandlerInterceptor的子类,比如Spring 已经提供的实现了Handl
- 本文介绍的仿IOS对话框的实现,先来看一下效果图具体代码如下:public class AlertDialog { private Cont
- 前言跳过废话,直接看正文当年入坑Java是因为它的跨平台优势。那时我认为,”编写一次,处处运行。”这听上去多么牛逼,应该是所有语言发展的终极
- 总结:对应某个类的实例化的对象tc, 遍历获取所有属性(子成员)的方法(采用反射):Type t = tc.GetType();//获得该类