1、JWT是什么

官方网站

JWT是JSON Web Token的简称。是一种开放标准(RFC 7519),定义了一种紧凑且自包含的方式,以JSON对象的形式在各方之间安全地传输信息,因为他被数字签名也就是加密过,因此可以被用来验证和信任。JWT使用RSA或者ECDSA的公钥/私钥进行签名认证。

2、它能做什么

  • 认证:这是使用JWT最常见的场景。用户登录后,每个后续请求将包括JWT,允许用户访问该令牌允许的路由、服务和资源。单点登录是目前JWT广泛使用的一个特性,因为它的开销小,并且可以跨不同的域轻松使用。

  • 信息交换:JWT是一种很好的加密传输信息的方式,因为它可以被因为JWT可以使用公钥/私钥对进行签名,因此可以确保发送者是他们所说的人。另外,由于签名是使用报头和有效负载计算的,所以还可以验证内容没有被篡改。

3、JWT的特点

基于传统的session的认证

因为HTTP协议时一种无状态协议,这意味着如果用户向服务器发送自己的用户名和密码进行用户认证,那么下一次请求时,用户还要进行一次用户认证才可以,因为根据HTTP协议,我们并不知道是哪个用户发出的请求,所以为了让我们的应用能是被是哪个用户发出的请求,我们只能在服务器存储一份用户登录的信息,这份登录信息会在响应时间内传递给浏览器,告诉浏览器保存cookie,一别下次请求时发送给我们的应用,这样我们的应用就能够识别请求来自哪个用户了,这是传统的session认证。

问题

每个用户经过我们的应用认证后,我们的应用都在服务端进行一次记录,以方便用户下次请求的鉴别,通常而言session是保存在服务端的内存中的,随着认证用户的增多,服务器的开销会加大。

用户认证之后,服务端做认证记录,如果认证的记录都被保存在内存中的话,如果在分布式应用中,就相对的限制了负载均衡的能力。

因为是基于cookie来进行用户识别的,cookie如果被截获,用户就会很容易的受到跨站请求伪造攻击(CSRF)。

认证流程

首先,前端通过表单提交将用户名密码等信息发送都后端的接口。这个过程一般是一个PSOT的请求,建议通过SSL加密传输(https协议),从而避免敏感信息被嗅探。

后端核对用户名和密码成功后,将用户的id等其他信息作为JWT Payload,将其头部分别进行BASE64编码拼接后签名,形成一个JWT。形成的JWT的格式是header.payload.signature分割成三部分。

head:存一些token加密的方式,类型等信息。

"alg":"HS256",
"type":"JWT"
  • alg:签名算法,HS256、HS384、HS512、RS256、RS384、RS512、ES256、ES384、ES512、PS256、PS384
  • type:认证格式,如JWT。

payload:一般就是用户的信息。

例如:

{
"uid":"1234567",
"name":"Tom",
"admin":"true"
}

对该json字符串进行BASE64压缩就得到了第二部分,这里可以看出payload完全是明文暴露的,因为BASE64是编码格式,有编码就有解码,他可不是加密算法。

声明的主体信息格式有三中类型: registeredpublicprivate

signature:该部分是签名,以token的前两部分也就是head和payload作为明文,用共同协商好的私钥进行签名。

如果选择的算法是HMAC-SHA256,执行以下的方法得到签名值signature

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

如果是非对称加密

HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), publicKey, privateKey)

再回过来看认证流程,后端将JWT字符串作为登陆成功的返回结果返回给前端。前端可以将返回的结果存在本地缓存中或者sessionStorage中,退出登录的时候,只需要删除token即可。

前端每次请求都将JWT放在HTTP请求头的Authorization位(为了解决XSS和XSRF攻击)HEADER。

后端检查是否存在,如果存在还要进一步验证JWT的有效性。例如检查签名是否正确;检查Token是否过期;检查Token的接收方是否是自己。

验证通过后后端使用JWT中包含的用户信息进行其他逻辑操作,返回相应的结果。

因此从上面的验证过程看出,不压不铭感信息放在JWT中,例如用户密码等,因为如果知道秘钥在通过BASE64解码,就能知道payload中的内容。

4.JWT的优势

  • 简洁:可以通过URL,POST参数或者HTTP header发送,因为数据量小,传输速度快。
  • 自包含:payload中包含了所有用户所需要的信息,避免了多次查询数据库。
  • 因为token是以JSON加密的形式保存在客户端的,所以JWT是跨语言的,原则上任何web形式都支持。
  • 不需要保存服务端,使用户分布式应用。

5、常见异常信息

  • SignatureVerificationException:签名不一致
  • TokenExpireException:令牌过期异常
  • AlgorithmMismatchException:算法不匹配异常
  • InvalidClaimException:失效的payload异常。

SpringBoot 中对JWT的处理

首先编写JWT工具类,JWTUtil

public class JwtUtil {
// 签名可以用算法生成
private static final String SIGN = "%^$#@!*nbcfer12794"; /**
* 生成token
* @param map
* @return
*/
public static String getToken(Map<String, String> map){
Calendar instance = Calendar.getInstance();
instance.add(Calendar.DATE,7);
JWTCreator.Builder builder = JWT.create();
map.forEach((k,v)->{
builder.withClaim(k,v);
});
builder.withExpiresAt(instance.getTime());
return builder.sign(Algorithm.HMAC256(SIGN)); } /**
* 验证token
* @param token
* @return
*/
public static DecodedJWT verify(String token) throws Exception{
DecodedJWT verify = JWT.require(Algorithm.HMAC256(SIGN)).build().verify(token);
return verify;
}
}

每次请求都要检查请求头中是否包含正确的token,只有token验证成功才能继续进行加下来的操作。
因此可以自定义一个拦截器,每次请求都做检查token的工作。

public class JWTInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// errorMsg map
Map<String, Object> errorMsg = new HashMap<>(); // 从请求头中获取token
String token = request.getHeader("token"); // 验证token的有效性,如果校验成功返回true,放行,否则捕捉异常,返回errorMsg
try {
JwtUtil.verify(token);
return true;
}catch (SignatureVerificationException e){
errorMsg.put("msg","无效签名");
e.printStackTrace();
}catch (TokenExpiredException e){
e.printStackTrace();
errorMsg.put("msg","签名失效");
}catch (AlgorithmMismatchException e){
e.printStackTrace();
errorMsg.put("msg","签名算法不一致");
}catch (Exception e){
e.printStackTrace();
errorMsg.put("msg","签名异常");
}
errorMsg.put("state",false); // 返回的是json串,因此需要用jackson将map转成json
String jsonMsg = new ObjectMapper().writeValueAsString(errorMsg);
response.setContentType("application/json; charset=UTF-8");
response.getWriter().println(jsonMsg);
return false;
}
}

将拦截器加入到配置类中

@Configuration
public class JWTConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new JWTInterceptor())
.excludePathPatterns("/user/login") // 登陆的时候不进行拦截,因为第一次访问需要生成token
.addPathPatterns("/**");
}
}

剩下的是controller,service,dao
控制层需要调用service层的方法校验传过来的参数,如果无误,根据用户信息放入payload,生成token。最终返回提示信息。

@GetMapping("/user/login")
public Map<String, Object> login(String username,String password){
//校验参数
User loginUser = userService.login(username, password); // 通过后生成token,返回给客户端
Map<String, Object> map = new HashMap<>();
Map<String, String> payload = new HashMap<>();
payload.put("userId",loginUser.getUserId());
payload.put("username",loginUser.getUsername());
try{
String token = JwtUtil.getToken(payload);
map.put("token",token);
map.put("state",true);
map.put("msg","认证成功");
}catch (Exception e){
map.put("state",false);
map.put("msg","认证失败");
} return map;
}

用户postman测试一下。

当不带token的时候,自然会抛出异常,返回错误提示。

初识JWT的更多相关文章

  1. 初识SSO与JWT

    以前在学校做项目的时候,登录注销,权限验证这些事情,都是交给框架来做的,每次都是把这个架子拿到项目中去,也没有真正思考过它的过程,总觉的这些都是十分简单的逻辑. 然而来公司工作之后,慢慢觉得登录和权限 ...

  2. Spring Boot初识(4)- Spring Boot整合JWT

    一.本文介绍 上篇文章讲到Spring Boot整合Swagger的时候其实我就在思考关于接口安全的问题了,在这篇文章了我整合了JWT用来保证接口的安全性.我会先简单介绍一下JWT然后在上篇文章的基础 ...

  3. 初识单点登录及JWT实现

    单点登录 多系统,单一位置登录,实现多系统同时登录的一种技术 (三方登录:某系统使用其他系统的用户,实现本系统登录的方式.如微信登录.支付宝登录) 单点登录一般是用于互相授信的系统,实现单一位置登录, ...

  4. PHP JWT初识

    一直没有好好看过jwt,直到前两天要做web验证,朋友给我推荐了jwt.才发现jwt已经被大家广泛的应用了.看来我有点out了.哈哈,趁着这个世界来好好看看这个. JWT(JSON Web Token ...

  5. JWT初识记录

    因为前一段时间做了一个系统持续操作期间自动刷新token有效性的需求,然后就想着找一个空闲时间总结一下JWT,所以今天就简单的记录一下自己了解的内容. JWT是什么 JWT全称是JSON Web To ...

  6. ASP.NET Core WebAPI中使用JWT Bearer认证和授权

    目录 为什么是 JWT Bearer 什么是 JWT JWT 的优缺点 在 WebAPI 中使用 JWT 认证 刷新 Token 使用授权 简单授权 基于固定角色的授权 基于策略的授权 自定义策略授权 ...

  7. drf框架 - JWT认证插件

    JWT认证 JWT认证方式与其他认证方式对比: 优点 1) 服务器不要存储token,token交给每一个客户端自己存储,服务器压力小 2)服务器存储的是 签发和校验token 两段算法,签发认证的效 ...

  8. ASP.NET Web API 2系列(四):基于JWT的token身份认证方案

    1.引言 通过前边的系列教程,我们可以掌握WebAPI的初步运用,但是此时的API接口任何人都可以访问,这显然不是我们想要的,这时就需要控制对它的访问,也就是WebAPI的权限验证.验证方式非常多,本 ...

  9. CAS单点登录(一)——初识SSO

    转载:https://blog.csdn.net/Anumbrella/article/details/80821486 一.初识CAS 首先我们来说一下CAS,CAS全称为Central Authe ...

随机推荐

  1. OI学习过程记录

    这帖子本来是教练为了给低年级学生分享经验而让我写的学习经历,不过等我退役之后可能就变成回忆录了. 初三 WC 前:上了正睿的线上课程,练了一些模拟赛,同时也正在学文化课. 然后,莫名奇妙1膜考了全校前 ...

  2. P5327 [ZJOI2019]语言

    一边写草稿一边做题吧.要看题解的往下翻,或者是旁边的导航跳一下. 草稿 因为可以开展贸易活动的条件是存在一种通用语 \(L\) 满足 \(u_i\) 到 \(v_i\) 的最短路径上都会 \(L\) ...

  3. sqlplus、lsnrctl命令工具不可用(libclntsh.so.11.1)

    原因: libclntsh.so.11.1文件丢失了 解决方法: 在其他机器把这个文件拷贝到目标库安装目录底下的lib目录即可

  4. Java 8 新特性:Lambda、Stream和日期处理

    1. Lambda 简介   Lambda表达式(Lambda Expression)是匿名函数,Lambda表达式基于数学中的λ演算得名,对应于其中的Lambda抽象(Lambda Abstract ...

  5. IDEA将Java Web项目打war包

    准备工作 1.IntelliJ IDEA开发工具 2.可以正常运行的Java Web项目 打war包流程 1.使用快捷键Ctrl+Alt+Shift+s 或者 鼠标点击选中项目名按F4 打开 Proj ...

  6. OkHttpClient调优案例

    OkHttpClient调优案例 作者:Grey 原文地址: 语雀 博客园 Github 实际案例 系统运行一段时间后,线程数量飙升,CPU持续居高不下 排查工具 https://fastthread ...

  7. [日常摸鱼]HDU1348Wall-凸包

    我学习进度慢得连我自己都怕- 题意:大概给$n$个点搞出它的凸包,然后还要在凸包外弄一层厚为$l$的东西,求这个东西的周长 我个滞涨居然把pi开成了int-搞了一个晚上才看见 凸包直接求,因为是凸多边 ...

  8. [水题日常]Luogu1113 杂务

    这几天又在颓. 我的blog难度目前还比较低,主要面向像我这样子的新手(当然内容也会尽量讲得具体清楚一些)x 如果有错误还请指出~ 写完随笔之后才去翻了一下这题题解之后才注意到这题是有序的 QAQ完全 ...

  9. Eureka系列(九)Eureka自我保护机制

      因为本篇简文并不是自己总结的,而是当了下搬运工,所以直接直接附上原作者博客链接. 参考链接:   1.SpringCloud Eureka自我保护机制   2.Spring Cloud Eurek ...

  10. Springboot接入RabbitMQ详细教程

    本文适用于对 RabbitMQ 有所了解的人,在此不讨论MQ的原理,只讨论如何接入.其实Spring Boot 集成 RabbitMQ 非常简单,本文章使用的是Spring Boot 提供了sprin ...