环境介绍
技术栈 |
springboot+mybatis-plus+mysql+java-jwt |
软件 |
版本 |
mysql |
8 |
IDEA |
IntelliJ IDEA 2022.2.1 |
JDK |
1.8 |
Spring Boot |
2.7.13 |
mybatis-plus |
3.5.3.2 |
Json Web令牌简称JWT
Token是在服务端产生的一串字符串是客户端访问资源接口(AP)时所需要的资源凭证。
Token认证流程
1、客户端使用用户名跟密码请求登录,服务端收到请求,验证用户名与密码验证成功后,服务端会签发一个 token并把这个 token发送给客户端,客户端收到 token后,会把它存储起来,比如放在cookie里或者localStorage里
2、客户端每次向服务端请求资源的时候需要带着服务端签发的 token
3、服务端收到请求,然后去验证客户端请求里面带着的 token,如果验证成功就向客户端返回请求的数据
token用户认证是一种服务端无状态的认证方式,服务端不用存放token数据。
用解析 token的计算时间换取 session的存储空间,从而减服务器的力,减少频繁的查询数据库
token完全由应用管理,所以它可以避开同源策略
JWT的使用
JSON Web Token(简称JWT)是一个 token的具体实现方式,是目前最流行的跨域认证解决方案。JWT的原理是:服务器认证以后,生成一个JSON对象,发回给用户。
{
“name” :”张三”,
“time”:”2022年10月10日”
}
用户与服务端通信时,都要发回该JSON对象。服务器完全只靠这个对象认定用户身份。
为防止用户篡改数据,服务器在生成对象时,会加上签名
JWT由三个部分组成:Header(头部)、Payload(负载)、Signature(签名)
Header.Payload.Signature
官方描述
Header
JWT头是一个描述JWT元数据的JSON对象,alg属性表示签名使用的算法,默认为HMAC SHA256(写为HS256);typ属性表示令牌的类型,JWT令牌统一写为JWT。最后,使用Base64 URL算法将上述JSON对象转换为字符串保存
{
"alg": "HS256",
"typ": "JWT"
}
Payload
有效载荷部分,是JWT的主体内容部分,也是一个JSON对象,包含需要传递的数据。 JWT指定七个默认字段供选择
iss:发行人
exp:到期时间
sub:主题
aud:用户
nbf:在此之前不可用
iat:发布时间
jti:JWT ID用于标识该JWT
Signature
签名哈希部分是对上面两部分数据签名,需要使用base64编码后的header和payload数据,通过指定的算法生成哈希,以确保数据不会被篡改。
加入依赖
<dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>4.3.0</version> </dependency>
入门案例
@Test //生成token void jwtdemo01(){ Calendar instance = Calendar.getInstance(); //instance.add(Calendar.SECOND, 90); instance.add(Calendar.DAY_OF_WEEK, 7); System.out.println(instance.getTime()); String token = JWT.create() .withClaim("username", "李四")//payload 设置自定义用户名 .withExpiresAt(instance.getTime())//设置过期时间 .sign(Algorithm.HMAC256("123"));//设置签名 密钥 System.out.println(token); //"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MDM5NDcyODMsInVzZXJuYW1lIjoi5p2O5ZubIn0.3onRy8p0G9ojnpA9u5h5ytd8hLZpGMZUyj49LTge5ao" } @Test //验证token void jwtdemo02(){ //创建验证对象 //参数1:签名使用的算法 参数2:签名的密钥 JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("123")).build(); // DecodedJWT verify =jwtVerifier.verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE3MDM5NDcyODMsInVzZXJuYW1lIjoi5p2O5ZubIn0.3onRy8p0G9ojnpA9u5h5ytd8hLZpGMZUyj49LTge5ao"); System.out.println(verify.getClaim("username")); }
Springboot整合JWT
JWT工具类
public class JWTUtil { private static final String TOKENKey="qgs12345"; /** * 生成token * @param map * @return 返回token */ public static String getToken(Map<String,String> map){ Calendar instance = Calendar.getInstance(); instance.add(Calendar.DATE,7);//7天过期 //添加payload JWTCreator.Builder builder = JWT.create(); map.forEach((k,v)->{ builder.withClaim(k,v); }); builder.withExpiresAt(instance.getTime());//设置令牌过期时间 //生成并返回token return builder.sign(Algorithm.HMAC256(TOKENKey)).toString(); } /** * 验证token * @param token */ public static void verify(String token){ JWT.require(Algorithm.HMAC256(TOKENKey)).build().verify(token); } /** * 获取token中payload * @param token * @return */ public static DecodedJWT getTokenInfo(String token){ return JWT.require(Algorithm.HMAC256(TOKENKey)).build().verify(token); } }
UserController
@RestController @RequestMapping("/users") @CrossOrigin //表示都允许跨域访问 public class UserController extends BaseController{ @Autowired private UserService userModuleService; @RequestMapping("/login") public Map<String,Object> login(String username, String password){ Map<String,Object> map =new HashMap<>(); try { User data = userModuleService.login(username, password); Map<String,String> payload =new HashMap<>(); payload.put("username",data.getUsername()); //生成JWT令牌 String token =JWTUtil.getToken(payload); map.put("state",true); map.put("msg","登入成功"); map.put("token",token); }catch (Exception e){ map.put("state",false); map.put("msg","登入失败"); } return map; } //验证token @RequestMapping("/loginVerify") public Map<String,Object> loginVerify(String token){ System.out.println(token); Map<String,Object> map =new HashMap<>(); try { //生成JWT令牌 JWTUtil.verify(token); map.put("state",true); map.put("msg","验证成功"); }catch (Exception e){ map.put("state",true); map.put("msg","验证失败"); } return map; } }
登录,产生token
验证token
Session认证
session用户认证流程
1、用户向服务器发送用户名和密码。
2、服务器验证通过后,在当前对话( session)里面保存相关数据,比如用户角色登录时间等。
3、服务器向用户返回一个 session_id,写入用户的 Cookie。
4、用户随后的每一次请求,都会通过Cookie,将 session_id传回服务器。
5、服务器收到 session_id,找到前期保存的数据,由此得知用户的身份。