SpringBoot学习- 4、整合JWT
1、Json web token(JWT)是为了网络应用环境间传递声明而执行的一种基于JSON的开发标准(RFC 7519),该token被设计为紧凑且安全的,特别适用于分布式站点的单点登陆(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。JWT听起来很复杂,其实原理很简单,比如我们可以自己生成一个guid字符串+key+附加信息加密作为token传递到客户端也能达到同样目的。
2、pom.xml增加如下代码来添加JWT依赖包
<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.9.0</version>
</dependency>
3、IDEA2019.3版本中文乱码,设置UTF-8不起作用,修改字体如下
以下几部分内容主要参考
https://www.cnblogs.com/30go/p/10963924.html
https://www.jianshu.com/p/9af8612f6aef
4、在Utils文件夹下增加TokenUtil
RefreshToken暂不使用
package com.jgui.utils; import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;
import com.jgui.domain.JUser; import java.util.Date; /**
* @Author: zhaogaojian
* @Description:
* @Date: Created in 2020/1/722:13
*/
public class TokenUtil {
private static final long TOKEN_EXPIRE_TIME= 30*60*1000;//超时时间30分钟
private static final long REFRESH_TOKEN_EXPIRE_TIME= 15*24*60*1000;//超时时间15天
private static final String TOKEN_SECRET="jguiafadfiierpewirpew8908ewrq";//秘钥
private static final String ISSUER="jgadmin";//签发人
/**
* 签名生成
* @param user
* @return
*/
public static String sign(JUser user){ String token = "";
try {
Date expiresAt = new Date(System.currentTimeMillis() + TOKEN_EXPIRE_TIME);
Date now = new Date();
token = JWT.create()
.withIssuer(ISSUER)
.withClaim("username", user.getUsername())
.withExpiresAt(expiresAt)
.withIssuedAt(now)
// 使用了HMAC256加密算法。
.sign(Algorithm.HMAC256(TOKEN_SECRET));
} catch (Exception e){
e.printStackTrace();
}
return token; }
/**
* 签名验证
* @param token
* @return
*/
public static boolean verify(String token){
try {
JWTVerifier verifier = JWT.require(Algorithm.HMAC256(TOKEN_SECRET)).withIssuer("auth0").build();
DecodedJWT jwt = verifier.verify(token);
System.out.println("认证通过:");
System.out.println("issuer: " + jwt.getIssuer());
System.out.println("username: " + jwt.getClaim("username").asString());
System.out.println("签发时间:" + jwt.getIssuedAt());
System.out.println("过期时间:" + jwt.getExpiresAt());
return true;
} catch (Exception e){
return false;
} }
/**
* 从token获取username
*/
public static String getUsername(String token){
try{
return JWT.decode(token).getClaim("username").asString();
}catch(Exception ex){
ex.printStackTrace();
}
return "";
}
}
package com.jgui.utils; import java.util.UUID; /**
* @Author: zhaogaojian
* @Description:
* @Date: Created in 2020/1/722:50
*/
public class StringUtil {
public static String GetUUIDString()
{
return UUID.randomUUID().toString();
} }
5、在Controller下增加LoginController
package com.jgui.controller; import com.jgui.dao.JUserDao;
import com.jgui.domain.JUser;
import com.jgui.utils.StringUtil;
import com.jgui.utils.TokenUtil;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit; /**
* @Author: zhaogaojian
* @Description:
* @Date: Created in 2020/1/722:38
*/
@RestController
public class LoginController {
@Resource
private JUserDao userDao;
@GetMapping("/login")
public Map<String,Object> login(@RequestParam String username, @RequestParam String password) { if("zhangsan".equals(username) && "123".equals(password)){
JUser user=new JUser();
user.setUsername("zhangsan");
user.setRealname("张三");
Map<String,Object> map = new HashMap<>();
//生成token
String token = TokenUtil.sign(user);
String refreshToken = StringUtil.GetUUIDString();
if(token != ""){
map.put("code", "10000");
map.put("message", "认证成功");
map.put("token", token);
map.put("refreshtoken", refreshToken);
return map;
}
}
Map<String,Object> map = new HashMap<>();
map.put("code", "10001");
map.put("message", "认证失败");
map.put("token", "");
map.put("refreshtoken", "");
return map;
}
}
6、在Interceptor目录下增加TokenInterceptor
package com.jgui.interceptor;
import com.jgui.utils.TokenUtil;
import net.minidev.json.JSONObject;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
/**
* @Author: zhaogaojian
* @Description:
* @Date: Created in 2020/1/723:12
*/
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
@Component
public class TokenInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler)throws Exception{ if(request.getMethod().equals("OPTIONS")){
response.setStatus(HttpServletResponse.SC_OK);
return true;
}
response.setCharacterEncoding("utf-8");
String token = request.getHeader("token");
if(token != null){
boolean result = TokenUtil.verify(token);
if(result){
System.out.println("通过拦截器");
return true;
}
}
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json; charset=utf-8");
PrintWriter out = null;
try{
JSONObject json = new JSONObject();
json.put("success","false");
json.put("msg","认证失败,未通过拦截器");
json.put("code","10003");
response.getWriter().append(json.toJSONString());
System.out.println("认证失败,未通过拦截器");
}catch (Exception e){
e.printStackTrace();
response.sendError(500);
return false;
}
return false; } }
7、在config下增加InterceptorConfig
package com.jgui.config; /**
* @Author: zhaogaojian
* @Description:
* @Date: Created in 2020/1/723:15
*/
import com.jgui.interceptor.TokenInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.ArrayList;
import java.util.List;
/**
* 拦截器配置
*/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
private TokenInterceptor tokenInterceptor;
//构造方法
public InterceptorConfig(TokenInterceptor tokenInterceptor){
this.tokenInterceptor = tokenInterceptor;
}
@Override
public void addInterceptors(InterceptorRegistry registry){
List<String> excludePath = new ArrayList<>();
excludePath.add("/login"); //登录 registry.addInterceptor(tokenInterceptor)
.addPathPatterns("/**")
.excludePathPatterns(excludePath);
WebMvcConfigurer.super.addInterceptors(registry);
}
}
8、运行项目
可以发现之前的http://localhost:8080/Hello
访问时会因为拦截器而导致无法访问
login接口因为被排除在拦截器外可以访问
以上内容主要参考
https://www.cnblogs.com/30go/p/10963924.html
https://www.jianshu.com/p/9af8612f6aef
截止目前项目结构如下
SpringBoot学习- 4、整合JWT的更多相关文章
- 玩转 SpringBoot 2 之整合 JWT 上篇
前言 该文主要带你了解什么是 JWT,以及JWT 定义和先关概念的介绍,并通过简单Demo 带你了解如何使用 SpringBoot 2 整合 JWT. 介绍前在这里我们来探讨一下如何学习一门新的技术, ...
- 玩转 SpringBoot 2 之整合 JWT 下篇
前言 在<玩转 SpringBoot 2 之整合 JWT 上篇> 中介绍了关于 JWT 相关概念和JWT 基本使用的操作方式.本文为 SpringBoot 整合 JWT 的下篇,通过解决 ...
- SpringBoot学习之整合Mybatis
本博客使用IDEA开发工具,通过Maven构建SpringBoot项目,初始化项目添加的依赖有:spring-boot-starter-jdbc.spring-boot-starter-web.mys ...
- SpringBoot学习之整合Druid的简单应用
一.Druid介绍 Druid简介 Druid是目前Java语言中最好的数据库连接池之一.结合了 C3P0.DBCP 等 DB 池的优点,同时加入了日志监控.Druid 是一个分布式的.支持实时多维 ...
- SpringBoot学习之整合Swagger
Swagger介绍 1.什么是Swagger 作为后端程序开发,我们多多少少写过几个后台接口项目,不管是编写手机端接口,还是目前比较火热的前后端分离项目,前端与后端都是由不同的工程师进行开发,那么这之 ...
- SpringBoot学习:整合Mybatis,使用HikariCP超高性能数据源
一.添加pom依赖jar包: <!--整合mybatis--> <dependency> <groupId>org.mybatis.spring.boot</ ...
- springboot学习2 整合mybatis
springboot整合mybatis 一.添加mybatis和数据库连接的依赖 <!--整合mybatis--> <dependency> <groupId>or ...
- SpringBoot学习:整合shiro(身份认证和权限认证),使用EhCache缓存
项目下载地址:http://download.csdn.NET/detail/aqsunkai/9805821 (一)在pom.xml中添加依赖: <properties> <shi ...
- SpringBoot学习:整合shiro自动登录功能(rememberMe记住我功能)
首先在shiro配置类中注入rememberMe管理器 /** * cookie对象; * rememberMeCookie()方法是设置Cookie的生成模版,比如cookie的name,cooki ...
- SpringBoot学习:整合shiro(rememberMe记住我后自动登录session失效解决办法)
项目下载地址:http://download.csdn.NET/detail/aqsunkai/9805821 定义一个拦截器,判断用户是通过记住我登录时,查询数据库后台自动登录,同时把用户放入ses ...
随机推荐
- C#24种设计模式汇总
创建型:6 01. 简单工厂模式 08. 工厂方法模式 09. 原型模式 13. 建造者模式 15. 抽象工厂模式 21. 单例模式 结构型:7 06. 装饰模式 07. 代理模式 12. 外观模式 ...
- MySQL的JDBC驱动(8.0版本)
1.引用外部库 mysql-connector-java-8.0.版本的jar 2.jdbc驱动类:com.mysql.jdbc.Driver 改成 com.mysql.cj.jdbc.Drive ...
- python命令行运行django项目, can't open file 'manage.py' 问题解决
找到manage.py的绝对路径即可运行
- 基于云开发开发 Web 应用(二):界面 UI 开发
工作量分析 在我们进行这部分开发的时候,接下来我们需要进行相应的功能安排和分类. 简单看来,我需要开发 3 个页面: 首页:首页负责用户默认访问. 列表页:列表页面则是在搜索过程中,如果有多个结果,则 ...
- Java 8 函数式编程
今天打开Oracle Java官网一看,Java已经更新到 13 了 https://www.oracle.com/technetwork/java/javase/jdk-relnotes-index ...
- 纪中21日c组T2 2117. 【2016-12-30普及组模拟】台风
2117. 台风 (File IO): input:storm.in output:storm.out 时间限制: 1000 ms 空间限制: 262144 KB 具体限制 Goto Proble ...
- Android注册时验证码的生产方法
今天主要是学习了注册时 的验证码的使用. 1.创建了验证码的生成类. 2.通过此生成类,与imageview相互联系起来,实现验证码显示.并添加点击事件,实现验证码的切换. 代码是现成的代码块可以套用 ...
- Origin-作图相关
1.跨越缺失数据连接直线
- centos7虚拟机分配静态IP但是得不到IP、不能上网一种可能的原因和解决办法
1.首先通过ifconfig查看网卡,发现网卡名称为ens33 2. 在/etc/sysconfig/network-scripts/目录下查看网络配置文件 3. 发现有ifcfg-eth0的配置文件 ...
- 【WPF学习】第一章 XAML介绍
XAML(Extensible Application Markup Language的简写,发音为“zammel”)是用于实例化.NET对象的标记语言.尽管XAML是一种应用于诸多不同问题领域的技术 ...