十二、反向代理服务器——Nginx
支持热部署,几乎可以做到 7 * 24 小时不间断运行,即使运行几个月也不需要重新启动,还能在不间断服务的情况下对软件版本进行热更新。性能是 Nginx 最重要的考量,其占用内存少、并发能力强、能支持高达 5w 个并发连接数,最重要的是, Nginx 是免费的并可以商业化,配置使用也比较简单。
使用场景
- 静态资源服务,通过本地文件系统提供服务;
- 反向代理服务,延伸出包括缓存、负载均衡等;
- API 服务, OpenResty。
## 正向和反向代理区别
正向代理需要你主动设置代理服务器ip或者域名进行访问,由设置的服务器ip或者域名去获取访问内容并返回;
反向代理不需要你做任何设置,直接访问服务器真实ip或者域名,但是服务器内部会自动根据访问内容进行跳转及内容返回,你不知道它最终访问的是哪些机器。
## 使用场景
正向:VPN
反向:保护和隐藏原始资源服务器、加密和SSL加速、负载均衡、缓存静态内容、压缩、减速上传、安全、外网发布
十三、远程过程调用——RPC
- 客户端(Client):服务调用方(服务消费者)
- 客户端存根(Client Stub):存放服务端地址信息,将客户端的请求参数数据信息打包成网络消息,再通过网络传输发送给服务端
- 服务端存根(Server Stub):接收客户端发送过来的请求消息并进行解包,然后再调用本地服务进行处理
- 服务端(Server):服务的真正提供者
十四、JWT——轻量级的身份验证和授权机制
组成
- Header(标头),通常由两部分组成:令牌的类型 和 所用的加密算法,然后将该JSON对象数据进行Base64 URL编码,得到的字符串就是JWT令牌的第一部分。
- Payload(载荷),有效数据存储区,主要定义自定义字段和内置字段数据。通常会把用户信息和令牌过期时间放在这里,同样也是一个JSON对象,里面的key和value可随意设置,然后经过Base64 URL编码后得到JWT令牌的第二部分
- Signature(签名), 使用头部Header定义的加密算法,对前两部分Base64编码拼接的结果进行加密,加密时的秘钥服务私密保存,加密后的结果在通过Base64Url编码得到JWT令牌的第三部分。
- JWT令牌由Header、Payload、Signature三部分组成,每部分字符串中间用. 拼接。JWT令牌的最终格式是这样的: 第一部分.第二部分.第三部分
流程
- 应用在用户认证后不需要把用户信息保存在内存中,而是将用户信息编码成JWT TOKEN,返回
- 前端可以把token保存在localStorage或sessionStorage中,退出登录时删除Token
- 每次请求时,前端应把Token放在HTTP请求Header的Authorization字段中,并且后端验证Token的有效性和正确性
- 如果Token被验证通过,后端可以根据Token中的用户信息进行其他权限或业务操作,并返回相应的结果
代码
package com.example.mydreams.jwt;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.util.Calendar;
import java.util.HashMap;
public class JwtDemo {
public static void main(String[] args) {
String token = generateJwtToken();
System.out.println("生成的JWT的Token为:");
System.out.println(token);
//创建验证对象
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("Periqi")).build();
DecodedJWT verify = jwtVerifier.verify(token);
System.out.println("验证传入的用户信息为:userId:"+verify.getClaim("userId")+",username:"+verify.getClaim("username")+",过期时间:"+verify.getExpiresAt());
}
//生成JWTtoken
public static String generateJwtToken() {
HashMap<String,Object> map = new HashMap();
Calendar instance = Calendar.getInstance();
instance.add(Calendar.SECOND,1000);
String token = JWT.create()
.withHeader(map) //Header(可以不用设置,因为Header有默认值:{"alg":"HS256", "typ":"JWT" })
.withClaim("userId",100) //payload
.withClaim("username","码农佩奇") //payload
.withExpiresAt(instance.getTime()) //指定令牌过期时间
.sign(Algorithm.HMAC256("Periqi")); //Signature
return token;
}
}
程序运行结果:
生成的JWT的Token为:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MDE0NDI0OTYsInVzZXJJZCI6MTAwLCJ1c2VybmFtZSI6IueggeWGnOS9qeWlhyJ9.qAik5UQsDV_mjr10C3cyCqpLBvhI_IXZDRczQQy2mCk
验证传入的用户信息为:userId:100,username:"码农佩奇",过期时间:Fri Dec 01 22:54:56 CST 2023
验证
服务器收到token后,取出前2部分使用私钥签名得到结果,与token第三部分比较,看是否相同
- SignatureVerificationException 签名不一致异常
- TokenExpiredException 令牌过期异常
- AlgorithmMismatchException 算法不匹配异常
- InvalidClaimException 失效的payload异常
缺点:不支持注销、Token过期机制存在缺陷、Token数量过多可能导致性能问题