Java及网络基础

206 阅读26分钟

1、位运算符:

2、输入输出流

 /**
     * 文件读写
     */
    static class FilrWrite{
        /**
         * 字节流读取文件
         */

        public static void InputStream() throws Exception {
            File file = new File("E:\\aaa.txt");
            InputStream inputStream = new FileInputStream(file);
            int k;
            StringBuffer str = new StringBuffer();
            byte[] bytes = new byte[inputStream.available()];

            if((k = inputStream.read(bytes)) != -1){
                str = str.append(new String(bytes));
            }

            inputStream.close();
            System.out.println(str);
        }

        /**
         * 字节流写入文件
         */

        public static void OuputStream() throws Exception {
            File file = new File("E:\\aaa.txt");
            OutputStream outputStream = new FileOutputStream(file);

            String text = "明天也是晴天";
            outputStream.write(text.getBytes());
            outputStream.close();

            InputStream();

        }

        /**
         * 字符流读取文件
         */
        public static void FileReader() throws Exception {
            File file = new File("E:\\aaa.txt");
            FileReader fileReader = new FileReader(file);
            BufferedReader bufferedReader = new BufferedReader(fileReader);

            StringBuffer str = new StringBuffer();
            String temp = "";
            while ((temp = bufferedReader.readLine()) != null){
                str = str.append(temp);
            }

            fileReader.close();
            bufferedReader.close();

            System.out.println(str);

        }

        /**
         * 字符流写入文件
         */
        public static void FileWriter() throws Exception {
            File file = new File("E:\\aaa.txt");
            FileWriter writer = new FileWriter(file);

            String text = "后天会更好";
            writer.write(text);
            writer.flush();//写入
            writer.close();//在关闭字符流时会强制性地将缓冲区中的内容进行输出

            FileReader();

        }



        public static void main(String[] args) throws Exception {
//            InputStream();

//            OuputStream();

//            FileReader();

            FileWriter();
        }
    }

3、重写、重载

4、多态

5、抽象类

6、接口

7、序列化

8、多线程

实现方式:

1、实现Runnable接口

2、继承Thread类重写run方法

3、通过 Callable 和 Future 创建线程

4、线程池 ThreadPoolExecutor

9、错误和异常的区别(Error vs Exception)

Java异常的基类为java.lang.Throwable,java.lang.Error和java.lang.Exception继承 Throwable,RuntimeException和其它的Exception等继承Exception

1)

  • java.lang.Error: Throwable的子类,用于标记严重错误。try/catch 不能捕获
  • java.lang.Exception: Throwable的子类,非严重错误,try/catch 可以捕获

2)

  • Error和RuntimeException 及其子类都是未检查的异常(unchecked exceptions),而所有其他的Exception类都是检查了的异常(checked exceptions).
  • checked exceptions: 通常是从一个可以恢复的程序中抛出来的,并且最好能够从这种异常中使用程序恢复。比如FileNotFoundException, ParseException等。检查了的异常发生在编译阶段,必须要使用try…catch(或者throws)否则编译不通过。
  • unchecked exceptions: 通常是如果一切正常的话本不该发生的异常,但是的确发生了。发生在运行期,具有不确定性,主要是由于程序的逻辑问题所引起的。比如ArrayIndexOutOfBoundException, ClassCastException等。

如果没有异常出现,而且finally语句中没有return,则会执行try里边的return,并且,会将变量暂存起来(对象存的是引用的地址),再去执行finally中的语句,这时候,如果返回值是基本数据类型或者字符串,则finally相当于更改副本,不会对暂存值有影响;但是,如果返回值是对象,则finally中的语句,仍会根据地址的副本,改变原对象的值

10、常见集合类关系图

11、八种基本类型。六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型

12、创建对象的四种方式

    public static void main(String[] args) throws Exception {
        //todo 创建对象的四种方式

        //1、使用new关键字
        Book book1 = new Book();
        System.out.println(book1);

        //2、使用反射机制
        //使用Class类的newInstance方法
        Book book2 = (Book) Class.forName("com.test.entity.Book").newInstance();
        System.out.println(book2);
        Book book3 = Book.class.newInstance();
        System.out.println(book3);

        //使用Constructor类的newInstance方法
        Constructor<Book> constructor = Book.class.getConstructor();
        Book book4 = constructor.newInstance();
        System.out.println(book4);

        //3、使用clone方法
        //无论何时我们调用一个对象的clone方法,jvm就会创建一个新的对象,将前面对象的内容全部拷贝进去。用clone方法创建对象并不会调用任何构造函数。
        //要使用clone方法,我们需要先实现Cloneable接口并实现其定义的clone方法。

        Book book5 = (Book) book4.clone();
        System.out.println(book5);
        System.out.println("原对象与克隆对象是否相同:"+(book4 == book5));

        //4、用对象流来实现 前提是对象必须实现 Serializable
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(
                new FileOutputStream(filename));
        objectOutputStream.writeObject(book5);
        ObjectInput input=new ObjectInputStream(new FileInputStream(filename));
        Book book6 = (Book) input.readObject();
        System.out.println(filename);
        System.out.println(book6);
        System.out.println("原对象与复制对象是否相同:"+(book6 == book5));

    }


    private static String filename = Book.class.getResource("").getPath()
            + "/obj.txt";
    static File file = new File(filename);
    static {
        if (!file.exists())
            try {
                file.createNewFile();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

    }

13、加密算法

14、Spring 数据库连接等配置加密

地址:


15、静态语句块、构造语句块(就是只有大括号的那块)以及构造函数的执行顺序

对象的初始化顺序:

(1)类加载之后,按从上到下(从父类到子类),从前到后执行被static修饰的语句或静态属性,然后执行普通属性初始化。

(2)如果有语句new了自身的对象,将从上到下执行构造代码块、构造器(两者可以说绑定在一起)。

(3)static初始化块不能访问非statci成员,也不能调用非static方法,并且只在类加载时执行一次。

    static class HelloA {

        public HelloA() {
            System.out.println("HelloA");
        }

        {
            System.out.println("I'm A class");
        }

        static {
            System.out.println("static A");
        }

    }

    static class HelloB extends HelloA {
        public HelloB() {
            System.out.println("HelloB");
        }

        {
            System.out.println("I'm B class");
        }

        static {
            System.out.println("static B");
        }

        public static void main(String[] args) {
            new HelloB();
            new HelloB();
        }
    }

结果:

static修饰的语句 --> 构造代码块 --> 构造器

最终结论:

    1.父类静态属性或静态代码块
    2.子类静态属性或静态代码块
    3.父类属性初始化
    4.父类构造代码块
    5.父类构造函数
    6.子类属性初始化
    7.子类构造代码块
    8.子类构造函数

例子:

    static class Dervied extends Base {
        private String name1 = "dervied";

        public Dervied() {
            tellName();
            printName();
        }

        public void tellName() {
            System.out.println("Dervied tell name: " + name1);
        }

        public void printName() {
            System.out.println("Dervied print name: " + name1);
        }

        public static void main(String[] args){

            new Dervied();
        }

        static {
            System.out.println("Dervied static");
        }
    }
    static class Base {
        static {
            System.out.println("Base static");
        }
        
        private static String value = "base";
        private String name = "base";

        public Base() {
            tellName();
            printName();
        }

        public void tellName() {
            System.out.println("Base tell name: " + name);
        }

        public void printName() {
            System.out.println("Base print name: " + name);
        }
    }

运行结果

16、多个catch语句块的异常捕获顺序

把子类放前面,因为子类的异常信息比父类更详细,父类放在前面编译报错

        try {
            throw new FileNotFoundException();

        } catch (FileNotFoundException ex) {

            System.out.print("FileNotFoundException!");

        } catch (IOException ex) {

            System.out.print("IOException!");

        } catch (Exception ex) {

            System.out.print("Exception!");

        }

17、java中(基本类型或对象)全局变量和局部变量的赋值方式不同。全局变量主动初始化,基本类型为0,引用类型为null。局部变量需要手动初始化

18、switch、case 不加break从匹配等到开始,后面的都执行

        public static int getValue(int i) {
            int result = 0;
            switch (i) {
                case 1:
                    result = result + i;
                    //break;
                case 2:
                    result = result + i * 2;
                    //break;
                case 3:
                    result = result + i * 3;
                    //break;

            }
            return result;
        }

输入2,不加break 返回10 , 加break返回4

19、网络协议

OSI参考模型,下面是协议层从底层至顶层的一个模型图:

OSI参考模型中每个分层的作用:

  • 应用层 : 为应用程序提供服务并规定应用程序中通信相关的细节

      1、超文本传输协议HTTP
    
      2、文件传送协议FTP
      
      3、DNS域名解析协议
      
      4、DHCP动态主机配置协议
    
  • 表示层:将应用处理的信息转换为适合网络传输的格式,或将来自下一层的数据转换为上层能够处理的格式;主要负责数据格式的转换,确保一个系统的应用层信息可被另一个系统应用层读取 具体来说,就是将设备固有的数据格式转换为网络标准传输格式,不同设备对同一比特流解释的结果可能会不同;因此,主要负责使它们保持一致

  • 会话层:负责建立和断开通信连接(数据流动的逻辑通路),记忆数据的分隔等数据传输相关的管理

  • 传输层:只在通信双方的节点上(比如计算机终端)进行处理,而无需在路由器上处理,传输层是OSI中最重要、最关键的一层,是唯一负责总体的数据传输和数据控制的一层;传输层提供端到端的交换数据的机制,检查分组编号与次序,传输层对其上三层如会话层等,提供可靠的传输服务,对网络层提供可靠的目的地站点信息主要功能 包括的协议如下:

      1、TCP:传输控制协议,传输效率低,可靠性强
    
      2、UDP:用户数据报协议,适用于传输可靠性要求不高,数据量小的数据(比如QQ)
    
      3、DCCP、SCTP、RTP、RSVP、PPTP等协议
    
  • 网络层:将数据传输到目标地址;目标地址可以使多个网络通过路由器连接而成的某一个地址,主要负责寻找地址和路由选择,网络层还可以实现拥塞控制、网际互连等功能 在这一层,数据的单位称为数据包(packet) 网络层协议的代表包括:IP、IPX、RIP、OSPF等

  • 数据链路层:负责物理层面上的互联的、节点间的通信传输(例如一个以太网项链的2个节点之间的通信);该层的作用包括:物理地址寻址、数据的成帧、流量控制、数据的检错、重发等。 在这一层,数据的单位称为帧(frame) 数据链路层协议的代表包括:ARP、RARP、SDLC、HDLC、PPP、STP、帧中继等

  • 物理层:负责0、1 比特流(0/1序列)与电压的高低、逛的闪灭之间的转换 规定了激活、维持、关闭通信端点之间的机械特性、电气特性、功能特性以及过程特性;该层为上层协议提供了一个传输数据的物理媒体。只是说明标准 在这一层,数据的单位称为比特(bit) 属于物理层定义的典型规范代表包括:EIA/TIA RS-232、EIA/TIA RS-449、V.35、RJ-45、fddi令牌环网等

HTTP简介

HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。

HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)。

HTTP是一个属于应用层的面向对象的协议,由于其简捷、快速的方式,适用于分布式超媒体信息系统。它于1990年提出,经过几年的使用与发展,得到不断地完善和扩展。目前在WWW中使用的是HTTP/1.0的第六版,HTTP/1.1的规范化工作正在进行之中,而且HTTP-NG(Next Generation of HTTP)的建议已经提出。

HTTP协议工作于客户端-服务端架构为上。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。Web服务器根据接收到的请求后,向客户端发送响应信息。

HTTP之URL

HTTP使用统一资源标识符(Uniform Resource Identifiers, URI)来传输数据和建立连接。URL是一种特殊类型的URI,包含了用于查找某个资源的足够的信息

URL,全称是UniformResourceLocator, 中文叫统一资源定位符,是互联网上用来标识某一处资源的地址。以下面这个URL为例,介绍下普通URL的各部分组成:

http://www.aspxfans.com:8080/news/index.asp?boardID=5&ID=24618&page=1#name

从上面的URL可以看出,一个完整的URL包括以下几部分:

1.协议部分:该URL的协议部分为“http:”,这代表网页使用的是HTTP协议。在Internet中可以使用多种协议,如HTTP,FTP等等本例中使用的是HTTP协议。在"HTTP"后面的“//”为分隔符

2.域名部分:该URL的域名部分为“www.aspxfans.com”。一个URL中,也可以使用IP地址作为域名使用

3.端口部分:跟在域名后面的是端口,域名和端口之间使用“:”作为分隔符。端口不是一个URL必须的部分,如果省略端口部分,将采用默认端口

4.虚拟目录部分:从域名后的第一个“/”开始到最后一个“/”为止,是虚拟目录部分。虚拟目录也不是一个URL必须的部分。本例中的虚拟目录是“/news/”

5.文件名部分:从域名后的最后一个“/”开始到“?”为止,是文件名部分,如果没有“?”,则是从域名后的最后一个“/”开始到“#”为止,是文件部分,如果没有“?”和“#”,那么从域名后的最后一个“/”开始到结束,都是文件名部分。本例中的文件名是“index.asp”。文件名部分也不是一个URL必须的部分,如果省略该部分,则使用默认的文件名

6.锚点部分:从“#”开始到最后,都是锚部分。本例中的锚部分是“name”。锚部分也不是一个URL必须的部分,#代表网页中的一个位置。其右
面的字符,就是该位置的标识符。比如,http://www.example.com/index.html#print就代表网页index.html的print位置。浏览器读取这个
URL后,会自动将print位置滚动至可视区域。为网页位置指定标识符,有两个方法。一是使用锚点,比
如<a name="print"></a>,二是使用id属性,比如<div id="print">。

7.参数部分:从“?”开始到“#”为止之间的部分为参数部分,又称搜索部分、查询部分。本例中的参数部分为“boardID=5&ID=24618&page=1”
。参数可以允许有多个参数,参数与参数之间用“&”作为分隔符。

HTTP之请求消息Request

HTTP之状态码

状态代码有三位数字组成,第一个数字定义了响应的类别,共分五种类别:

1xx:指示信息--表示请求已接收,继续处理

2xx:成功--表示请求已被成功接收、理解、接受

3xx:重定向--要完成请求必须进行更进一步的操作

4xx:客户端错误--请求有语法错误或请求无法实现

5xx:服务器端错误--服务器未能实现合法的请求

常见状态码:

200 OK                        //客户端请求成功
400 Bad Request               //客户端请求有语法错误,不能被服务器所理解
401 Unauthorized              //请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用 
403 Forbidden                 //服务器收到请求,但是拒绝提供服务
404 Not Found                 //请求资源不存在,eg:输入了错误的URL
500 Internal Server Error     //服务器发生不可预期的错误
503 Server Unavailable        //服务器当前不能处理客户端的请求,一段时间后可能恢复正常

HTTP工作原理 HTTP协议定义Web客户端如何从Web服务器请求Web页面,以及服务器如何把Web页面传送给客户端。HTTP协议采用了请求/响应模型。客户端向服务器发送一个请求报文,请求报文包含请求的方法、URL、协议版本、请求头部和请求数据。服务器以一个状态行作为响应,响应的内容包括协议的版本、成功或者错误代码、服务器信息、响应头部和响应数据。

以下是 HTTP 请求/响应的步骤:

1、客户端连接到Web服务器

一个HTTP客户端,通常是浏览器,与Web服务器的HTTP端口(默认为80)建立一个TCP套接字连接。例如,www.oakcms.cn

2、发送HTTP请求

通过TCP套接字,客户端向Web服务器发送一个文本的请求报文,一个请求报文由请求行、请求头部、空行和请求数据4部分组成。

3、服务器接受请求并返回HTTP响应

Web服务器解析请求,定位请求资源。服务器将资源复本写到TCP套接字,由客户端读取。一个响应由状态行、响应头部、空行和响应数据4部分组成。

4、释放连接TCP连接

若connection 模式为close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若connection 模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求;

5、客户端浏览器解析HTML内容

客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码。然后解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符集。客户端浏览器读取响应数据HTML,根据HTML的语法对其进行格式化,并在浏览器窗口中显示。

例如:在浏览器地址栏键入URL,按下回车之后会经历以下流程:

1、浏览器向 DNS 服务器请求解析该 URL 中的域名所对应的 IP 地址;

2、解析出 IP 地址后,根据该 IP 地址和默认端口 80,和服务器建立TCP连接;

3、浏览器发出读取文件(URL 中域名后面部分对应的文件)的HTTP 请求,该请求报文作为 TCP 三次握手的第三个报文的数据发送给服务器;

4、服务器对浏览器请求作出响应,并把对应的 html 文本发送给浏览器;

5、释放 TCP连接;

6、浏览器将该 html 文本并显示内容; &emsp;&emsp;

TCP三次握手

所谓三次握手(Three-Way Handshake)即建立TCP连接,就是指建立一个TCP连接时,需要客户端和服务端总共发送3个包以确认连接的建立。在socket编程中,这一过程由客户端执行connect来触发,整个流程如下图所示:

(1)第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。 (2)第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。 (3)第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。 简单来说,就是 1、建立连接时,客户端发送SYN包(SYN=i)到服务器,并进入到SYN-SEND状态,等待服务器确认 2、服务器收到SYN包,必须确认客户的SYN(ack=i+1),同时自己也发送一个SYN包(SYN=k),即SYN+ACK包,此时服务器进入SYN-RECV状态 3、客户端收到服务器的SYN+ACK包,向服务器发送确认报ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手,客户端与服务器开始传送数据。

四次挥手

所谓四次挥手(Four-Way Wavehand)即终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。在socket编程中,这一过程由客户端或服务端任一方执行close来触发,整个流程如下图所示:

上面是一方主动关闭,另一方被动关闭的情况,实际中还会出现同时发起主动关闭的情况,具体流程如下图:

由于TCP连接时全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭,上图描述的即是如此。

(1)第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。

(2)第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。

(3)第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。

(4)第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。

总结:

(1)三次握手是什么或者流程?四次握手呢?答案前面分析就是。

(2)为什么建立连接是三次握手,而关闭连接却是四次挥手呢?
  这是因为服务端在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。而关闭连接时,当收到对方
  的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,己方也未必全部数据都发送给对方了,所以己方可以立即close,也可以
  发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送。

GET和POST请求的区别

GET请求

GET /books/?sex=man&name=Professional HTTP/1.1
Host: www.wrox.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Connection: Keep-Alive

注意最后一行是空行

POST请求

POST / HTTP/1.1
Host: www.wrox.com
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6)
Gecko/20050225 Firefox/1.0.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 40
Connection: Keep-Alive

name=Professional%20Ajax&publisher=Wiley

1、GET提交,请求的数据会附在URL之后(就是把数据放置在HTTP协议头中),以?分割URL和传输数据,多个参数用&连接;例 如:login.action?name=hyddd&password=idontknow&verify=%E4%BD%A0 %E5%A5%BD。如果数据是英文字母/数字,原样发送,如果是空格,转换为+,如果是中文/其他字符,则直接把字符串用BASE64加密,得出如: %E4%BD%A0%E5%A5%BD,其中%XX中的XX为该符号以16进制表示的ASCII。

POST提交:把提交的数据放置在是HTTP包的包体中。上文示例中红色字体标明的就是实际的传输数据

因此,GET提交的数据会在地址栏中显示出来,而POST提交,地址栏不会改变 2、传输数据的大小:首先声明:HTTP协议没有对传输的数据大小进行限制,HTTP协议规范也没有对URL长度进行限制。

而在实际开发中存在的限制主要有:

GET:特定浏览器和服务器对URL长度有限制,例如 IE对URL长度的限制是2083字节(2K+35)。对于其他浏览器,如Netscape、FireFox等,理论上没有长度限制,其限制取决于操作系 统的支持。

因此对于GET提交时,传输数据就会受到URL长度的 限制。

POST:由于不是通过URL传值,理论上数据不受 限。但实际各个WEB服务器会规定对post提交数据大小进行限制,Apache、IIS6都有各自的配置。

3、安全性

POST的安全性要比GET的安全性高。比如:通过GET提交数据,用户名和密码将明文出现在URL上,因为(1)登录页面有可能被浏览器缓存;(2)其他人查看浏览器的历史纪录,那么别人就可以拿到你的账号和密码了,除此之外,使用GET提交数据还可能会造成Cross-site request forgery攻击

4、Http get,post,soap协议都是在http上运行的

(1)get:请求参数是作为一个key/value对的序列(查询字符串)附加到URL上的 查询字符串的长度受到web浏览器和web服务器的限制(如IE最多支持2048个字符),不适合传输大型数据集同时,它很不安全

(2)post:请求参数是在http标题的一个不同部分(名为entity body)传输的,这一部分用来传输表单信息,因此必须将Content-type设置为:application/x-www-form- urlencoded。post设计用来支持web窗体上的用户字段,其参数也是作为key/value对传输。 但是:它不支持复杂数据类型,因为post没有定义传输数据结构的语义和规则。

(3)soap:是http post的一个专用版本,遵循一种特殊的xml消息格式 Content-type设置为: text/xml 任何数据都可以xml化。

Http协议定义了很多与服务器交互的方法,最基本的有4种,分别是GET,POST,PUT,DELETE. 一个URL地址用于描述一个网络上的资源,而HTTP中的GET, POST, PUT, DELETE就对应着对这个资源的查,改,增,删4个操作。 我们最常见的就是GET和POST了。GET一般用于获取/查询资源信息,而POST一般用于更新资源信息.

我们看看GET和POST的区别

  • GET提交的数据会放在URL之后,以?分割URL和传输数据,参数之间以&相连,如EditPosts.aspx?name=test1&id=123456. POST方法是把提交的数据放在HTTP包的Body中.

  • GET提交的数据大小有限制(因为浏览器对URL的长度有限制),而POST方法提交的数据没有限制.

  • GET方式需要使用Request.QueryString来取得变量的值,而POST方式通过Request.Form来获取变量的值。

  • GET方式提交数据,会带来安全问题,比如一个登录页面,通过GET方式提交数据时,用户名和密码将出现在URL上,如果页面可以被缓存或者其他人可以访问这台机器,就可以从历史记录获得该用户的账号和密码.

HTTP VS HTTPS

HTTP特点:

  • 无状态:协议对客户端没有状态存储,对事物处理没有“记忆”能力,比如访问一个网站需要反复进行登录操作
  • 无连接:HTTP/1.1之前,由于无状态特点,每次请求需要通过TCP三次握手四次挥手,和服务器重新建立连接。比如某个客户机在短时间多次请求同一个资源,服务器并不能区别是否已经响应过用户的请求,所以每次需要重新响应请求,需要耗费不必要的时间和流量。
  • 基于请求和响应:基本的特性,由客户端发起请求,服务端响应
  • 简单快速、灵活
  • 通信使用明文、请求和响应不会对通信方进行确认、无法保护数据的完整性

HTTPS特点:

  • 基于HTTP协议,通过SSL或TLS提供加密处理数据、验证对方身份以及数据完整性保护

  • 通过抓包可以看到数据不是明文传输,而且HTTPS有如下特点:

    • 内容加密:采用混合加密技术,中间者无法直接查看明文内容
    • 验证身份:通过证书认证客户端访问的是自己的服务器
    • 保护数据完整性:防止传输的内容被中间人冒充或者篡改

      混合加密:结合非对称加密和对称加密技术。客户端使用对称加密生成密钥对传输数据进行加密,然后使用非对称加密的公钥再对秘钥进行加密,所以网络上传输的数据是被秘钥加密的密文和用公钥加密后的秘密秘钥,因此即使被HK截取,由于没有私钥,无法获取到加密明文的秘钥,便无法获取到明文数据。

      数字摘要:通过单向hash函数对原文进行哈希,将需加密的明文“摘要”成一串固定长度(如128bit)的密文,不同的明文摘要成的密文其结果总是不相同,同样的明文其摘要必定一致,并且即使知道了摘要也不能反推出明文。

      数字签名技术:数字签名建立在公钥加密体制基础上,是公钥加密技术的另一类应用。它把公钥加密技术和数字摘要结合起来,形成了实用的数字签名技术。

      收方能够证实发送方的真实身份; 发送方事后不能否认所发送过的报文; 收方或非法者不能伪造、篡改报文。

HTTPS实现原理:

安全性考虑:

  • HTTPS协议的加密范围也比较有限,在HK攻击、拒绝服务攻击、服务器劫持等方面几乎起不到什么作用

  • SSL证书的信用链体系并不安全,特别是在某些国家可以控制CA根证书的情况下,中间人攻击一样可行

    中间人攻击(MITM攻击)是指,HK拦截并篡改网络中的通信数据。又分为被动MITM和主动MITM,被动MITM只窃取通信数据而不修改,而主动MITM不但能窃取数据,还会篡改通信数据。最常见的中间人攻击常常发生在公共wifi或者公共路由上。

成本考虑:

  • SSL证书需要购买申请,功能越强大的证书费用越高
  • SSL证书通常需要绑定IP,不能在同一IP上绑定多个域名,IPv4资源不可能支撑这个消耗(SSL有扩展可以部分解决这个问题,但是比较麻烦,而且要求浏览器、操作系统支持,Windows XP就不支持这个扩展,考虑到XP的装机量,这个特性几乎没用)。
  • 根据ACM CoNEXT数据显示,使用HTTPS协议会使页面的加载时间延长近50%,增加10%到20%的耗电。
  • HTTPS连接缓存不如HTTP高效,流量成本高。
  • HTTPS连接服务器端资源占用高很多,支持访客多的网站需要投入更大的成本。
  • HTTPS协议握手阶段比较费时,对网站的响应速度有影响,影响用户体验。比较好的方式是采用分而治之,类似12306网站的主页使用HTTP协议,有关于用户信息等方面使用HTTPS。

HTTPS 协议的主要功能基本都依赖于 TLS/SSL 协议,TLS/SSL 的功能实现主要依赖于三类基本算法:散列函数 、对称加密和非对称加密,其利用非对称加密实现身份认证和密钥协商,对称加密算法采用协商的密钥对数据加密,基于散列函数验证信息的完整性。

应该就是客户端获得证书之后,先对证书进行验证,如果没问题,会产生一个随机数值,客户端用公钥对这个随机值进行加密传递到服务端,服务端用私钥解密获得随机值(密钥),然后之后的数据传输就使用这个新产生的密钥进行对称加密,客户端是有这个随机值(密钥)的,所以可以进行解密