类型溢出原理
什么叫类型溢出
基本的数据类型(long,int,short,byte,char,float,double)都有自己能够保存的数据范围。
long(长整型)的数据范围:-9223372036854775808~9223372036854775807;
int(整型)的数据范围:-2147483648~2147483647;
short(短整型):-32768~32767;
byte(位):-128~127;
char(字符型):0~65536;
float(单精度浮点型):-3.4E38(-3.4X10的38次方)~3.4E38(3.4X10的38次方);
double(双精度浮点型):-1.7E38~1.7E38;
类型溢出就是:
当某一种类型的数值已经达到了此类型能够保存的最大值之后,再继续扩大,或者达到了最小值后再继续缩小,就会出现数据溢出问题。
由于整形运算过程中,结果占取了首高位,将原本的符号位改变成了1,因此造成负数的过程。
首高位是符号位,0表示+,1表示-。
解决方法:
- 当第一和第二因子都在整形范围内时,可以将程序定义的那个因子修改为更大范围的整长型
- 通常情况下,两个运算因子中,有一个是由程序定义的;因此只需要限制第二因子的输入范围(最大值、边界值)
- 通常情况下,用户输入的都是字符串,限制字符串的长度
- 基于程序本身的处理
int溢出:
public class MyDemo{
public static void main(String args []){
int a = 2147483647;
System.out.println(a + 1);
}
}
输出结果:
-2147483648
解决方法
在整型中,能够保存的数值范围最大的是long型;
在浮点型中,能够保存的数值范围最大的是double型;
在存在交互的环境下,设置本地端的数据类型为范围大的类型:long、double,设置输入端的数据类型为范围小的类型:int、float,这样计算得出的结果是long、double类型,且不会导致类型溢出;
public class MyDemo{
public static void main(String args []){
Scanner a = new Scanner(System.in);
//限制输入类型为int
int a;
//计算用的本地数据用long型,int与long计算的出的结果为long型
long b = (long)a;
System.out.println(b+2);
}
}
包装类型
每一个基本数据类型都对应了一个引用数据类型;使引用数据类型来表示基本数据类型
包装类型的作用:将基本数据类型装换成引用数据类型:
1.判断类型
2.用于转型
short --> Short
int --> Integer
long --> Long
float --> Float
double --> Double
byte --> Byte
boolean --> Boolean
char --> Character
转型
小转大,直接转,大转小,强制转;
字符串转基本类型需要用包装类型所提供的方法进行 。
形参、实参
形参:定义函数时,申明函数需要接收的参数个数、类型、顺序。
实参:调用函数过程中给函数传入的实际参数值,参数的传入过程必须按照形参定义的顺序、个数和类型传入。
注入原理
防御手段中,破坏规则比清除危险项效果更好。
替换敏感词
public class Replace {
public static void main(String[] args){
String s = "< script >";
do{
//使用ascii对字符进行转换,32-空格符,42-*;
s = s.replace((char)32,(char)42);
//循环替换字符串中的空格,直到没有空格
}while (s.indexOf(32) > 0);
System.out.println(s);
}
}
限制文件上传类型
public class Up {
public static void main(String[] args){
String fileName = "image.jpg.exe";
//lastIndexOf(start,end):判断start~end之间的字符是否存在
int start = fileName.lastIndexOf(".");
//substring(start,end):截取start~end之间的字符
String type = fileName.substring(start);
//匹配后缀为jpg的字符串
if(type.equalsIgnoreCase("jpg")){
System.out.println("图片文件");
}else{
System.out.println("其他文件");
}
}
}
文件传输黑名单:
public class EndWith {
public static void main(String[] args){
String filename = "image.jpg";
//endsWith:判断 jpg 结尾的文件
if(filename.endsWith("jpg")){
System.out.println("图片文件");
}else{
System.out.println("其他文件");
}
}
}
白名单:
public class BaiMD {
public static void main(String[] args){
String filename = "image.gif";
//正则,字典中存入需要过滤的项
String s = "[a-zA-Z0-9]+.(jpg|bmp|jpeg|png|gif)";
//matches() 方法用于检测字符串是否匹配给定的正则表达式。
if(filename.matches(s)){
System.out.println("可以上传");
}else{
System.out.println("不能上传");
}
}
}
利用替换<,>,的方法破坏规则
package com.mtlk.demo;
//import org.omg.PortableInterceptor.ServerRequestInfo;
//import java.io.File;
import java.util.Scanner;
public class Guolv {
public static void main(String[] strings){
System.out.println("注入测试");
//创建一个数组,过滤请求参数中的非法字符,防止XSS攻击、SQL盲注等
String[] reg = {"(?:')|(?:--)|>|<|<>|html|`| |(/\\*(?:.|[\\n\\r])*?\\*/)|(\\b(frame|<frame|iframe|<iframe|img|<img|javascript|<javascript|script|<script|alert|select|update|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute)\\b)"};
//将用户输入的数据存放入parm中
Scanner parm = new Scanner(System.in);
while (true){
//next():next()不会获取字符前/后的空格/Tab键,只吸取字符,开始吸取字符(字符前后不算)直到遇到空格/Tab键/回车截止吸取;
//nextLine()获取字符前后的空格/Tab键,回车键截止。
String s = parm.nextLine();
//将字符转换成小写
s = s.toLowerCase();
//将字符转换成大写
//s = s.toUpperCase();
//从数组reg中取元素给p
for(String p:reg){
//将输入的字符串中与reg相同的元素替换成*
s = s.replaceAll(p, "*");
}
System.out.println(s);
}
}
}
Java流加密
//流加密 密匙个明文一样长
public class JM {
public static void main(String[] args){
//输入明文用 mes 接收
String mes = "trytoremember";
//输入密匙用 key 接收
String key = "try0123456789";
//将明文转换成字符数组用cs接收
char[] cs = mes.toCharArray();
//将密匙转换成字符数组用keys接收
char[] keys = key.toCharArray();
//新建一个ms字符组用来接收cs字符数组的长度
char[] ms = new char[cs.length];
//遍历字符数组
for(int i = 0; i<cs.length; i++) {
//将明文和密匙按位异或 得到的是整形
int j = cs[i] ^ keys[i];
//将整形j转换成字符型并存在ms中
ms[i] = (char)j;
}
//重新定义ms
String m = new String(ms);
System.out.println(m);
}
}