首页 >> 大全

Jwt的新手入门教程

2023-11-18 大全 32 作者:考证青年

1.Jwt究竟是什么东东?

学习交流君羊【】暗号:67

再贴官方的定义:

What is JSON Web Token?

JSON Web Token (JWT) is an open (RFC 7519) that a and self- way for as a JSON . This can be and it is . JWTs can be using a (with the HMAC ) or a / key pair using RSA or ECDSA.

JWTs can be to also

, we will focus on . can the

of the it, while

hide those from other . When are using

/ key pairs, the also that only the

party the key is the one that it.

我的理解总结:Jwt全称是Json Web Token,顾名思义就是一种通过Json方式来传输的令牌,并且他最大的特点就是 ,签发者可以使用各种的加密方式对信息进行签名,更重要的是Jwt还能验证token是否被篡改或者token是否正确。当然了,这种方式注定是不安全的。我们很容易地就可以在官网得到这一结论。文章来源乐字节

可以看到,只要我们获得token字符串,就可以获取到里面的大部分信息,除了签名的密钥。

所以Jwt简单来说,就是简单地存储部分不那么重要的信息,通过Json,对客户端进行验证的一种方式。

2.Jwt的组成

​ 从官网的界面,我们可以得知,Jwt由三部分组成。

魔方玩法技巧入门新手教程__魔术气球入门新手教程

  "alg": "HS256","typ": "JWT"

这个的含义就是"alg"–(算法) 是HS256。

{"sub": "1234567890","name": "John Doe","admin": true
}

但是要注意的是,记录的这些信息是完全公开的,所以千万不能把用户或者系统的敏感数据放到中,只是负责记录简单信息,并不具备加密的功能。

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

可以说这部分是Jwt的重点,因为他承担着两个作用,第一个:验证在传输过程中没有受到篡改 第二个:验证签发人的身份

​ 详细说一下这两个作用。

验证在传输过程中没有受到篡改,这个原理就比较好理解,因为中有一个字符串,也就是,这个是由我们来设置的,相当于私钥,只有我们自己才知道,别人是不知道的。那么在后续验证过程中,只要我们自己生产的Token与客户端传来的Token进行比对,如果一致那就证明该Token没有受到篡改,反之则证明客户端传来的Token是非法的。

验证签发人的身份,其实第二个作用是从第一个作用中展现而来的,因为如果能证明Token在传输过程中没有受到篡改,那就更加说明服务端是这个签名的签发者,因为只有签发者才知道私钥。

​ 其实我们也可以认为是盐(salt),我们知道如果单纯地在数据库中存储明文密码,或者是只经过一重MD5加密的密码,是非常的不安全,因为就算是经过MD5加密,仍然可以通过暴力穷举的方式来进行破解,可是如果在用户密码的基础上,加上我们生成的随机或固定的字符串,然后再进行加密,那么安全程度会大大提升。

​ 如果不知道盐(salt)的童鞋,可以去bind搜索一下相关资料,其实理解起来就是用户密码+我们设置的随机或固定字符串再进行多重加密。

3.编码实现

​ 我们来创建这几个类。

配置类:

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(authenticationInterceptor()).addPathPatterns("/**").excludePathPatterns("/login");}@Beanpublic JwtInterceptor authenticationInterceptor() {return new JwtInterceptor();}}

控制类:

@RestController
public class UserController {@PostMapping("/login")public Map, Object> login(@RequestBody User user) {Map, Object> map = new HashMap<>();String username = user.getUsername();String password = user.getPassword();// 省略 账号密码验证// 验证成功后发送tokenString token = JwtUtil.sign(username, password);if (token != null) {map.put("code", "200");map.put("message", "认证成功");map.put("token", token);return map;}map.put("code", "403");map.put("message", "认证失败");return map;}@GetMapping(value = "/api/test")public String get(){System.out.println("执行了get请求");return "success";}
}

服务类:

@Service
public class UserService {public String getPassword(){return "admin";}
}

实体类 User

@Data
public class User {private String username;private String password;}

自定义拦截器类

@Component
public class JwtInterceptor implements HandlerInterceptor {@AutowiredUserService userService;@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {// 从 http 请求头中取出 tokenString token = request.getHeader("token");// 如果请求不是映射到方法直接通过if(!(handler instanceof HandlerMethod)){return true;}if (token != null){String username = JwtUtil.getUserNameByToken(request);// 这边拿到的 用户名 应该去数据库查询获得密码,简略,步骤在service直接获取密码boolean result = JwtUtil.verify(token,username,userService.getPassword());if(result){System.out.println("通过拦截器");return true;}}return false;}@Overridepublic void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {}@Overridepublic void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {}
}

Jwt工具类

public class JwtUtil {// Token一天后过期public static final long EXPIRE_TIME = 1000 * 60 * 60 * 24;//检验Token是否正确public static boolean verify(String token, String username, String secret) {try {// 设置加密算法Algorithm algorithm = Algorithm.HMAC256(secret);JWTVerifier verifier = JWT.require(algorithm).withClaim("username", username).build();// 效验TOKENDecodedJWT jwt = verifier.verify(token);return true;} catch (Exception exception) {return false;}}public static String sign(String username, String secret) {//现在系统的时间 + 一天Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);//对密码进行加密Algorithm algorithm = Algorithm.HMAC256(secret);// 附带username信息return JWT.create().withClaim("username", username).withExpiresAt(date).sign(algorithm);}public static String getUserNameByToken(HttpServletRequest request)  {String token = request.getHeader("token");DecodedJWT jwt = JWT.decode(token);return jwt.getClaim("username").asString();}}

具体代码,可以加入我的企鹅君羊:、暗号67

也可以看我制作的视频教程:代码教程

这里代码的则是用户的密码。

我们先通过向/login接口发送我们的账号密码,得到Jwt根据我们的账号密码生成的token。

{"code": "200","message": "认证成功","token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MzIzMTg1NjksInVzZXJuYW1lIjoiYWRtaW4ifQ.c_m3z11UOcFcS_hZN9KNlidzZ2j6y_Ugkb9awHQ3FGY"
}

这里认证成功后,服务器如果不经过我们其他的存储操作,是不会对生成的token进行持久化或其他控制的,所以一旦签发出去,这个token串就会变成无状态了。

​ 接着,我们访问一下我们的api测试接口,因为我们在里配置了全局拦截器,且重写了类,除了/login路径,其他全路径都需要请求的(请求头)中带有token字段,且需验证token成功后才会允许访问,否则进行拦截。

4.管理的状态

​ 要做到管理的状态,我们可以通过把token存储到Redis数据库中,通过设置key的过期时间,就可以做到对Jwt的过期操作,同时也能够对Token进行续签,失效等等操作。这部分先不去仔细探究,有个思路就可以了。具体的编码实现我相信也不难。文章来源乐字节

具体代码,可以加入我的企鹅君羊:、暗号67

也可以看我制作的视频教程:代码教程

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了