MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature()----》获得修饰符+ 包名+组件名(类名) +方法名
Method method = methodSignature.getMethod()----》获取方法名
PugRateLimiter annotation = method.getAnnotation(PugRateLimiter.class)----》通过方法名上面的“小旗子”类,获取注解携带的限流参数
Integer limit = annotation.limit()----》获取限制次数 Integer timeout = annotation.timeout()----》获取限制时间
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes() ----》获取请求属性
HttpServletRequest request = requestAttributes.getRequest()----》获取请求对象
String methodNameKey = getRateLimiterKey(annotation, joinPoint, request)----》获取redis的key
String userIp = IpUtils.getIpAddr(request)----》获取请求IP
Boolean acquired = stringRedisTemplate.execute(ipLimitLua, Lists.newArrayList(methodNameKey), limit.toString(), timeout.toString())----》请求lua脚本实现限流,根据返回值进一步进行限流返回操作
ipLimiLua----》用来读取lua脚本,序列化为java可以操作的语言
jwt是为了解决传统session+cookie的登录校验的缺点。
传统的session+cookies的方法,session存储在服务端,这样客户端每次发起请求的时候只能请求同一个服务器,且将校验数据存储在服务器端会占用大量内存,不利于维护和扩展。而且cookie一旦被拦截,则用户很容易遭受跨站请求伪造的攻击。
而基于jwt token的鉴权机制,则是将认证信息(token)保存在客户端,服务端只需要保存用于加解密的secret(盐/密钥),每次客户端访问时,将首次访问服务端派发的token携带在请求头中,这样服务端拿到token,然后利用服务端存储的secret来进行解密,从而鉴权。服务器需要支持CORS(跨域资源共享)策略,以便于服务器密钥共享。
JWT 由三部分构成,分别是头部(header)、载荷(payload,类似于飞机上承载的物品)、签证(signature)。将这三部分用“ . ”连接起来,就构成了JWT字符串。
例如:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJVc2VySWQiOjEyMywiVXNlck5hbWUiOiJhZG1pbiJ9.Qjw1epD5P6p4Yy2yju3-fkq28PddznqRj3ESfALQy_U
header主要包含两部分信息:
完整的头部如:
{ 'typ':'JWT', 'alg':'HS256' },然后经过based64加密(该加密是可以对称解密的),构成JWT第一部分:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
载荷是用来存放有效信息的地方,它主要包含三部分:
标准中注册的声明
iss:jwt签发者
sub:jwt所面向的用户
aud:接收jwt的一方
exp:jwt的过期时间,这个过期时间必须大于签发时间
nbf:定义在什么时间之前,该jwt都是不可用的
iat:jwt的签发时间
jti:jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击
公共的声明
公共的声明可以添加任何的信息,一般添加用户的相关信息或其它业务需要的必要信息,但不建议添加敏感信息,因为该部分在客户端可解密 。
私有的声明
私有的声明是提供者和消费者功能定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为名文信息。
payload:
{ "sub": "1234567890", "name": "John Doe", "admin": true },经过based64加密:
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
签证是JWT的第三个部分,这个部分需要base64加密后的header和base64加密后的payload使用“.”连接组成字符串,然后用header中声明的加密方式,然后进行加secret加密。
如:
var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload); var signature = HMACSHA256(encodedString, 'secret'); // TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
最终的JWT,就是由这三部分用“ . " 连接起来组成一个完整字符串:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
因为json的通用性,所以JWT是可以跨语言支持的,像C#,JavaScript,NodeJS,PHP等许多语言都可以使用
因为由了payload部分,所以JWT可以在自身存储一些其它业务逻辑所必要的非敏感信息
便于传输,jwt的构成非常简单,字节占用很小,所以它是非常便于传输的
它不需要在服务端保存会话信息,所以它易于应用的扩展
不应该在jwt的payload部分存储敏感信息,因为该部分是客户端可解密的部分
保护好secret私钥。该私钥非常重要
token
一般是在请求头里加入Authorization,并加上Bearer标注:
fetch('api/user/1', {
headers: { 'Authorization': 'Bearer ' + token
}
})
首先判断请求头中是否有token,token需要前缀Bearer
若请求头带有token则判断是否过期。