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

依赖

<!-- JWT token -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.2.0</version>
</dependency>

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

生成JWT

public static String tokencreate(Object de){
//当前时间
Date now=new Date();
//1小时
long last=now.getTime()+120*1000;
//过期时间2分钟
Date expir=new Date(last);

JwtBuilder builder= Jwts.builder()
/*.setId("1")*/
//存放的内容
/*.setSubject(usde)*/
//生成的时间
.setIssuedAt(now)
//过期时间
.setExpiration(expir)
//可以存对象
.claim("login",de)
//加密方式
.signWith(SignatureAlgorithm.HS256,"xianxian");
//生成token
String token= builder.compact();
return token;
}

解析JWT

主要解析JWT代码

Claims cl=Jwts.parser().setSigningKey("xianxian").parseClaimsJws(oldtoken).getBody();

当JWT错误或者过期时则会报错

@Test
public void decrypt() throws JsonProcessingException {
//原来生成的token
String oldtoken="eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIxIiwic3ViIjoie1wiaWRcIjoxLFwibmFtZVwiOlwi5qCI5LiJXCIsXCJiaXJ0aGRhdGVcIjoxNjM4NDk1MzEzNzc0fSIsImlhdCI6MTYzODQ5NTMxMywiZXhwIjoxNjM4NDk4OTEzLCJsb2dpbiI6eyJpZCI6MSwibmFtZSI6IuagiOS4iSIsImJpcnRoZGF0ZSI6MTYzODQ5NTMxMzc3NH19.tQqtSVqgwLFcuuKn1kv_I4B0_ymBY-LUPHz8Z2nPP7U";
//setSigningKey(加密方式的key ) parseClaimsJws(原来生成的token)
Claims cl=Jwts.parser().setSigningKey("xianxian").parseClaimsJws(oldtoken).getBody();
LinkedHashMap lmap= (LinkedHashMap) cl.get("login");
System.out.println(cl.get("login"));
System.out.println("id:"+lmap.get("id"));
System.out.println("iat:"+cl.get("iat"));
System.out.println(cl);
//获取Subject
System.out.println("sub:"+cl.getSubject());
ObjectMapper obj=new ObjectMapper();
//把subj里面的转换成对象
Userdemo us=obj.readValue(cl.getSubject(),Userdemo.class);
System.out.println(us);
System.out.println(us.getBirthdate());
}

跨域和拦截器配置类

package com.it.seckill.config;
import com.it.seckill.Interceptor.LoginInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* @Author: 羡羡
* @Date: 2021/12/02/10:39
*/
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired
LoginInterceptor login;
/**
* 跨域
* @param registry
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
//所有
registry.addMapping("/**")
//支持的方法
/*.allowedOrigins("*")*/
.allowedOriginPatterns("*")
//支持的方法
.allowedMethods("GET","PUT","DELETE","POST","HEAD","OPTIONS")
//证书
.allowCredentials(true)
//超时
.maxAge(3600)
//允许头
.allowedHeaders("*");
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
//增加拦截器
registry.addInterceptor(login)
//拦截的路径
.addPathPatterns("/**")
//排除的路径
.excludePathPatterns("/selogin");
}
}

拦截器

拦截器不拦截登入 但是会解析请求头

package com.it.seckill.Interceptor;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
* @Author: 羡羡
* @Date: 2021/12/03/10:03
*/
@Component
public class LoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String method=request.getMethod();
if(!method.equalsIgnoreCase("GET") && !method.equalsIgnoreCase("POST")){
return true;
}
System.out.println("login标志!");
//会的前台的请求头token
String token=request.getHeader("token");
//解析JWT
Claims cl= Jwts.parser().setSigningKey("xianxian").parseClaimsJws(token).getBody();
System.out.println("检查Token:"+token);
//判断拦截
return true;
}

@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}

@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}

控制器

登入成功时就会生成token令牌 发送到前台

package com.it.seckill.controller;
/**
* @Author: 羡羡
* @Date: 2021/12/02/19:39
*
* 连接了数据库
*/
@RestController
public class SeckillControllerSQL {

@Autowired
UserService use;

@Autowired
GoodsService gos;

/**
* 用户登入
* @param us
* @param pa
* @return
*/
@RequestMapping("/selogin")
public JsonResult selogin(String us,String pa){
JsonResult js;
User user=new User();
user.setUsname(us);
user.setUspass(pa);
User usevi=use.login(user);
if(usevi!=null){
//生成令牌
String token=TokenTools.tokencreate(usevi);
js=new JsonResult(200,"登入成功!",token);
}else{
js=new JsonResult(500,"登入失败!");
}
return js;
}



/**
* 查询所有商品
* @return
*/
@RequestMapping("/seckillall")
public JsonResult seall(){
List lis=gos.seall();
JsonResult js=new JsonResult(200,"成功!",lis);
return js;
}
}

前台登入

当登入成功后就会获取token 把token保存到 localStorage中

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<h1>登入页</h1>
UserName:<input type="text" name="usname" id="na" required/><br /><br />
Password:<input type="password" name="password" id="pwd" required/><br /><br />
<button type="submit" name="">提交</button>
</body>
<script>
$(function(){
$("button").click(function(){
var ac=$("#na").val();
var pa=$("#pwd").val();
var data ={
"us":ac,
"pa":pa
}
$.post("http://127.0.0.1:8090/selogin",data,function(da){
//登入成功
if(da.code == "200"){
localStorage.setItem("mstoken",da.data);
$("a").eq(0).text("退出登入");
//加载首页
$(".app").load("main.html");
}else{
alert("登入失败!");
}
})
})
})
</script>
</html>

前台显示内容

加载完界面后 取出存到浏览器的localStorage 发送请求到后台 带一个tonken

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<h1>主页面</h1>
<div id="cd1">
<table border="1px" style="text-align: center;">
</table>
</div>
</body>
<script>
$(function () {
//取出token
var mstoken=localStorage.getItem("mstoken");
$.ajax({
//请求头
headers:{
token:mstoken
},
url: "http://127.0.0.1:8090/seckillall",
type: "POST",
success: function (da) {
if(da.code=="500"){
alert("服务器错误!");
}else{
var tr="<tr><td>商品名称</td><td>商品数量</td><td>开抢时间</td></tr>";
for(var i=0;i<da.data.length;i++){
tr+="<tr><td>"+da.data[i].name+"</td><td>"+da.data[i].number+"</td><td>"+da.data[i].startTime+"</td></tr>";
}
$("#cd1 table").html(tr);
}
},
});
});
</script>
</html>