网站维护费大概多少,qq企业邮箱 wordpress,python 做的网站,python 自己做网站1、HTTP无状态及解决方案
HTTP一种是无状态的协议#xff0c;每次请求都是一次独立的请求#xff0c;一次交互之后就是陌生人。
以CSDN为例#xff0c;先登录一次#xff0c;然后浏览器退出#xff0c;这个时候在进入CSDN#xff0c;按理说服务器是不知道你已经登陆了每次请求都是一次独立的请求一次交互之后就是陌生人。
以CSDN为例先登录一次然后浏览器退出这个时候在进入CSDN按理说服务器是不知道你已经登陆了所以需要你重新登录但实际却是再次点进来之后仍然保持登录状态。
这是因为解决了HTTP无状态这个问题解决方式有很多
①使用Session和Cookie将 无状态 变为 有状态
第一次请求时服务器会自动记录一个SessionId然后把SessionId返回给浏览器。再次发起请求时浏览器就会携带SessionId而服务器就可以根据SessionId去查询会话信息(session)。
服务器可以往会话里保存用户信息 浏览器会自动保存SessionId Session弊端Session和Cookie适用于单机环境默认情况下会话信息(session)是保存在服务器内存中用户量大的话服务器内存压力大。如果生产是集群环境就没办法保证浏览器的请求每一次都传到有会话信息的那一台服务器。
这种也好解决把会话信息存到Redis里每次访问服务器根据SessionId去Redis拿会话信息SpringBoot实现了这个功能引入【spring-session-data-redis】依赖包做一些设置就会自动将会话信息交给Redis管理这样做服务器的内存压力也就会见。 ②使用Token
在登录时生成一个Token放入Redis之后把token返回给浏览器。浏览器发起其他请求时携带这个token服务器再去Redis看这个Token是否失效之类的。 ③使用JWT
使用JWT和使用Token很像但JWT不需要存储到Redis就能通过验签知道用户信息是否伪造、用户登录状态是否过期等等。 2、JWT的基本介绍
JWT官网地址https://jwt.io/
JWT全称JSON WEB TOKEN是一种JSON格式的Web应用令牌它是基于令牌去做认证。
什么是令牌举个例子古代调兵用的虎符这就相当于是令牌有了虎符才能调兵。而令牌也是有了令牌才能访问后端接口。 以下是官网介绍 大致就是JWT能够通过HMAC算法默认算法或者通过RSA、ECDSA算法生成数字签名(Signature)。 JWT令牌的组成 JWT由三部分组成Header(头)、Payload(负载)、Signature(签名)三部分用 . 进行分隔 Header
两部分组成令牌的类型是什么签名(Signature)使用什么算法。
从官网复制的例子表示令牌的类型是JWT算法是 HMAC-SHA256 {alg: HS256,typ: JWT
} Header的JSON串经过Base64编码就转换成 x.y.z 的 x部分 Payload
负载有七个默认字段 iss发行人 exp到期时间 sub主体 aud用户 nbf在此之前不可用 iat发布时间 jtiJWT ID用于标识该JWT 官方样例如下name 和 admin为自定义的字段
{sub: 1234567890,name: John Doe,admin: true
}
负载里面可以放自定义字段这部分内容也是通过Base64编码变成x.y.z部分的y部分可以通过Base64解码拿到里面的信息。所以官方也推荐不要往负载里存放敏感信息比如密码之类的除非想故意被攻击。 Signature
官方提供的例子如下可以看见签名是通过前两部分Header 和 Payloadbase64编码之后的字符串拼接成一个新的字符串以及指定一个密钥(secret)并使用Header里指定的算法生成的签名。因此密钥是一定不能暴露出去的。 HMACSHA256(base64UrlEncode(header) . base64UrlEncode(payload),secret) 假如攻击者对前两部分进行随意修改并冒充前端发起请求。后端每次验签的时候都会根据前两部分内容加上密钥(secret)再去生成一次签名而由于攻击者修改了内容所以生成的签名肯定和传来的签名不匹配这就说明被篡改了从而验签失败。 3、JWT的优缺点
优点
1、JWT生成的令牌保存在客户端前端服务端不会保存令牌减少了服务器内存的损耗。
2、易扩展负载中可以保存自定义的信息。
3、使用强密钥生成签名时JWT提供了很好的安全性。
4、使用JWTHTTP仍是无状态的和Session、Cookie的方式正好相反JWT不需要在服务器存储会话信息非常适合集群环境。 缺点
1、JWT 本身不支持会话管理不能主动使令牌失效。假如用户修改了密码这个时候肯定要重新登录原先的JWT令牌按理就应该失效但是由于没有到令牌指定的过期时间所以原先的令牌仍然是有效的。可以将令牌存到redis当修改密码后删除令牌当令牌没有就强制用户去登录
2、负载(Payload)中存放过多用户数据时会影响性能。 4、如何使用JWT
大致流程用户通过前端页面进行登录业务校验通过之后生成一个令牌JWT后端将JWT返回给前端前端进行保存。之后前端每次访问后端都必须携带JWT后端去验证令牌JWT的合法性。
①导入JWT依赖
dependencygroupIdcom.auth0/groupIdartifactIdjava-jwt/artifactIdversion3.4.0/version
/dependency ②编写工具类生成令牌
前面提到了JWT令牌由三部分组成所以创建一个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.Base64;
import java.util.Calendar;
import java.util.HashMap;public class JWTUtil {//密钥一般是从配置文件读取private static final String secretKey 4008123123#;private static final String algorithm Algorithm.HMAC256(secretKey).getName();/*** 生成JWT令牌** return*/public static String generateJwtToken(String userId, String secretKey) {Calendar exp Calendar.getInstance();//过期时间当前时间往后推20分钟exp.add(Calendar.MINUTE, 20);System.out.println(过期时间 exp.getTime());// HashMapString, Object map new HashMapString, Object();
// map.put(alg,algorithm);
// map.put(typ,JWT);String token JWT.create()//header即使不写也会使用默认的推荐算法HS256和JWT令牌类型
// .withHeader(map).withExpiresAt(exp.getTime()) //默认的负载字段设置过期时间.withClaim(userId, userId) //负载---自定义字段.withClaim(username, UMR123) //负载---自定义字段.sign(Algorithm.HMAC256(secretKey));System.out.println(token);return token;}/*** 验签验证JWT令牌的合法性** param jwtToken* param secretKey* return 用来获取令牌信息*/public static DecodedJWT verifyToken(String jwtToken, String secretKey) {//生成验证对象JWTVerifier jwtVerifier JWT.require(Algorithm.HMAC256(secretKey)).build();//如果验证没问题就可以获取到负载信息如果签名有问题(签名不一致令牌过期)就会报错DecodedJWT verify jwtVerifier.verify(jwtToken);System.out.println(负载(Payload)经过base64解码 new String(Base64.getDecoder().decode(verify.getPayload())));System.out.println(userId信息 verify.getClaim(userId).asString());System.out.println(username信息 verify.getClaim(username).asString());System.out.println(令牌过期时间: verify.getExpiresAt());return verify;}public static void main(String[] args) {//生成令牌String jwtToken generateJwtToken(user123, secretKey);System.out.println();verifyToken(jwtToken, secretKey);}
} 控制台打印结果如下 服务端生成JWT令牌之后客户端在请求其他接口时请求头新增Authorization字段放入JWT信息 Authorization: Bearer token 都是对数据完整性和用户身份进行校验什么时候直接使用算法生成签名什么时候使用JWT
当需求没有要求过期时间就可以使用直接使用算法反之用JWT令牌是最好的。