JWT跨域认证

news/2024/12/22 9:37:10/

Session认证

用户认证的流程:

用户向服务器发送用户名和密码。
服务器验证通过后,在当前对话(session)里面保存相关数据,比如用户角色、登录时间等。
服务器向用户返回一个session_id,写入用户的Cookie。
用户随后的每一次请求,都会通过Cookie,将session_id传回服务器。
服务器收到session_id,找到前期保存的数据,由此得知用户的身份。

session认证的方式应用非常普遍,但也存在一些问题:扩展性不好。

如果是服务器集群,或者是跨域的服务导向架构,就要求session数据共享,每台服务器都能够读取session,否则当用户分到新的服务器时会要求重新登录(即使之前用户已经登录过了)。

针对此种问题一般有两种方案:

一种解决方案是session数据持久化,写入数据库或别的持久层。各种服务收到请求后,都向持久层请求数据。这种方案的优点是架构清晰,缺点是工程量比较大。

一种方案是服务器不再保存session数据,所有数据都保存在客户端,每次请求都发回服务器。Token认证就是这种方案的一个代表。【但是用户有可能会恶意篡改信息】

Token认证

Token是在服务端产生的一串字符串,是客户端访问资源接口(API)时所需要的资源凭证。

流程如下:

客户端使用用户名跟密码请求登录,服务端收到请求,去验证用户名与密码

验证成功后,服务端会签发一个token并把这个token发送给客户端

客户端收到token以后,会把它存储起来,比如放在cookie里或者localStorage里

客户端每次向服务端请求资源的时候需要带着服务端签发的token

服务端收到请求,然后去验证客户端请求里面带着的token,如果验证成功,就向客户端返回请求的数据。

Token认证的特点

基于token的用户认证是一种服务端无状态的认证方式,服务端不用存放token数据

用解析token的计算时间换取session的存储空间,从而减轻服务器的压力,减少频繁的查询数据库

token完全由应用管理,所以它可以避开同源策略

JWT

原理:

JSON Web Token(简称JWT)是一个token的具体实现方式,是目前最流行的跨域认证解决方案。
JWT的原理是,服务器认证以后,生成一个JSON对象,发回给用户,具体如下:
 

{
"姓名":"张三",
"角色":"管理员",
"到期时间":"2024年9月9日0点0分"
}

用户与服务端通信的时候,都要发回这个JSON对象。服务器完全只靠这个对象认定用户身份。

为了防止用户篡改数据,服务器在生成这个对象的时候,会加上签名。

组成:

JWT的由三个部分组成:

Header(头部)

Payload(负载),  携带的数据      

Signature(签名),对前两部分进行签名防止数据被篡改

三部分最终组合为完整的字符串,中间使用.分隔,如下

//Header.Payload.SignatureeyJhbGcioiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIioiIxMjMONTY30DkwIiwibmFtZSI6IkpvaG4gRG91IiwiaXNTb2NpYWwiOnRydWV9.
4pcPyMD09o1PSyXnrXCjTwXyr4BsezdI1AVTmud2fU4

Header

Header部分是一个JSON对象,描述JWT的元数据

{
"a1g":"Hs256",
"typ":"JWT"
}

alg属性表示签名的算法(algorithm),默认是HMAC SHA256(写成HS256),可以自行更改

typ属性表示这个令牌(token)的类型(type),JWT令牌统一写为JWT

最后,将上面的JSON对象使用Base64URL算法转成字符串,方便传输。

Payload

Payload部分也是一个JSON对象,用来存放实际需要传递的数据。JWT规定了7个官方字段,供选用。

iss(issuer):签发人exp(expiration time):过期时i间sub(subject):主题aud(audience):受众nbf(Not Before):生效时i间iat(Issued At):签发时间jti (WT ID):编号

注意,JWT默认是不加密的(签名≠加密),任何人都可以读到,所以不要把秘密信息放在个部分。
这个JSON对象也要使用Base64URL算法转成字符串。

Signature

Signature部分是对前两部分的签名,防止数据篡改。

首先,需要指定一个密钥(secret)。这个密钥只有服务器才知道,不能泄露给用户

然后,使用Header里面指定的签名算法(默认是HMAC SHA256),按照下面的公式产生签名。

HMACSHA256(base64UrlEncode(header)+"."+base64Ur1Encode(payload),secret)

算出签名后,把Header、Payload、Signature三个部分拼成一个字符串,每个部分之间用"点”(’.‘)分隔,就可以返回给用户。

JWT特点

客户端收到服务器返回的JWT,可以储存在Cookie里面,也可以储存在localStorage

客户端每次与服务器通信,都要带上这个JWT,可以把它放在Cookie里面自动发送,但是这样不能跨域

更好的做法是放在HTTP请求的头信息’Authorization‘字段里面,单独发送。

JWT的实现

加入依赖:

<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version>
</dependency>

生成Token:

//7天过期
private static Long expire 604800;
//32位秘钥
private static String secret "abcdfghiabcdfghiabcdfghiabcdfghi";
//生成token,自定义方法即可
public static String generateToken(String username){Date now new Date();Date expiration new Date(now.getTime()+1000 expire);return Jwts.builder().setHeaderParam("type","JWT")    //Header是固定的.setSubject(username)    //设置载荷.setIssuedAt(now)    //设置生效时间.setExpiration(expiration)    //设置过期时间.signwith(SignatureAlgorithm.HS512,secret)    //指定签名算法HS512,加入密钥.compact();    //合成,最后我们看到的字符串形式
}

解析Token

//解析token
public static Claims getclaimsByToken(String token){return Jwts.parser().setsigningKey(secret).parseclaimsJws(token).getBody();
}

JWT的实现演示:

创建工具类,用于创建(生成)jwt字符串和解析jwt。

package com.example.jwt_demo.jwtdemo.Util;import io.jsonwebtoken.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;import java.util.Date;
import java.util.Map;@Component  //将该类标记为一个Spring的组件,这样Spring框架会自动管理它的生命周期,并且可以在其他地方通过依赖注入使用它。
public class JWTUtil {@Value("${jwt.secretKey}")private String secretKey;//生成JWTpublic String createJWT(String id, String subject, long ttlMillis, Map<String, Object> map) throws Exception {JwtBuilder builder = Jwts.builder().setId(id).setSubject(subject)    //发行者.setIssuedAt(new Date())    //发行时间.signWith(SignatureAlgorithm.HS256, secretKey)  //签名类型、钥.compressWith(CompressionCodecs.DEFLATE);   //对载荷进行压缩'//处理自定义的Claims/*如果 map 不为空,调用 setClaims(map) 来将自定义的 claims(负载)添加到 JWT 中。Claims 是 JWT 的主体信息,包含了关于用户或上下文的相关信息,可以自定义存储用户角色、权限、用户 ID 等。*/if (!CollectionUtils.isEmpty(map)) {builder.setClaims(map);}//设置有效期/*如果 ttlMillis 大于 0,使用 setExpiration 方法设置 JWT 的过期时间。过期时间表示 JWT 的有效期,超过这个时间,JWT 就会失效。这里是通过 当前时间+有效期ttlMillis 来计算出过期时间。*/if (ttlMillis > 0) {builder.setExpiration(new Date(System.currentTimeMillis() + ttlMillis));}//生成 JWT 字符串/*调用 compact() 方法生成最终的 JWT 字符串。这是经过签名和编码的字符串,可以在客户端和服务端之间传输。*/return builder.compact();}//解析 JWT (parseJWT 方法)/*用于解析客户端传来的 JWT 字符串,并返回其中的 Claims(负载)信息。*/public Claims parseJWT(String jwtString) {return Jwts.parser().setSigningKey(secretKey)   //创建一个 JWT 解析器,并设置签名的密钥(必须与生成时的 secretKey 一致).parseClaimsJws(jwtString)  //对传入的 JWT 字符串进行解析,并验证其合法性(例如,签名是否匹配、是否过期等).getBody(); //返回 JWT 的主体 Claims,其中包含了之前设置的 id、subject 和自定义的 map 信息}}

接着在application.yml配置文件配置jwt.secretKey。


http://www.ppmy.cn/news/1528249.html

相关文章

导电滑环在工业设备中的作用分析

导电滑环作为现代工业设备中的关键组件&#xff0c;广泛应用于各种机械和电子系统中。本文将探讨导电滑环的工作原理及其在不同应用领域中的重要作用。 导电滑环的工作原理主要基于电气传导与机械旋转的结合。导电滑环通常由环形导体和刷子组成&#xff0c;刷子紧贴在滑环表面…

前缀和与差分(二维)

二维前缀和 下面是一个二维数组&#xff0c;我们要求&#xff08;1&#xff0c;1&#xff09;到&#xff08;2&#xff0c;2&#xff09;区间内的所有元素的和&#xff0c;最原始的方法就是遍历每个元素然后一个一个加起来&#xff0c;此时时间复杂度为O(n*m)。 我们之前学过…

下载 B 站封面的正确方式

B 友们经常用一些很好看的图片作为视频封面&#xff0c;但是大部分都不会指出图片来源&#xff0c;为此我们可以下载封面原图&#xff0c;用于保存或者搜索源出处。 这里介绍几个我知道的方法&#xff0c;欢迎补充&#x1f914; ‍ 使用相关客户端 上一篇博客介绍了很多的能…

【C++篇】~类和对象(中)

类和对象&#xff08;中&#xff09; 1.类的默认成员函数​ 默认成员函数就是用户没有显式实现&#xff0c;编译器会自动生成的成员函数称为默认成员函数。一个类&#xff0c;我们不写的情况下编译器会默认生成以下6个默认成员函数&#xff0c;需要注意的是这6个中最重要的是前…

k8s证书过期处理

证书一共分为 根CA&#xff08;ca.crt&#xff09; master各组件的证书&#xff08;包括etcd、apiserver、front-proxy、controller-manager等各种&#xff09; kubelet证书 k8s证书有效期说明&#xff1a; 1、原生版本有效期master节点&#xff1a; /etc/kubernetes/ssl/…

Node js介绍

目录 概要**对Node的认识****Node的概念理解****Node和浏览器区别****Node的架构图** **Node的应用场景****Node的安装****安装Node的LTS版本****Node的版本管理工具nvm(了解)** **Node的输入和输出**Node程序传递参数Node的输出 **Node的全局对象****特殊的全局对象****其他的…

[ffmpeg] 视频格式转换

本文主要梳理 ffmpeg 中的视频格式转换。由于上屏的数据是 rgba&#xff0c;编码使用的是 yuv数据&#xff0c;所以经常会使用到视频格式的转换。 除了使用 ffmpeg进行转换&#xff0c;还可以通过 libyuv 和 directX 写 shader 进行转换。 之前看到文章说 libyuv 之前是 ffmpeg…

2024新动态:低代码开发占领新常态市场

随着技术的不断进步和数字化转型的加速&#xff0c;企业对于快速开发和部署应用程序的需求日益增长。2024年&#xff0c;低代码开发平台已经成为新常态市场的重要力量&#xff0c;它通过简化应用程序的开发过程&#xff0c;让非技术背景的业务用户也能参与到软件开发中来&#…