JWT 简介

  • JWT:Json Web Token

  • 官网:https://jwt.io

  • 优点:可生成安全性较高的 token 且可以完成时效性的检验(登陆过期检查)

  • JWT 结构:(由官网获取)

JWT 生成 token

添加依赖:

<!-- java-jwt -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.18.2</version>
</dependency>
<!-- jjwt -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>

生成 token 示例代码:

//使用jwt生成token进行加密
JwtBuilder builder = Jwts.builder(); //此map可以存储用户角色权限信息
Map<String, Object> map = new HashMap<>();
map.put("k1", "v1"); //链式调用,设置相关加密信息
String token = builder.setSubject(name) //设置主题,也就是设置token中携带的数据
.setIssuedAt(new Date()) //设置token生成时间
.setId(users.get(0).getUserId() + "") //设置token的id(此处用的用户id)
.setClaims(map) //map中可存放用户角色权限信息
.setExpiration(new Date(System.currentTimeMillis() + 24 * 60 * 60 * 1000)) //设置token过期时间为1天后
.signWith(SignatureAlgorithm.HS256, "luis333") //设置加密方式和加密密码
.compact();

JWT 解析 token

//获取token并校验
if (token == null) {
return new ResultVo(ResStatus.NO, "请先登陆!", null);
} else { //获取jwt解析器
JwtParser parser = Jwts.parser();
parser.setSigningKey("luis333"); //之前加密时的加密密码,一致才能解析成功 try {
//如果token正确(密码正确,且在有效期内)则正常执行,否则抛出异常
Jws<Claims> claimsJws = parser.parseClaimsJws(token); //解析token //获取解析的token中相关数据
Claims body = claimsJws.getBody(); //获取token中用户数据
String subject = body.getSubject(); //获取subject中数据
String v1 = body.get("k1", String.class); //获取claims中存储的map中数据 return new ResultVo(ResStatus.OK, "success", null);
} catch (Exception e) {
return new ResultVo(ResStatus.NO, "登陆过期,请重新登陆!", null);
}
}

拦截器校验 token

请求非常多,一个一个地进行校验不现实,所以需要统一校验 token,此时可以使用拦截器。

在拦截器的预处理方法中进行 token 统一校验,校验通过则放行请求,不通过则做出相关响应提示。

在拦截器统一校验 token 后,在控制器中做过校验的请求就不需要再次进行校验了,直接写业务逻辑即可。

拦截器类:

/**
* 拦截器
*/
@Component
public class CheckTokenInterceptor implements HandlerInterceptor { /**
* 预处理方法,拦截请求,决定是否放行。
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //获取token并校验
String token = request.getParameter("token");
System.out.println("preHandle ========> token = " + token);
if (token == null) {
//没有token
ResultVo resultVo = new ResultVo(ResStatus.NO, "请先登录!", null);
doResponse(response, resultVo);
} else {
//获取jwt解析器
JwtParser parser = Jwts.parser();
parser.setSigningKey("luis333"); //之前加密时的加密密码,一致才能解析成功
try {
//如果token正确(密码正确,且在有效期内)则正常执行,否则抛出异常
Jws<Claims> claimsJws = parser.parseClaimsJws(token); //解析token
return true;
} catch (ExpiredJwtException e) {
ResultVo resultVo = new ResultVo(ResStatus.NO, "token已过期!", null);
doResponse(response, resultVo);
} catch (UnsupportedJwtException e) {
ResultVo resultVo = new ResultVo(ResStatus.NO, "异常token!", null);
doResponse(response, resultVo);
} catch (Exception e) {
ResultVo resultVo = new ResultVo(ResStatus.NO, "请先登录!", null);
doResponse(response, resultVo);
}
}
return false;
} /**
* 响应流程封装
*/
private void doResponse(HttpServletResponse response, ResultVo resultVo) throws IOException {
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
PrintWriter out = response.getWriter();
String s = new ObjectMapper().writeValueAsString(resultVo);
out.print(s);
out.flush();
out.close();
}
}

拦截器配置类:

/**
* 拦截器配置类(SpringBoot中配置拦截器)
*/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer { //注意此处需要实现WebMvcConfigurer接口 @Autowired
private CheckTokenInterceptor checkTokenInterceptor; @Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(checkTokenInterceptor) //添加拦截器
.addPathPatterns("/shopcart/**") //添加要拦截的请求
.addPathPatterns("/orders/**")
.excludePathPatterns("/user/**"); //放行的请求
}
}

常用请求头传递 token

前端但凡访问受限资源,都必须携带 token 发起请求;token 可以通过请求行(params)、请求头(headers)以及请求体(data)传递,但是习惯性使用 headers 传递!

在实际开发中,发送请求时,我们一般都是在请求头中来传递 token,通过自定义请求头数据,传递 token 到后端。

前端使用自定义请求头数据传递 token 示例:(注意请求头传递数据关键字 headers,带 s)

<script type="text/javascript">

    var baseUrl = "http://localhost:8080";
var vm = new Vue({
el: "#container",
data: {
token: ""
},
//钩子函数,生命周期函数,直接定义!
created: function() {
//钩子函数,data数据初始化之后自动调用
console.log("========> created method execute !") var token = getCookieValue("token");
this.token = token;
console.log("token = " + token); axios({
url: baseUrl + "/shopcart/list",
method: "get",
headers: {token: this.token} //自定义请求头数据传递token
}).then(function(res) {
console.log(res.data);
});
}
});
</script>

注意:使用自定义请求头传递数据时,浏览器会自动发起一次预检请求(method="OPTIONS"),来监测环境是否畅通,如果服务器正常响应,则后续请求才可正常发起。

所以,当使用拦截器统一校验 token ,并且使用自定义请求头传递 token 时,需要在拦截器中放行浏览器自动发起的预检请求,即放行 OPTIONS 请求方式的预检请求。

主要注意点:

拦截器代码示例:

/**
* 拦截器
*/
@Component
public class CheckTokenInterceptor implements HandlerInterceptor { /**
* 预处理方法,拦截请求,决定是否放行。
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { //放行浏览器自动发起的预检请求(请求方式为OPTIONS)
String method = request.getMethod();
System.out.println("method ========> " + method);
if ("OPTIONS".equalsIgnoreCase(method)) {
return true;
} //从请求头中获取token并校验
String token = request.getHeader("token");
System.out.println("preHandle ========> token = " + token);
if (token == null) {
//没有token
ResultVo resultVo = new ResultVo(ResStatus.NO, "请先登录!", null);
doResponse(response, resultVo);
} else {
//获取jwt解析器
JwtParser parser = Jwts.parser();
parser.setSigningKey("luis333"); //之前加密时的加密密码,一致才能解析成功
try {
//如果token正确(密码正确,且在有效期内)则正常执行,否则抛出异常
Jws<Claims> claimsJws = parser.parseClaimsJws(token); //解析token
return true;
} catch (ExpiredJwtException e) {
ResultVo resultVo = new ResultVo(ResStatus.NO, "token已过期!", null);
doResponse(response, resultVo);
} catch (UnsupportedJwtException e) {
ResultVo resultVo = new ResultVo(ResStatus.NO, "异常token!", null);
doResponse(response, resultVo);
} catch (Exception e) {
ResultVo resultVo = new ResultVo(ResStatus.NO, "请先登录!", null);
doResponse(response, resultVo);
}
}
return false;
} /**
* 响应流程封装
*/
private void doResponse(HttpServletResponse response, ResultVo resultVo) throws IOException {
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
PrintWriter out = response.getWriter();
String s = new ObjectMapper().writeValueAsString(resultVo);
out.print(s);
out.flush();
out.close();
}
}

使用 JWT 生成 token的更多相关文章

  1. 国服最强JWT生成Token做登录校验讲解,看完保证你学会!

    转载于:https://blog.csdn.net/u011277123/article/details/78918390 Free码农 2017-12-28 00:08:02 JWT简介 JWT(j ...

  2. 利用jwt生成token,用于http请求身份验证

    前段时间在做移动端接口过程中,考虑到安全性,所有移动端发送请求(除了登录请求)过程中进行token有效验证. 1.利用jwt生成token a.导入jwt相关包 <!-- jwt --> ...

  3. 使用 JWT 生成 Token 代码示例

    JSON Web Token,简称 JWT, 是一个开放的标准(RFC 7519),它定义了以一种紧凑的.自包含的 JSON 对象在各方之间安全传输信息的方式.该信息含有数字签名,可以被验证和信任. ...

  4. Token_使用JWT生成token

    1.token三部分 header   { "typ": "JWT", "alg": "HS256"   } paylo ...

  5. JWT生成token及过期处理方案

    业务场景 在前后分离场景下,越来越多的项目使用token作为接口的安全机制,APP端或者WEB端(使用VUE.REACTJS等构建)使用token与后端接口交互,以达到安全的目的.本文结合stacko ...

  6. tp5使用jwt生成token,做api的用户认证

    首先 composer 安装  firebase/php-jwt github:https://github.com/firebase/php-jwt composer require firebas ...

  7. JWT生成token

    1.JWT简介 JSON Web Token 简称JWT.一个JWT实际上就是一个字符串,它由三部分组成,头部.载荷与签名.JWT生成的token是这样的 2.Json Web Token(JWT)生 ...

  8. .NET6 JWT(生成Token令牌)

    一.Net 6环境下的.net core项目里如何使用JWT. 第一步,在Nuget引入JWT.Microsoft.AspNetCore.Authentication.JwtBearer这两个NuGe ...

  9. JWT生成Token做登录校验

    一.JWT的优点 1.服务端不需要保存传统会话信息,没有跨域传输问题,减小服务器开销. 2.jwt构成简单,占用很少的字节,便于传输. 3.json格式通用,不同语言之间都可以使用. 二.使用JWT进 ...

  10. JSON Web Token (JWT)生成Token及解密实战。

    昨天讲解了JWT的介绍.应用场景.优点及注意事项等,今天来个JWT具体的使用实践吧. 从JWT官网支持的类库来看,jjwt是Java支持的算法中最全的,推荐使用,网址如下. https://githu ...

随机推荐

  1. 【AGC】使用云调试优惠扣费、华为设备上触发崩溃、无法下载华为应用市场问题小结

    ​ 1.使用云调试剩余优惠时长还剩300分钟,但还会扣费的情况. 问题描述:用户的云调试账户显示剩余优惠时长还有300分钟,但在使用云调试的过程中,还是产生了扣费的情况. ​ 解决方案: 当开发者成功 ...

  2. k8s 网络持久化存储之StorageClass(如何一步步实现动态持久化存储)

    StorageClass的作用: 创建pv时,先要创建各种固定大小的PV,而这些PV都是手动创建的,当业务量上来时,需要创建很多的PV,过程非常麻烦. 而且开发人员在申请PVC资源时,还不一定有匹配条 ...

  3. 大数据Hadoop平台安装及Linux操作系统环境配置

    配置 Linux 系统基础环境 查看服务器的IP地址 设置服务器的主机名称 hostnamectl set-hostname hadoop hostname可查看 绑定主机名与IP 地址 vim /e ...

  4. 使用脚本在FTP上传、下载文件

    由于最近勒索病毒变种又一次爆发,公司内部封锁了TCP 445端口.导致原来通过文件共享的方式上传下载的计划任务无法执行.所以,我开设了FTP服务器来完成这个工作. 关于如何建立FTP服务器,请看这里 ...

  5. dotnet 为大型应用接入 ApplicationStartupManager 启动流程框架

    对于大型的应用软件,特别是客户端应用软件,应用启动过程中,需要执行大量的逻辑,包括各个模块的初始化和注册等等逻辑.大型应用软件的启动过程都是非常复杂的,而客户端应用软件是对应用的启动性能有所要求的,不 ...

  6. Kubernetes实践技巧:集群升级k8s版本

    更新证书 使用 kubeadm 安装 kubernetes 集群非常方便,但是也有一个比较烦人的问题就是默认的证书有效期只有一年时间,所以需要考虑证书升级的问题,本文的演示集群版本为 v1.16.2 ...

  7. 使用kubeoperator自带的nginx-ingress-controller设置服务的ingress规则进行访问

    情况说明 当使用kubeoperator安装k8s集群的时候,在组件设置部分选择的ingress 类型是nginx-ingress yaml文件 k8s集群安装后,可以在节点的master主机的这个目 ...

  8. MongoDB 的用户和角色权限

    副本和分片集群的安全设置参考这个:高级:https://files.cnblogs.com/files/sanduzxcvbnm/mongodb_advance.pdf 默认情况下,MongoDB实例 ...

  9. (编程语言界的丐帮 C#).NET MD5 HASH 哈希 加密 与JAVA 互通

    一.注意要点 1:输入字符串的的编码双方保持统一,如:UTF8: 2:HASH计算输出结果 byte[] 数组转String 时,编码要统一,如:转16进制小写字符串.当然也可以转Base64. 3: ...

  10. JavaScript根据参数获取url中参数名的值

    //假设ulr如下var localhost="http://127.0.0.1?name=tom&sex=男&id=1";//正则方法封装function Get ...