后端服务器安全组规则 后端安全策略

怎么把VUE项目部署到服务器上面

1.使用xshell登录到阿里云服务器。安装nginx(本文安装到/etc下)

创新互联公司专业为企业提供麻阳网站建设、麻阳做网站、麻阳网站设计、麻阳网站制作等企业网站建设、网页设计与制作、麻阳企业网站模板建站服务,10年麻阳做网站经验,不只是建网站,更提供有价值的思路和整体网络服务。

[plain] view plain copy

cd /etc  

apt-get update  

apt-get install nginx  

2.首先先配置nginx,然后再根据配置文件做下一步操作

打开/etc/nginx/nginx.conf文件

[plain] view plain copy

vim /etc/nginx/nginx.conf  

在nginx.conf中配置如下:

[plain] view plain copy

user www-data;  

worker_processes auto;  

pid /run/nginx.pid;  

events {  

worker_connections 768;  

# multi_accept on;  

}  

http {  

##  

# Basic Settings  

##  

tcp_nodelay on;  

keepalive_timeout 65;  

types_hash_max_size 2048;  

# server_tokens off;  

# server_names_hash_bucket_size 64;  

# server_name_in_redirect off;  

include /etc/nginx/mime.types;  

default_type application/octet-stream;  

##  

# SSL Settings  

##  

ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE  

ssl_prefer_server_ciphers on;  

##  

# Logging Settings  

##  

access_log /var/log/nginx/access.log;  

error_log /var/log/nginx/error.log;  

##  

# Gzip Settings  

##  

gzip on;  

gzip_disable "msie6";  

# gzip_vary on;  

# gzip_proxied any;  

# gzip_comp_level 6;  

# gzip_buffers 16 8k;  

# gzip_http_version 1.1;  

##  

# Virtual Host Configs  

##  

gzip on;  

gzip_disable "msie6";  

# gzip_vary on;  

# gzip_proxied any;  

# gzip_comp_level 6;  

# gzip_buffers 16 8k;  

# gzip_http_version 1.1;  

# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;  

##  

# Virtual Host Configs  

##  

include /etc/nginx/conf.d/*.conf;  

include /etc/nginx/sites-enabled/*;  

#以下为我们添加的内容  

server {               

listen 80;  

server_name your-ipaddress;  

root /home/my-project/;  

index index.html;  

location /datas {  

rewrite ^.+datas/?(.*)$ /$1 break;  

include uwsgi_params;  

proxy_pass ;  

}  

}  

}  

接下来就根据配置文件进行下一步工作。配置文件中的server_name后面是阿里云服务器的ip地址

3.配置文件中的listen是nginx监听的端口号,所以需要在阿里云服务器上为80端口添加安全组规则

在本地的浏览器登录阿里云服务器-进入控制台-点击安全组-点击配置规则-点击添加安全组规则,之后配置如下(注:入方向和出方向都要配置)

4.配置文件中的root和index那两行表示我们把项目文件夹放在/home/my-project下

例如有两个项目文件夹分别为test1,test2,里面都有index.html。则目录结构如下

/home

|--my-project

|--test1

|--index.html

|--test2

|--index.html

则在浏览器输入

服务器便会在/home/my-project中找到test1下的index.html执行;

如果在浏览器中输入

服务器便会在/home/my-project中找到test2下的index.html执行;

这样便可以在服务器下放多个项目文件夹。

5.所以我们也需要在本地项目的config/index.js里的build下进行修改,如果要把项目放到test1下,则

[javascript] view plain copy

assetsPublicPath: '/test1/',  

如果用到了vue-router,则修改/router/index.js

[javascript] view plain copy

export default new Router({  

base: '/test1/',   //添加这行  

linkActiveClass: 'active',  

routes  

});  

6.nginx配置文件中的location则是针对跨域处理,表示把对/datas的请求转发给,本文中这个下就是需要的数据,例如,在本地项目文件中ajax请求数据的地方如下

[javascript] view plain copy

const url = '/datas/seller';  

this.$http.get(url).then((response) = {  

.....  

});  

7.修改后在本地命令行下运行:cnpm run build 生成dist文件。把dist文件里的index.html和static文件上传到服务器的/home/my-project/test1下,目录结构如下

/home

|--my-project

|--test1

|--index.html

|--static

8.启动nginx

[plain] view plain copy

service nginx start  

9.至此项目部署成功,在浏览器下输入:    即可

Token是什么?和session、cookie相比,使用场景有什么区别?

在Web开发领域,相信大家对于Cookie和Session都很熟悉,Cookie和Session都是会话保持技术的解决方案。随着技术的发展,Token机制出现在我们面前,不过很多开发者对于Token和Cookie、Session的区别及使用场景分辨不清。

Cookie和Session的用途

要知道我们访问网站都是通过HTTP协议或HTTPS协议来完成的, HTTP协议它本身是无状态的协议 (即:服务器无法分辨哪些请求是来源于同个客户)。而业务层面会涉及到客户端与服务器端的交互(同网站下多个页面间能共享数据),此时服务器端必须要保持会话状态,这样才能进行用户身份的鉴别。

由于HTTP无状态的特性,如果要实话客户端和服务器端的会话保持,那就需要其它机制来实现,于是Cookie和Session应运而生。

通常情况下, Session和Cookie是搭配在一起使用的 。

Token是什么

上面说到的Session和Cookie机制来保持会话,会存在一个问题:客户端浏览器只要保存自己的SessionID即可,而 服务器却要保存所有用户的Session信息,这对于服务器来说开销较大,而且不利用服务器的扩展 (比如服务器集群时,Session如何同步存储就是个问题)!

于是有人思考,如果把Session信息让客户端来保管而且无法伪造不就可以解决这个问题了?进而有了Token机制。

Token俗称为“令牌” ,它的构成是:

Token机制下的认证流程

Token机制其实和Cookie机制极其相似 ,主要有以下流程:

1、用户登录进行身份认证,认证成功后服务器端生成Token返回给客户端;

2、客户端接收到Token后保存在客户端(可保存在Cookie、LocalStorage、SessionStorage中);

3、客户端再次请求服务器端时,将Token作为请求头放入Headers中;

4、服务器端接收请求头中的Token,将用户参数按照既定规则再进行一次签名,两次签名若一致则认为成功,反之数据存在篡改请求失败。

(生成签名示例图)

(验证签名示例图)

Token与Cookie+Session的区别

Cookie其实也充当的是令牌作用,但它是“有状态”的; 而Token令牌是无状态的,更利于分布式部署。

session和cookie

在讲Token之前,先简单说说什么是session和cookie。

Token

但是这里会有个问题, 服务器要保存所有用户的session信息,开销会很大,如果在分布式的架构下,就需要考虑session共享的问题,需要做额外的设计和开发 ,例如把session中的信息保存到Redis中进行共享;所以因为这个原因,有人考虑这些信息是否可以让客户端保存,可以保存到任何地方,并且保证其安全性,于是就有了Token。

Token是服务端生成的一串字符串,可以看做客户端进行请求的一个令牌。

基于Token的认证流程

整体的流程是这样的:

总结 希望我的回答,能够帮助到你!我将持续分享Java开发、架构设计、程序员职业发展等方面的见解,希望能得到你的关注。

Token顾名思义就是令牌、凭证、钥匙 。只有这把钥匙,你才能打开门。token一般都是服务端生成,比如一个web系统,用户登录的时候,服务端校验用户名密码通过以后,会生成一个token,同时会生成refreshToken和一个过期时间。然后将refreshToken和token返回给客户端。客户端会将token保存下来。后续所有的请求都会携带这个token。服务端会判断当前token是否存在已经是否过期。如果token不存在或者过期就会拒绝本次请求。如果token过期怎么办,就用refreshToken刷新时间。当然这里可能还有别的方案。比如只生成token,每次请求的时候都刷新过期时间。如果长时间没有刷新过期时间,那token就会过期。

session就是回话,这是服务端的一种操作。当你第一次访问一个web网站的时候,服务端会生成一个session,并有一个sessionid和他对应。这个session是存储到内存中的,你可以向这个session中写入信息,比如当前登录用户的信息。sessionid会被返回到客户端,客户端一般采用cookie来保存。当然这个cookie不用人为写入。用tomcat容器来举个例子。 当后端调用HttpServletRequest对象的getSession的方法的时候,tomcat内部会生成一个jsessonid(tomcat sessionid的叫法)。这个jsessonid会随本次请求返回给客户端。响应头信息

这个jessionid就会写到cookie中。之后jessionid就会通过cookie传递到服务端。

这里我们就会很清楚了, session的数据是存储到内存中。那问题就来了,如果我们的服务是分布式部署,有多台机器的话,可能我们第一次登陆的时候,我们把用户的信息存储到了session,但是后面的请求到了B机器上,那B机器是获取不到用户的session的。另外就是session存储在内存中,那服务器重启,session就丢失了,这就是他的弊端。现在有一些技术,例如session共享、iphash、session持久等也可以解决上述问题 。

cookie是浏览器的一种策略。上述讲到了sessionid就是存储在cookie中的。我们知道http协议是无状态的,cookie就是用来解决这个问题的。cookie中可以用来保存服务端返回的一些用户信息的,例如前文提到的token、sessionid。每一次的请求,都会携带这些cookie。服务端从请求头中取到cookie中的信息,就可以识别本次请求的来源,这样,http是不是就变成有状态的了。

这里说几点cookie注意事项。

1、cookie存放在客户端,所以是不安全的。人为可以清除

2、cookie有过期时间设定。如果不设置过期时间,说明这个cookie就是当前浏览器的会话时间,浏览器关了,cookie 就存在了。如果有过期时间,cookie就会存储到硬盘上,浏览器关闭不影响cookie。下次打开浏览器,cookie还存在

3、cookie有大小的限制,4KB。

这个问题,网上有很多的答案,相信都看过了,估计也没有看明白。所以我就不去网上复制了,用自己的话,尽量说通俗,说重点。

cookie和session实际上是同一套认证流程,相辅相成。session保存在服务器,cookie保存在客户端。最常见的做法就是客户端的cookie仅仅保存一个sessionID,这个sessionID是一个毫无规则的随机数,由服务器在客户端登录通过后随机生产的。往后,客户端每次访问该网站都要带上这个由sessionID组成的cookie。服务器收到请求,首先拿到客户端的sessionID,然后从服务器内存中查询它所代表的客户端(用户名,用户组,有哪些权限等)。

与token相比,这里的重点是,服务器必须保存sessionID以及该ID所代表的客户端信息。这些内容可以保存在内存,也可以保存到数据库(通常是内存数据库)。

而token则可以服务器完全不用保存任何登录信息。

token的流程是这样的。客户端登录通过后,服务器生成一堆客户端身份信息,包括用户名、用户组、有那些权限、过期时间等等。另外再对这些信息进行签名。之后把身份信息和签名作为一个整体传给客户端。这个整体就叫做token。之后,客户端负责保存该token,而服务器不再保存。客户端每次访问该网站都要带上这个token。服务器收到请求后,把它分割成身份信息和签名,然后验证签名,若验证成功,就直接使用身份信息(用户名、用户组、有哪些权限等等)。

可以看出,相对于cookie/session机制,token机制中,服务器根本不需要保存用户的身份信息(用户名、用户组、权限等等)。这样就减轻了服务器的负担。

我们举个例来说,假如目前有一千万个用户登录了,在访问不同的网页。如果用cookie/session,则服务器内存(或内存数据库)中要同时记录1千万个用户的信息。每次客户端访问一个页面,服务器都要从内存中查询出他的登录信息。而如果用token,则服务器内存中不记录用户登录信息。它只需要在收到请求后,直接使用客户端发过来的登录身份信息。

可以这么说, cookie/session是服务器说客户端是谁,客户端才是谁。而token是客户端说我(客户端)是谁,我就是谁 。当然了,token是有签名机制的。要是客户端伪造身份,签名通不过。这个签名算法很简单,就是将客户端的身份信息加上一个只有服务器知道的盐值(不能泄露),然后进行md5散列算法(这里只是简化,方便理解,实际细节要稍复杂一些)。

cookie/session在单服务器,单域名时比较简单,否则的话,就要考虑如何将客户端的session保存或同步到多个服务器。还要考虑一旦宕机,内存中的这些信息是否会丢失。token因为服务器不保存用户身份,就不存在这个问题。这是token的优点。

token因为服务器不保存用户身份信息,一切都依赖当初那个签名。所以存在被盗用的风险。也就是说一旦盗用,服务器可能毫无办法,因为它只认签名算法。而session机制,服务器看谁不爽,可以随时把他踢出(从内存中删掉)。正是因为如此,token高度依赖过期时间。过期时间不能太长。过期短,可以减少被盗用的风险。

除了上面所说的,我个人认为,如果开发的系统足够小,倾向于使用cookie/session。如果系统同时登录用户多,集群服务器多,有单点登录需求,则倾向于使用token。

万维网的发展 历史

Token, 令牌,代表执行某些操作的权利的对象。

token主要用于鉴权使用,主要有以下几类:

cookie主要是网站用于在浏览器临时存放的数据,包括浏览器缓存数据以及服务器设定的一些数据,主要存放在浏览器端。

session主要用于保存会话数据,一般存储在服务器端,同时每一条session对用一个sessionID,sessionID是存放在浏览器的cookie中。

传统上的会话登陆和鉴权主要用session加cookie实现,随着分布式系统的快速演进,尤其是微服务的应用,token+cookie的授权访问机制得到亲睐,通常在用户登录后,服务器生成访问令牌(Access token),浏览器存储cookie中,在每次请求资源时都会在请求头中带上token,用于服务器授权访问使用。

Token和session都是web网站的会话保持、认证的解决方案;

既然都一样为什么还有token的说法。

从token产生的背景说起

1.移动端应用使得服务器端Session失效

2.分布式系统中Session无法共享

所以说session对于以上两种情况无效了,所以有了Token的说法

那么什么是token,token长什么样子?

先给大家一个直观的感受

token:PC-3066014fa0b10792e4a762-23-20170531133947-4f6496

说白了token保存就是用户的信息(不能保存密码等敏感信息)

token的组成:

客户端标识-USERCODE-USERID-CREATIONDATE-RONDEM[6位]

USERCODE,RONDEM[6位]经过MD5加密就变成了以上字符串

token的请求流程

请求流程解析

1.前端用户发送登录信息至认证系统

2.验证用户登录信息,判断用户是否存在

3.如果用户存在,生成token信息(客户端标识-USERCODE-USERID-CREATIONDATE-RONDEM[6位]),并存储在redis中

4.并将该token返回前端,附加至header

验证token

客户端

将token附加至header

服务端

最后总结一下

一般的垂直架构项目使用Session没有任何问题,但是分布式项目或涉及到移动端则考虑使用token。

session

session的中文翻译是“会话”,当用户打开某个web应用时,便与web服务器产生一次session。服务器使用session把用户的信息临时保存在了服务器上,用户离开网站后session会被销毁。这种用户信息存储方式相对cookie来说更安全,可是session有一个缺陷:如果web服务器做了负载均衡,那么下一个操作请求到了另一台服务器的时候session会丢失。

cookie

cookie是保存在本地终端的数据。cookie由服务器生成,发送给浏览器,浏览器把cookie以kv形式保存到某个目录下的文本文件内,下一次请求同一网站时会把该cookie发送给服务器。由于cookie是存在客户端上的,所以浏览器加入了一些限制确保cookie不会被恶意使用,同时不会占据太多磁盘空间,所以每个域的cookie数量是有限的。

cookie的组成有:名称(key)、值(value)、有效域(domain)、路径(域的路径,一般设置为全局:"")、失效时间、安全标志(指定后,cookie只有在使用SSL连接时才发送到服务器(https))。下面是一个简单的js使用cookie的例子:

用户登录时产生cookie:

document.cookie = "id="+result.data['id']+"; path=/";

document.cookie = "name="+result.data['name']+"; path=/";

document.cookie = "avatar="+result.data['avatar']+"; path=/";

使用到cookie时做如下解析:

var cookie = document.cookie;var cookieArr = cookie.split(";");var user_info = {};for(var i = 0; i cookieArr.length; i++) {

user_info[cookieArr[i].split("=")[0]] = cookieArr[i].split("=")[1];

}

$('#user_name').text(user_info[' name']);

$('#user_avatar').attr("src", user_info[' avatar']);

$('#user_id').val(user_info[' id']);

token

token的意思是“令牌”,是用户身份的验证方式,最简单的token组成:uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,由token的前几位+盐以哈希算法压缩成一定长的十六进制字符串,可以防止恶意第三方拼接token请求服务器)。还可以把不变的参数也放进token,避免多次查库

cookie 和session的区别

1、cookie数据存放在客户的浏览器上,session数据放在服务器上。

2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗

考虑到安全应当使用session。

3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能

考虑到减轻服务器性能方面,应当使用COOKIE。

4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。

5、所以个人建议:

将登陆信息等重要信息存放为SESSION

其他信息如果需要保留,可以放在COOKIE中

token 和session 的区别

session 和 oauth token并不矛盾,作为身份认证 token安全性比session好,因为每个请求都有签名还能防止监听以及重放攻击,而session就必须靠链路层来保障通讯安全了。如上所说,如果你需要实现有状态的会话,仍然可以增加session来在服务器端保存一些状态

App通常用restful api跟server打交道。Rest是stateless的,也就是app不需要像browser那样用cookie来保存session,因此用session token来标示自己就够了,session/state由api server的逻辑处理。 如果你的后端不是stateless的rest api, 那么你可能需要在app里保存session.可以在app里嵌入webkit,用一个隐藏的browser来管理cookie session.

Session 是一种HTTP存储机制,目的是为无状态的HTTP提供的持久机制。所谓Session 认证只是简单的把User 信息存储到Session 里,因为SID 的不可预测性,暂且认为是安全的。这是一种认证手段。 而Token ,如果指的是OAuth Token 或类似的机制的话,提供的是 认证 和 授权 ,认证是针对用户,授权是针对App 。其目的是让 某App有权利访问 某用户 的信息。这里的 Token是唯一的。不可以转移到其它 App上,也不可以转到其它 用户 上。 转过来说Session 。Session只提供一种简单的认证,即有此 SID,即认为有此 User的全部权利。是需要严格保密的,这个数据应该只保存在站方,不应该共享给其它网站或者第三方App。 所以简单来说,如果你的用户数据可能需要和第三方共享,或者允许第三方调用 API 接口,用 Token 。如果永远只是自己的网站,自己的 App,用什么就无所谓了。

token就是令牌,比如你授权(登录)一个程序时,他就是个依据,判断你是否已经授权该软件;cookie就是写在客户端的一个txt文件,里面包括你登录信息之类的,这样你下次在登录某个网站,就会自动调用cookie自动登录用户名;session和cookie差不多,只是session是写在服务器端的文件,也需要在客户端写入cookie文件,但是文件里是你的浏览器编号.Session的状态是存储在服务器端,客户端只有session id;而Token的状态是存储在客户端。

 

想要全面深入地掌握Token,我们需要先了解这些:Token的概念、身份验证过程、实现思路、使用场景,以及Cookie、Session、Token的区别。

内容纲要

Token的定义

Token是验证用户身份的一种方式,简称做“令牌”。最简单的token组成:uid(用户唯一的身份标识)、time(当前时间的时间戳)、sign(签名,由token的前几位+盐,以哈希算法压缩成一定长的十六进制字符串,可以防止恶意第三方拼接token请求服务器)。还可以把不变的参数也放进token,避免多次查库。

Token的身份验证过程

每一次请求都需要Token,Token应该在HTTP的头部发送,从而保证Http请求无状态。我们同样通过设置服务器属性Access-Control-Allow-Origin:* ,让服务器能接受到来自所有域的请求。

需要注意的是,在ACAO头部标明(designating)*时,不得带有像HTTP认证,客户端SSL证书和cookies的证书。

Token的实现思路

当我们在程序中认证了信息,并取得Token之后,我们便能通过这个Token做许多的事情。我们甚至能基于创建一个基于权限的token传给第三方应用程序,这些第三方程序能够获取到我们的数据(当然只有在我们允许的特定的token)。

Token的应用场景

Cookie和Session的区别

综合以上考量,建议方案:

Session和Cookie取长补短、配合使用,将登陆信息等重要信息存放为Session,其他信息如果需要保留,可以放在Cookie中。

Token 和 Session 的区别

Session和Token并不矛盾,作为身份认证,Token安全性比Session高,因为Token发送的每个请求都带有签名,能防止监听,以及重放攻击。而session就必须靠链路层来保障通讯安全。如上所说,如果需要实现有状态的会话,可以通过增加session,在服务器端保存一些状态。

App通常用Restful API跟server打交道。Rest是Stateless的,也就是App不需要像Browser那样用Cookie来保存Session,因此使用Session Token来标示就足够了。Session/state由API Server的逻辑处理。如果后端不是Stateless的rest API,那么可能需要在App里保存Session,可以在App里嵌入webkit,用一个隐藏的Browser来管理Cookie Session.

Session是一种HTTP存储机制,目的是为无状态的HTTP提供持久机制。 所谓的Session认证,只是简单的把User信息存储到Session里,因为SID的不可预测性,暂且认为是安全的,这是一种认证手段。

Session只提供一种简单的认证,即有此SID,以及User的全部权利。是需要严格保密的,这个数据只在使用站点保存,不可共享给其它网站或者第三方App。所以简单来说,如果你的用户数据可能需要和第三方共享,或者允许第三方调用API接口,则使用Token,如果只是自己的网站或App应用,使用什么都OK。

Token,指的是OAuth Token或类似的机制的话,提供的是认证和授权 ,认证是针对用户,授权是针对App。其目的是让某App有权利访问某用户的信息,这里的Token是唯一的,不可以转移到其它App上,也不可以转到其它用户上。

Token就是令牌,比如你授权(登录)一个程序时,他就是个依据,判断你是否已经授权该软件。Cookie就是写在客户端的一个txt文件,记录下用户的访问、登录等信息,下次用户再登录某个网站时,服务器接收到请求,就会自动调用Cookie,自动登录用户名。

Session和Cookie差不多,只是Session是写在服务器端的文件,也需要在客户端写入Cookie文件,但是文件里是用户的浏览器编号.Session的状态是存储在服务器端,客户端只有session id,而Token的状态是存储在客户端的。

以上,是关于Token、Session、Cookie的知识点介绍,更加深入的详解,感兴趣的童鞋,可查看我持续分享的【BAT架构技术专题合集500+】,回复【架构】,即可领取。

Token是什么?

Token是令牌、凭证、钥匙,在Web领域中进行 身份验证 ,关键点在验证!!,说验证就必须了解一下Web领域的发展史呢。

2. 随着人们需求的改变,比如在线购物系统,需要登陆的网站等,这时候需要进行 交互 性,服务器接收到请求的时候,要根据你是否登陆,以及判断你是谁,来给你响应,这时候问题就来了,怎么知道每次请求的谁呢,所以就出来了一个 会话标识(session id),就是一个随机的字符串 ,每个人登陆的时候,服务器都会返回一个会话标识,这是再请求的时候,只要带上会话标识,服务器就知道请求的是谁。

3. 这样子每个人只要保存自己的session id就可以啦,服务器要保存 所有人 的session id!!!如果有成千上万的人访问服务器,那对服务器是巨大的开销,严重限制了服务器端的扩展能力,比如机器A跟机器B组成了服务器集群,那么访问了机器A,会话标识在机器A上,如果转到机器B,就不能访问了,也许会说,那复制呢,机器A搬到机器B,也有说统一把标识放在一个机器上,但是万一这个机器挂了呢,那体验就很差了。

4. 这个时候就有人想,用户自己保存自己的标识,就是Token,访问的时候带上这个Token,这个 Token是用户id+签名 ,验证时,服务器只要相同的算法和服务器才知道的密钥进行签名,如果结果跟Token中的签名一样,那就可以证明是登陆过的用户。

这样一来,服务器不保存session id,只要生成Token,访问时,只要对Token进行判断,Token也是有有效期的,所以也要进行refreshToken的。

Token,Cookie,Session三者使用场景的区别?

Token主要是Web领域的身份认证 ,最常见的就是Web API这个功能:

Cookie 就是饼干, 它是服务器生产,永久保存在浏览器的数据,以kv的形式 ,你可以打开你的浏览器(这里以win10 edge为例),点击上方的三个点的按钮,再点击更多工具,再点击开发人员工具,再点击网络,此时内容选择文档,然后刷新页面,找Cookie即可。

Session是会话标识,是服务器用来判断正在会话的用户是谁,服务器生产的随机数 ,保存在服务器中,用户端也要进行保存,虽然能实现会话的共能,但对服务器的扩展能力限制,同时当服务器是两台机器组成以上的时候,会导致两台机器以上保存的session同步问题,会导致用户体验极差。

Token跟Session最大的区别就是Token服务端不用保存,同时是通过签名等技术实现的,Session因为是随机数,导致服务器要进行保存。

后端开发都需要那些技术?

后端主要是让服务器、应用、数据库能够彼此交互,需要考虑如何实现功能、数据的存取、平台的稳定性与性能等。常用的脚本语言有php、 java 、 python、C、C++等,以java为例主要用到的技术包括但不限于Struts、spring、springmvc 、Hibernate、Http协议、Servlet、Tomcat服务器等

第一,Servlet技术。Servlet技术是Java后端的重要技术之一,作为Java Web开发的核心组件,Servlet承担了Web MVC结构中的核心作用(功能导航)。传统的Model2结构(Servlet+JavaBean+JSP)虽然在目前已经很少使用了,但是Web开发的基本结构依然没有改变。Servlet技术的应用涉及到Web容器、会话(HttpSession)、安全、同步、Web应用部署等相关内容。

第二,Java操作数据库。后端开发免不了与数据库打交道,所以掌握Java的数据库操作是一个基本要求。Java操作数据库涉及到的内容有JDBC、JNDI、RMI、DAO等内容,其中使用RMI+JDBC是构建java数据库开发的一个常见的解决方案,而JNDI则是对各种资源的定义。

第三,Spring框架。Spring+SpringMVC+MyBatis是目前一个比较常见的后端开发方案,Spring的原理就是构建了一个“业务组件容器”,SpringMVC则是Web MVC的一个具体实现框架,而MyBatis则是一个基于DAO的实现框架。从性能的角度来说,Spring是EJB的轻量级解决方案,得到了广大Java程序员的欢迎。如果有Servlet以及数据库操作的基础,那么学习这几个框架的使用是一件非常轻松的过程。虽然基于Spring的编程比较方便,但是Spring也有缺点,比如配置文件过于繁琐。

第四,结合hadoop构建Java的分布式开发。Java的分布式开发是提高Java后端处理能力的重要内容,RMI是Java分布式开发比较常见的解决方案,学习起来也比较简单

IPVS从入门到精通kube-proxy实现原理

我们知道容器的特点是快速创建、快速销毁,Kubernetes Pod和容器一样只具有临时的生命周期,一个Pod随时有可能被终止或者漂移,随着集群的状态变化而变化,一旦Pod变化,则该Pod提供的服务也就无法访问,如果直接访问Pod则无法实现服务的连续性和高可用性,因此显然不能使用Pod地址作为服务暴露端口。

解决这个问题的办法和传统数据中心解决无状态服务高可用的思路完全一样,通过负载均衡和VIP实现后端真实服务的自动转发、故障转移。

这个负载均衡在Kubernetes中称为Service,VIP即Service ClusterIP,因此可以认为Kubernetes的Service就是一个四层负载均衡,Kubernetes对应的还有七层负载均衡Ingress,本文仅介绍Kubernetes Service。

这个Service就是由kube-proxy实现的,ClusterIP不会因为Podz状态改变而变,需要注意的是VIP即ClusterIP是个假的IP,这个IP在整个集群中根本不存在,当然也就无法通过IP协议栈无法路由,底层underlay设备更无法感知这个IP的存在,因此ClusterIP只能是单主机(Host Only)作用域可见,这个IP在其他节点以及集群外均无法访问。

Kubernetes为了实现在集群所有的节点都能够访问Service,kube-proxy默认会在所有的Node节点都创建这个VIP并且实现负载,所以在部署Kubernetes后发现kube-proxy是一个DaemonSet。

而Service负载之所以能够在Node节点上实现是因为无论Kubernetes使用哪个网络模型,均需要保证满足如下三个条件:

至少第2点是必须满足的,有了如上几个假设,Kubernetes Service才能在Node上实现,否则Node不通Pod IP也就实现不了了。

有人说既然kube-proxy是四层负载均衡,那kube-proxy应该可以使用haproxy、nginx等作为负载后端啊?

事实上确实没有问题,不过唯一需要考虑的就是性能问题,如上这些负载均衡功能都强大,但毕竟还是基于用户态转发或者反向代理实现的,性能必然不如在内核态直接转发处理好。

因此kube-proxy默认会优先选择基于内核态的负载作为后端实现机制,目前kube-proxy默认是通过iptables实现负载的,在此之前还有一种称为userspace模式,其实也是基于iptables实现,可以认为当前的iptables模式是对之前userspace模式的优化。

本节接下来将详细介绍kube-proxy iptables模式的实现原理。

首先创建了一个ClusterIP类型的Service:

其中ClusterIP为10.106.224.41,我们可以验证这个IP在本地是不存在的:

所以 不要尝试去ping ClusterIP,它不可能通的 。

此时在Node节点192.168.193.172上访问该Service服务,首先流量到达的是OUTPUT链,这里我们只关心nat表的OUTPUT链:

该链跳转到 KUBE-SERVICES 子链中:

我们发现与之相关的有两条规则:

其中 KUBE-SVC-RPP7DHNHMGOIIFDC 子链规则如下:

这几条规则看起来复杂,其实实现的功能很简单:

我们查看其中一个子链 KUBE-SEP-FTIQ6MSD3LWO5HZX 规则:

可见这条规则的目的是做了一次DNAT,DNAT目标为其中一个Endpoint,即Pod服务。

由此可见子链 KUBE-SVC-RPP7DHNHMGOIIFDC 的功能就是按照概率均等的原则DNAT到其中一个Endpoint IP,即Pod IP,假设为10.244.1.2,

此时相当于:

接着来到POSTROUTING链:

这两条规则只做一件事就是只要标记了 0x4000/0x4000 的包就一律做MASQUERADE(SNAT),由于10.244.1.2默认是从flannel.1转发出去的,因此会把源IP改为flannel.1的IP 10.244.0.0 。

剩下的就是常规的走Vxlan隧道转发流程了,这里不再赘述,感兴趣的可以参考我之前的文章 浅聊几种主流Docker网络的实现原理 。

接下来研究下NodePort过程,首先创建如下Service:

其中Service的NodePort端口为30419。

假设有一个外部IP 192.168.193.197,通过 192.168.193.172:30419 访问服务。

首先到达PREROUTING链:

PREROUTING的规则非常简单,凡是发给自己的包,则交给子链 KUBE-NODEPORTS 处理。注意前面省略了判断ClusterIP的部分规则。

KUBE-NODEPORTS 规则如下:

这个规则首先给包打上标记 0x4000/0x4000 ,然后交给子链 KUBE-SVC-RPP7DHNHMGOIIFDC 处理, KUBE-SVC-RPP7DHNHMGOIIFDC 刚刚已经见面过了,其功能就是按照概率均等的原则DNAT到其中一个Endpoint IP,即Pod IP,假设为10.244.1.2。

此时发现10.244.1.2不是自己的IP,于是经过路由判断目标为10.244.1.2需要从flannel.1发出去。

接着到了 FORWARD 链,

FORWARD表在这里只是判断下,只允许打了标记 0x4000/0x4000 的包才允许转发。

最后来到 POSTROUTING 链,这里和ClusterIP就完全一样了,在 KUBE-POSTROUTING 中做一次 MASQUERADE (SNAT),最后结果:

我们发现基于iptables模式的kube-proxy ClusterIP和NodePort都是基于iptables规则实现的,我们至少发现存在如下几个问题:

本文接下来将介绍kube-proxy的ipvs实现,由于本人之前也是对ipvs很陌生,没有用过,专门学习了下ipvs,因此在第二章简易介绍了下ipvs,如果已经很熟悉ipvs了,可以直接跳过,这一章和Kubernetes几乎没有任何关系。

另外由于本人对ipvs也是初学,水平有限,难免出错,欢迎指正!

我们接触比较多的是应用层负载均衡,比如haproxy、nginx、F5等,这些负载均衡工作在用户态,因此会有对应的进程和监听socket,一般能同时支持4层负载和7层负载,使用起来也比较方便。

LVS是国内章文嵩博士开发并贡献给社区的( 章文嵩博士和他背后的负载均衡帝国 ),主要由ipvs和ipvsadm组成,ipvs是工作在内核态的4层负载均衡,和iptables一样都是基于内核底层netfilter实现,netfilter主要通过各个链的钩子实现包处理和转发。ipvsadm和ipvs的关系,就好比netfilter和iptables的关系,它运行在用户态,提供简单的CLI接口进行ipvs配置。

由于ipvs工作在内核态,直接基于内核处理包转发,所以最大的特点就是性能非常好。又由于它工作在4层,因此不会处理应用层数据,经常有人问ipvs能不能做SSL证书卸载、或者修改HTTP头部数据,显然这些都不可能做的。

我们知道应用层负载均衡大多数都是基于反向代理实现负载的,工作在应用层,当用户的包到达负载均衡监听器listening后,基于一定的算法从后端服务列表中选择其中一个后端服务进行转发。当然中间可能还会有一些额外操作,最常见的如SSL证书卸载。

而ipvs工作在内核态,只处理四层协议,因此只能基于路由或者NAT进行数据转发,可以把ipvs当作一个特殊的路由器网关,这个网关可以根据一定的算法自动选择下一跳,或者把ipvs当作一个多重DNAT,按照一定的算法把ip包的目标地址DNAT到其中真实服务的目标IP。针对如上两种情况分别对应ipvs的两种模式–网关模式和NAT模式,另外ipip模式则是对网关模式的扩展,本文下面会针对这几种模式的实现原理进行详细介绍。

ipvsadm命令行用法和iptables命令行用法非常相似,毕竟是兄弟,比如 -L 列举, -A 添加, -D 删除。

但是其实ipvsadm相对iptables命令简直太简单了,因为没有像iptables那样存在各种table,table嵌套各种链,链里串着一堆规则,ipvsadm就只有两个核心实体,分别为service和server,service就是一个负载均衡实例,而server就是后端member,ipvs术语中叫做real server,简称RS。

如下命令创建一个service实例 172.17.0.1:32016 , -t 指定监听的为 TCP 端口, -s 指定算法为轮询算法rr(Round Robin),ipvs支持简单轮询(rr)、加权轮询(wrr)、最少连接(lc)、源地址或者目标地址散列(sh、dh)等10种调度算法。

然后把10.244.1.2:8080、10.244.1.3:8080、10.244.3.2:8080添加到service后端member中。

其中 -t 指定service实例, -r 指定server地址, -w 指定权值, -m 即前面说的转发模式,其中 -m 表示为 masquerading ,即NAT模式, -g 为 gatewaying ,即直连路由模式, -i 为 ipip ,ji即IPIP隧道模式。

与iptables-save、iptables-restore对应的工具ipvs也有ipvsadm-save、ipvsadm-restore。

NAT模式由字面意思理解就是通过NAT实现的,但究竟是如何NAT转发的,我们通过实验环境验证下。

现环境中LB节点IP为192.168.193.197,三个RS节点如下:

为了模拟LB节点IP和RS不在同一个网络的情况,在LB节点中添加一个虚拟IP地址:

创建负载均衡Service并把RS添加到Service中:

这里需要注意的是,和应用层负载均衡如haproxy、nginx不一样的是,haproxy、nginx进程是运行在用户态,因此会创建socket,本地会监听端口,而 ipvs的负载是直接运行在内核态的,因此不会出现监听端口 :

可见并没有监听10.222.0.1:8080 Socket 。

Client节点IP为192.168.193.226,为了和LB节点的虚拟IP 10.222.0.1通,我们手动添加静态路由如下:

此时Client节点能够ping通LB节点VIP:

可见Client节点到VIP的链路没有问题,那是否能够访问我们的Service呢?

我们验证下:

非常意外的结果是并不通。

在RS节点抓包如下:

我们发现数据包的源IP为Client IP,目标IP为RS IP,换句话说,LB节点IPVS只做了DNAT,把目标IP改成RS IP了,而没有修改源IP。此时虽然RS和Client在同一个子网,链路连通性没有问题,但是由于Client节点发出去的包的目标IP和收到的包源IP不一致,因此会被直接丢弃,相当于给张三发信,李四回的信,显然不受信任。

既然IPVS没有给我们做SNAT,那自然想到的是我们手动做SNAT,在LB节点添加如下iptables规则:

再次检查Service是否可以访问:

服务依然不通。并且在LB节点的iptables日志为空:

也就是说,ipvs的包根本不会经过iptables nat表POSTROUTING链?

那mangle表呢?我们打开LOG查看下:

此时查看日志如下:

我们发现在mangle表中可以看到DNAT后的包。

只是可惜mangle表的POSTROUTING并不支持NAT功能:

对比Kubernetes配置发现需要设置如下系统参数:

再次验证:

终于通了,查看RS抓包:

如期望,修改了源IP为LB IP。

原来需要配置 net.ipv4.vs.conntrack=1 参数,这个问题折腾了一个晚上,不得不说目前ipvs的文档都太老了。

前面是通过手动iptables实现SNAT的,性能可能会有损耗,于是如下开源项目通过修改lvs直接做SNAT:

除了SNAT的办法,是否还有其他办法呢?想想我们最初的问题,Client节点发出去的包的目标IP和收到的包源IP不一致导致包被丢弃,那解决问题的办法就是把包重新引到LB节点上,只需要在所有的RS节点增加如下路由即可:

此时我们再次检查我们的Service是否可连接:

结果没有问题。

不过我们是通过手动添加Client IP到所有RS的明细路由实现的,如果Client不固定,这种方案仍然不太可行,所以通常做法是干脆把所有RS默认路由指向LB节点,即把LB节点当作所有RS的默认网关。

由此可知,用户通过LB地址访问服务,LB节点IPVS会把用户的目标IP由LB IP改为RS IP,源IP不变,包不经过iptables的OUTPUT直接到达POSTROUTING转发出去,包回来的时候也必须先到LB节点,LB节点把目标IP再改成用户的源IP,最后转发给用户。

显然这种模式来回都需要经过LB节点,因此又称为双臂模式。

网关模式(Gatewaying)又称为直连路由模式(Direct Routing)、透传模式, 所谓透传即LB节点不会修改数据包的源IP、端口以及目标IP、端口 ,LB节点做的仅仅是路由转发出去,可以把LB节点看作一个特殊的路由器网关,而RS节点则是网关的下一跳,这就相当于对于同一个目标地址,会有多个下一跳,这个路由器网关的特殊之处在于能够根据一定的算法选择其中一个RS作为下一跳,达到负载均衡和冗余的效果。

既然是通过直连路由的方式转发,那显然LB节点必须与所有的RS节点在同一个子网,不能跨子网,否则路由不可达。换句话说, 这种模式只支持内部负载均衡(Internal LoadBalancer) 。

另外如前面所述,LB节点不会修改源端口和目标端口,因此这种模式也无法支持端口映射,换句话说 LB节点监听的端口和所有RS节点监听的端口必须一致 。

现在假设有LB节点IP为 192.168.193.197 ,有三个RS节点如下:

创建负载均衡Service并把RS添加到Service中:

注意到我们的Service监听的端口30620和RS的端口是一样的,并且通过 -g 参数指定为直连路由模式(网关模式)。

Client节点IP为192.168.193.226,我们验证Service是否可连接:

我们发现并不通,在其中一个RS节点192.168.193.172上抓包:

正如前面所说,LB是通过路由转发的,根据路由的原理,源MAC地址修改为LB的MAC地址,而目标MAC地址修改为RS MAC地址,相当于RS是LB的下一跳。

并且源IP和目标IP都不会修改。问题就来了,我们Client期望访问的是RS,但RS收到的目标IP却是LB的IP,发现这个目标IP并不是自己的IP,因此不会通过INPUT链转发到用户空间,这时要不直接丢弃这个包,要不根据路由再次转发到其他地方,总之两种情况都不是我们期望的结果。

那怎么办呢?为了让RS接收这个包,必须得让RS有这个目标IP才行。于是不妨在lo上添加个虚拟IP,IP地址伪装成LB IP 192.168.193.197:

问题又来了,这就相当于有两个相同的IP,IP重复了怎么办?办法是隐藏这个虚拟网卡,不让它回复ARP,其他主机的neigh也就不可能知道有这么个网卡的存在了,参考 Using arp announce/arp ignore to disable ARP 。

此时再次从客户端curl:

终于通了。

我们从前面的抓包中知道,源IP为Client IP 192.168.193.226,因此直接回包给Client即可,不可能也不需要再回到LB节点了,即A-B,B-C,C-A,流量方向是三角形状的,因此这种模式又称为三角模式。

我们从原理中不难得出如下结论:

前面介绍了网关直连路由模式,要求所有的节点在同一个子网,而ipip隧道模式则主要解决这种限制,LB节点IP和RS可以不在同一个子网,此时需要通过ipip隧道进行传输。

现在假设有LB节点IP为 192.168.193.77/25 ,在该节点上增加一个VIP地址:

ip addr add 192.168.193.48/25 dev eth0

有三个RS节点如下:

如上三个RS节点子网掩码均为255.255.255.128,即25位子网,显然和VIP 192.168.193.48/25不在同一个子网。

创建负载均衡Service并把RS添加到Service中:

注意到我们的Service监听的端口30620和RS的端口是一样的,并且通过 -i 参数指定为ipip隧道模式。

在所有的RS节点上加载ipip模块以及添加VIP(和直连路由类型):

Client节点IP为192.168.193.226/25,我们验证Service是否可连接:

Service可访问,我们在RS节点上抓包如下:

我们发现和直连路由一样,源IP和目标IP没有修改。

所以IPIP模式和网关(Gatewaying)模式原理基本一样,唯一不同的是网关(Gatewaying)模式要求所有的RS节点和LB节点在同一个子网,而IPIP模式则可以支持跨子网的情况,为了解决跨子网通信问题,使用了ipip隧道进行数据传输。

ipvs是一个内核态的四层负载均衡,支持NAT、Gateway以及IPIP隧道模式,Gateway模式性能最好,但LB和RS不能跨子网,IPIP性能次之,通过ipip隧道解决跨网段传输问题,因此能够支持跨子网。而NAT模式没有限制,这也是唯一一种支持端口映射的模式。

我们不难猜想,由于Kubernetes Service需要使用端口映射功能,因此kube-proxy必然只能使用ipvs的NAT模式。

使用kubeadm安装Kubernetes可参考文档 Cluster Created by Kubeadm ,不过这个文档的安装配置有问题 kubeadm #1182 ,如下官方配置不生效:

需要修改为如下配置:

可以通过如下命令确认kube-proxy是否修改为ipvs:

创建一个ClusterIP类似的Service如下:

ClusterIP 10.96.54.11为我们查看ipvs配置如下:

可见ipvs的LB IP为ClusterIP,算法为rr,RS为Pod的IP。

另外我们发现使用的模式为NAT模式,这是显然的,因为除了NAT模式支持端口映射,其他两种均不支持端口映射,所以必须选择NAT模式。

由前面的理论知识,ipvs的VIP必须在本地存在,我们可以验证:

可见kube-proxy首先会创建一个dummy虚拟网卡kube-ipvs0,然后把所有的Service IP添加到kube-ipvs0中。

我们知道基于iptables的Service,ClusterIP是一个虚拟的IP,因此这个IP是ping不通的,但ipvs中这个IP是在每个节点上真实存在的,因此可以ping通:

当然由于这个IP就是配置在本地虚拟网卡上,所以对诊断问题没有一点用处的。

我们接下来研究下ClusterIP如何传递的。

当我们通过如下命令连接服务时:

此时由于10.96.54.11就在本地,所以会以这个IP作为出口地址,即源IP和目标IP都是10.96.54.11,此时相当于:

其中xxxx为随机端口。

然后经过ipvs,ipvs会从RS ip列中选择其中一个Pod ip作为目标IP,假设为10.244.2.2:

我们从iptables LOG可以验证:

我们查看OUTPUT安全组规则如下:

其中ipsetj集合 KUBE-CLUSTER-IP 保存着所有的ClusterIP以及监听端口。

如上规则的意思就是除了Pod以外访问ClusterIP的包都打上 0x4000/0x4000 。

到了POSTROUTING链:

如上规则的意思就是只要匹配mark 0x4000/0x4000 的包都做SNAT,由于10.244.2.2是从flannel.1出去的,因此源ip会改成flannel.1的ip 10.244.0.0 :

最后通过Vxlan 隧道发到Pod的Node上,转发给Pod的veth,回包通过路由到达源Node节点,源Node节点通过之前的MASQUERADE再把目标IP还原为10.96.54.11。

查看Service如下:

Service kubernetes-bootcamp-v1的NodePort为32016。

现在假设集群外的一个IP 192.168.193.197访问192.168.193.172:32016:

最先到达PREROUTING链:

如上4条规则看起来复杂,其实就做一件事,如果目标地址为NodeIP,则把包标记 0x4000 , 0x4000 。

我们查看ipvs:

我们发现和ClusterIP实现原理非常相似,ipvs Service的VIP为Node IP,端口为NodePort。ipvs会选择其中一个Pod IP作为DNAT目标,这里假设为10.244.3.2:

剩下的到了POSTROUTING链就和Service ClusterIP完全一样了,只要匹配 0x4000/0x4000 的包就会做SNAT。

Kubernetes的ClusterIP和NodePort都是通过ipvs service实现的,Pod当作ipvs service的server,通过NAT MQSQ实现转发。

简单来说kube-proxy主要在所有的Node节点做如下三件事:

使用ipvs作为kube-proxy后端,不仅提高了转发性能,结合ipset还使iptables规则变得更“干净”清楚,从此再也不怕iptables。

更多关于kube-proxy ipvs参考 IPVS-Based In-Cluster Load Balancing Deep Dive .

本文首先介绍了kube-proxy的功能以及kube-proxy基于iptables的实现原理,然后简单介绍了ipvs,了解了ipvs支持的三种转发模式,最后介绍了kube-proxy基于ipvs的实现原理。

ipvs是专门设计用来做内核态四层负载均衡的,由于使用了hash表的数据结构,因此相比iptables来说性能会更好。基于ipvs实现Service转发,Kubernetes几乎能够具备无限的水平扩展能力。随着Kubernetes的部署规模越来越大,应用越来越广泛,ipvs必然会取代iptables成为Kubernetes Service的默认实现后端。

转自


分享题目:后端服务器安全组规则 后端安全策略
文章网址:http://myzitong.com/article/ddicjsh.html