简单说明:最近在搞权限这一块的东西,需要用到jwt进行token认证,才有了如下的demo演示   具体细节可以看gitbug,噗,不是bug是hub  github地址:https://github.com/xuchao6969/jwt_demo  点击前边的gitbug也可以哦

项目是springboot+thymeleaf+mybatis+mysql搭建的

//pom核心依赖
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
//application.yml的核心配置
#token有效期 单位ms
expire_time: 9000000 #token加密secret
token_secret: jwtsecret

token的工具类,包括生成签名、校验、解析等方法

package com.xc.jwt_demo.util;

import java.util.Date;
import java.util.HashMap;
import java.util.Map; import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT; public class JwtTokenUtil { /**
* 生成签名,过期时间可以从配置文件里读取 具体看方法调用处
* @param **username**
* @param **password**
* @return
*/
public static String sign(String username, String userId,Long expiretime,String secret) {
try {
// 设置过期时间
Date date = new Date(System.currentTimeMillis() + expiretime);
// 私钥和加密算法
Algorithm algorithm = Algorithm.HMAC256(secret);
// 设置头部信息
Map<String, Object> header = new HashMap<>(2);
header.put("Type", "Jwt");
header.put("alg", "HS256");
// 返回token字符串
return JWT.create()
.withHeader(header)
.withClaim("loginName", username)
.withClaim("userId", userId)
.withExpiresAt(date)
.sign(algorithm);
} catch (Exception e) {
e.printStackTrace();
return null;
}
} /**
* 检验token是否正确
* @param **token**
* @return
*/
public static boolean verify(String token,String secret){
try {
Algorithm algorithm = Algorithm.HMAC256(secret);
JWTVerifier verifier = JWT.require(algorithm).build();
@SuppressWarnings("unused")
DecodedJWT jwt = verifier.verify(token);
return true;
} catch (Exception e){
return false;
}
} /**
* 从token中获取username信息
* @param **token**
* @return
*/
public static String getUserName(String token){
try {
DecodedJWT jwt = JWT.decode(token);
return jwt.getClaim("loginName").asString();
} catch (JWTDecodeException e){
e.printStackTrace();
return null;
}
} /**
* token是否过期
* @param token
*/
public static Boolean checkExpire(String token) {
try {
DecodedJWT jwt = JWT.decode(token);
//获取token过期时间
Date expiretime = jwt.getExpiresAt();
String etStr = String.valueOf(expiretime.getTime());
//获取系统当前时间
String nowTime = String.valueOf(System.currentTimeMillis());
//如果系统当前时间超过token过期时间返回false
if(nowTime.compareTo(etStr)>0){
return false;
}
return true;
} catch (JWTDecodeException e){
e.printStackTrace();
}
return true;
} }

JwtTokenUtil.java

token拦截器,针对所有的请求进行token认证 也是核心

package com.xc.jwt_demo.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor; import com.xc.jwt_demo.util.JwtTokenUtil; @Component
public class TokenInterceptor implements HandlerInterceptor {
private static final Logger logger = LoggerFactory.getLogger(TokenInterceptor.class); //从配置文件application.yml进行加载
@Value("${token_secret}")
private String secret; @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object)
throws Exception {
String str = request.getMethod();
if (str.equals("OPTIONS")) {
response.setStatus(HttpServletResponse.SC_OK);
return true;
}
response.setCharacterEncoding("utf-8");
String token = request.getHeader("token");
if (null != token) {
//校验token是否过期
boolean result = JwtTokenUtil.verify(token, secret);
if (result) {
logger.info("通过拦截器");
return true;
}
}
logger.info("认证失败");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("Token不存在或者已失效");
return false;
}
}

TokenInterceptor.java

token拦截器的配置,主要用来配置不需要拦截路径,比如登录...

package com.xc.jwt_demo.config;

import java.util.ArrayList;
import java.util.List; import com.xc.jwt_demo.interceptor.TokenInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration
public class InterceptorConfig implements WebMvcConfigurer{ private TokenInterceptor tokenInterceptor; public InterceptorConfig(TokenInterceptor tokenInterceptor) {
this.tokenInterceptor = tokenInterceptor;
} @Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(tokenInterceptor)
//拦截所有的请求
.addPathPatterns("/**")
//放开请求
.excludePathPatterns("/sys/test","/sys/login","/sys/doLogin","/js/**");
} }

InterceptorConfig.java

好了,下边的一坨坨代码就是常规的三层业务了,可以参考看一下UserServiceImpl里的生成token 解析token的调用,其他没啥大的价值  另外 我的token是存放在数据库的

package com.xc.jwt_demo.controller;

import java.io.IOException;
import java.util.Map; import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import com.xc.jwt_demo.entity.User;
import com.xc.jwt_demo.service.UserService;
import com.xc.jwt_demo.util.JsonUtil;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*; @Controller
@RequestMapping("/sys")
public class LoginController { @Resource
private UserService userService; //测试页面
@RequestMapping("/test")
public String testThymeleaf(ModelMap model) {
User user = new User();
user.setUsername("二叔");
user.setMobile("911");
model.addAttribute("user", user);
return "/viewTest";
} //登录页面
@RequestMapping("/login")
public String login(ModelMap model) {
return "/login";
} @RequestMapping(value = "/doLogin")
@ResponseBody
public Integer login(User user) {
Map<String, Object> resultMap = userService.login(user.getUsername(),user.getPassword());
Integer code = (Integer) resultMap.get("code");
return code;
} //使用postman或者restclient进行token测试
@RequestMapping("/tokenTest")
public void TokenTest(HttpServletRequest request,HttpServletResponse response) throws IOException {
String token = request.getHeader("token");
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
response.getWriter().write("认证成功 Token是:"+token);
}
}

LoginController.java

package com.xc.jwt_demo.service;

import java.util.Map;

public interface UserService {

    Map<String, Object> login(String username, String password);

}

UserService.java

package com.xc.jwt_demo.service.impl;

import java.util.HashMap;
import java.util.Map; import com.xc.jwt_demo.dao.UserDao;
import com.xc.jwt_demo.entity.User;
import com.xc.jwt_demo.service.UserService;
import com.xc.jwt_demo.util.JwtTokenUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.beans.factory.annotation.Value; @Service("userService")
public class UserServiceImpl implements UserService { private static final Logger logger = LoggerFactory.getLogger(UserServiceImpl.class); //从配置文件application.yml读取token有效期时间 单位ms
@Value("${expire_time}")
private Long expiretime; //读取加密的secret
@Value("${token_secret}")
private String secret; @Autowired
private UserDao dao; @Override
public Map<String, Object> login(String username,String password) {
Map<String, Object> map = new HashMap<>();
User userObj = dao.getUserByUserName(username);
//判断用户是否存在
if(null == userObj){
map.put("code", 0);//用户不存在
return map;
}
//判断密码是否正确
if(! password.equals(userObj.getPassword())){
map.put("code", -1);//密码错误
return map;
}
map.put("code", 1);//用户存在
String tokenObj = userObj.getToken();
//用户token不存在就创建token
if(null == tokenObj || "".equals(tokenObj)){
String token = JwtTokenUtil.sign(userObj.getUsername(),userObj.getUserId(),expiretime,secret);
logger.info("-----------创建token-------: "+ token);
Map<String, Object> paraMap = new HashMap<>();
paraMap.put("token", token);
paraMap.put("userId", userObj.getUserId());
dao.addToken2User(paraMap);
map.put("token", token);
}else{
//取出用户token
String token = userObj.getToken();
logger.info("------存在的token-----: "+ token);
//判断token是否过期 不过期返回,过期 新建token返回并插入数据库
if(JwtTokenUtil.checkExpire(token)){
logger.info("-------token存在且有效------: "+ token);
map.put("token", token);
}else{
String tokenStr = JwtTokenUtil.sign(userObj.getUsername(),userObj.getUserId(),expiretime,secret);
logger.info("------token重新生成-----: "+ tokenStr);
Map<String, Object> paraMap = new HashMap<>();
paraMap.put("token", tokenStr);
paraMap.put("userId", userObj.getUserId());
dao.addToken2User(paraMap);
map.put("token", tokenStr);
}
}
map.put("userId", userObj.getUserId());
map.put("username", userObj.getUsername());
return map;
} }

UserServiceImpl.java

package com.xc.jwt_demo.dao;

import org.apache.ibatis.annotations.Mapper;
import com.xc.jwt_demo.entity.User;
import java.util.Map; @Mapper
public interface UserDao {
User getUserByUserName(String username); void addToken2User(Map<String, Object> map);
}

UserDao.java

package com.xc.jwt_demo.entity;

import lombok.Data;

@Data
public class User { private String userId;
private String username;
private String password;
private String email;
private String mobile;
private String status;
private String createBy;
private String createTime;
private String lastUpdateBy;
private String lastUpdateTime;
private String department;
private String realName;
private String establishVest;
private String delFlag;
private String token; }

User.java

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xc.jwt_demo.dao.UserDao">
<resultMap id="UserResultMap" type ="com.xc.jwt_demo.entity.User">
<id property="userId" column="user_id" />
<result property="username" column="username" />
<result property="password" column="password" />
<result property="email" column="email" />
<result property="mobile" column="mobile" />
<result property="status" column="status" />
<result property="createBy" column="create_by" />
<result property="createTime" column="create_time" />
<result property="lastUpdateBy" column="last_update_by" />
<result property="lastUpdateTime" column="last_update_time" />
<result property="department" column="department" />
<result property="realName" column="real_name" />
<result property="establishVest" column="establish_vest" />
<result property="delFlag" column="del_flag" />
<result property="token" column="token" />
</resultMap> <sql id="tableName">t_user</sql> <update id="addToken2User" parameterType="java.util.Map">
update <include refid="tableName" /> set token = #{token} where user_id = #{userId}
</update> <select id="getUserByUserName" parameterType="String" resultMap="UserResultMap">
select * from <include refid="tableName" /> where username = #{username}
</select>
</mapper>

UserMapper.xml

另外说一点,很重要,在html页面中必须加入<link rel=“shortcut icon” href="#" />  否则会在测试的时候会出现 favicon.ico不存在的问题,从而导致测试失败 vue的话也会有类似的问题

下边是测试

首先不带token访问tokenTest页面

后台打印

然后登陆 获取token

后台打印

然后 把token粘到postman或者restClient中  设置好header token再次访问

后台打印

最终结果

使用jwt进行token认证的更多相关文章

  1. token 与 基于JWT的Token认证

    支持跨域访问,无状态认证 token特点 支持跨域访问: Cookie是不允许垮域访问的,这一点对Token机制是不存在的,前提是传输的用户认证信息通过HTTP头传输 无状态(也称:服务端可扩展行): ...

  2. 基于JWT的Token认证机制及安全问题

    [干货分享]基于JWT的Token认证机制及安全问题 https://bbs.huaweicloud.com/blogs/06607ea7b53211e7b8317ca23e93a891

  3. iOS 开发之基于JWT的Token认证机制及解析

    在移动端和服务端通信中,一般有两种认证方式:token 和 session. 1.session/cookie 认证机制: 在服务端创建一个Session对象,同时在客户端的浏览器端创建一个Cooki ...

  4. tp5.0使用JWT完成token认证技术

    1.安装 composer require firebase/php-jwt 2.封装(在框架根目录extend下新建Token.php) 复制代码 <?php use Firebase\JWT ...

  5. Django+JWT实现Token认证

    对外提供API不用django rest framework(DRF)就是旁门左道吗? 基于Token的鉴权机制越来越多的用在了项目中,尤其是对于纯后端只对外提供API没有web页面的项目,例如我们通 ...

  6. JWT实现token认证

    演变 1.1 有状态服务 在原来的单体系统中,有状态服务,即服务端需要记录每次会话的客户端信息,从而识别客户端身份,根据用户身份进行请求的处理,session+cookie.在如今的大多数分布式系统中 ...

  7. 简单说说基于JWT的token认证方式

    一.什么是认证 好多人不知道什么是认证,认证,其实就是服务端确认用户身份.Http协议是无状态的,客户端发送一条请求,服务端返回一条响应,二者就算做成一单买卖,一拍两散.在很久以前,互联网所能提供的服 ...

  8. 使用JWT实现Token认证

    为什么使用JWT? 随着技术的发展,分布式web应用的普及,通过session管理用户登录状态成本越来越高,因此慢慢发展成为token的方式做登录身份校验,然后通过token去取redis中的缓存的用 ...

  9. 基于JWT的token认证机制

    1. 一个JWT实际上就是一个字符串,由三部分组成 头部,载荷,签名 头部:事描述类型,签名,算法等 可以被表示成一个JSON对象 载荷:存放有效信息的地方 包含三个部分 (1)标准注册中的声明-建议 ...

随机推荐

  1. Python3-内置类型-集合类型

    Python3中的集合类型主要有两种 set 可变集合 可添加和删除元素,它是不可哈希的,因此set对象不能用作字典的键或另一个元素的集合 forzenset 不可变集合 正好与set相反,其内容创建 ...

  2. CLR垃圾收集器

    CLR GC是一种引用跟踪算法,大致步骤如下: 1.暂停进程中所有的线程: 2.标记阶段,遍历堆中的所有对象,标记为删除,然后检查所有活动根,如果有引用对象,就标记那个对象可达,否则不可达: 3.GC ...

  3. python fabric安装

    1 安装epel wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo 2 安装pip yum i ...

  4. 001_Linux常用命令之ls命令

    1. 认识Linux系统目录结构 /bin 可执行文件所在目录 /media 挂载设备媒体,u盘,光驱等 /mnt 该目录主要是为了让用户挂在别的文件系统(挂在自己的u盘) /usr unix sys ...

  5. 全宇宙首本 VS Code 中文书,来了!

    大家好!我是韩骏,VS Code 中文社区创始人,VS Code 的代码贡献者.2013 年,毕业于上海交通大学软件学院,现在是微软开发平台事业部的软件工程师.写过 20 多款 VS Code 插件, ...

  6. ASP.NET 开源导入导出库Magicodes.IE 多Sheet导入教程

    多Sheet导入教程 说明 本教程主要说明如何使用Magicodes.IE.Excel完成多个Sheet数据的Excel导入. 要点 多个相同格式的Sheet数据导入 多个不同格式的Sheet数据导入 ...

  7. 使用Fiddler模拟Post请求

    做了一个动态的GIF来做演示,应该更加直观些. (完)

  8. 多核CPU硬件架构介绍

    转自:http://book.51cto.com/art/201004/197196.htm SISD.MIMD.SIMD.MISD计算机的体系结构 1. 计算平台介绍 Flynn于1972年提出了计 ...

  9. vx小程序(1)

    一.程序配置 app.json 1. pages字段——用于描述当前小程序的页面路径. 2.window字段——定义小程序所有页面的顶部背景颜色,文字颜色等. 注意:可以在pages/logs目录下的 ...

  10. 「疫期集训day10」玫瑰

    不管我们在怎么抵抗,德国都已经败了----失守苏瓦松后绝望中的德国兵 (貌似今天的题记和内容毫无关系) 觉得以后还是不要抱怨考试失误了,感觉没啥大用 T1暴搜/状压(然俄一看题很像刚写过的二分答案,上 ...