SpringBoot学习足迹

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学习- 3、整合MyBatis

SpringBoot学习- 4、整合JWT的更多相关文章

  1. 玩转 SpringBoot 2 之整合 JWT 上篇

    前言 该文主要带你了解什么是 JWT,以及JWT 定义和先关概念的介绍,并通过简单Demo 带你了解如何使用 SpringBoot 2 整合 JWT. 介绍前在这里我们来探讨一下如何学习一门新的技术, ...

  2. 玩转 SpringBoot 2 之整合 JWT 下篇

    前言 在<玩转 SpringBoot 2 之整合 JWT 上篇> 中介绍了关于 JWT 相关概念和JWT 基本使用的操作方式.本文为 SpringBoot 整合 JWT 的下篇,通过解决 ...

  3. SpringBoot学习之整合Mybatis

    本博客使用IDEA开发工具,通过Maven构建SpringBoot项目,初始化项目添加的依赖有:spring-boot-starter-jdbc.spring-boot-starter-web.mys ...

  4. SpringBoot学习之整合Druid的简单应用

    一.Druid介绍 Druid简介 Druid是目前Java语言中最好的数据库连接池之一.结合了 C3P0.DBCP 等 DB 池的优点,同时加入了日志监控.Druid 是一个分布式的.支持实时多维 ...

  5. SpringBoot学习之整合Swagger

    Swagger介绍 1.什么是Swagger 作为后端程序开发,我们多多少少写过几个后台接口项目,不管是编写手机端接口,还是目前比较火热的前后端分离项目,前端与后端都是由不同的工程师进行开发,那么这之 ...

  6. SpringBoot学习:整合Mybatis,使用HikariCP超高性能数据源

    一.添加pom依赖jar包: <!--整合mybatis--> <dependency> <groupId>org.mybatis.spring.boot</ ...

  7. springboot学习2 整合mybatis

    springboot整合mybatis 一.添加mybatis和数据库连接的依赖 <!--整合mybatis--> <dependency> <groupId>or ...

  8. SpringBoot学习:整合shiro(身份认证和权限认证),使用EhCache缓存

    项目下载地址:http://download.csdn.NET/detail/aqsunkai/9805821 (一)在pom.xml中添加依赖: <properties> <shi ...

  9. SpringBoot学习:整合shiro自动登录功能(rememberMe记住我功能)

    首先在shiro配置类中注入rememberMe管理器 /** * cookie对象; * rememberMeCookie()方法是设置Cookie的生成模版,比如cookie的name,cooki ...

  10. SpringBoot学习:整合shiro(rememberMe记住我后自动登录session失效解决办法)

    项目下载地址:http://download.csdn.NET/detail/aqsunkai/9805821 定义一个拦截器,判断用户是通过记住我登录时,查询数据库后台自动登录,同时把用户放入ses ...

随机推荐

  1. author模块

    一.auth模块简介 1.什么是auth模块,auth模块主要是解决什么问题 还是那句话,‘没有无缘无故的爱,也没有无缘无故的恨   凡是必有因’, 像我们开发一个网站,不可避免的设计网络用户系统,比 ...

  2. DataX的使用——大数据同步技术

    准备工作: 1.视频教学http://113.31.104.47/portal/#/course/dashboard/b34d160db64624732ef152a1118af11a 2.DataX的 ...

  3. Blazor client-side + webapi (.net core 3.1) 添加jwt验证流程(非host)第三章 客户端存储及验证

    准备工作: 安装Nuget包:Blazored.LocalStorge. 这是一个client-side 浏览器存储库,找了非常久. 官方文档中也有一款Microsoft.AspNetCore.Pro ...

  4. Android实战项目——家庭记账本(七)

    今天主要实现了登录注册功能的客户端和服务端,但由于短信接口调用出现问题,导致注册功能还不完整. 截止到今天,APP的功能已经基本完成,后续还会陆陆续续的完善各功能模块与服务端的交互,因为需要和云端关联 ...

  5. Vue 项目中 外部js 如何获取 vue 实例

    1.将main.js 中的 Vue 实例暴露出去 2.在外部js中导入main.js (    import vm from '../main' );

  6. 38.Python自定义计算时间过滤器

    在写自定义的过滤器时,因为django.template.Library.filter()本身可以作为一个装饰器,所以可以使用: register = django.template.Library( ...

  7. 【MVC】Scripts.Render的用法

    一.配置BundleConfig.cs文件 1.首先要在App_Start 里面BundleConfig.cs 文件里面 添加要包含的css文件2.BundleConfig就是一个微软新加的 一个打包 ...

  8. LNMP+HTTPS

    title: "Lnmp + Https" date: 2019-08-28T16:18:20+08:00 draft: true --- 注:我的linux的ip地址为192.1 ...

  9. 【NLP】暑假课作业1 - 中文分词(前向匹配算法实现)

    作业任务: 使用98年人民日报语料库进行中文分词训练及测试. 作业输入: 98年人民日报语料库(1998-01-105-带音.txt),用80%的数据作为训练集,20%的数据作为验证集. 运行环境: ...

  10. Java虚拟内存(栈、堆)

    一.java虚拟的内存可以分为几种 1. 第一种 栈(stack) 栈的特点 1.1 栈描述的是方法执行的内存模型,每个方法都被调用都会创建一个栈(存储局部变量.操作数. 方法出口等) 1.2 JVM ...