https://gitee.com/fakerlove/spring-security

文章目录

  • 1. 介绍
  • 2. SpringBoot与JWT整合
    • 2.1 JWT的结构:
    • 2.2 JWT的使用测试:
      • 1) java-jwt 版本
      • 2) jjwt 版本
        • 检验
        • 过期时间
        • 自定义claim
    • 2.3 SpringBoot与JWT整合:

1. 介绍

https://jwt.io/

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

2. SpringBoot与JWT整合

2.1 JWT的结构:

Header(头):包含令牌的类型与使用的签名算法,它会使用Base64进行编码
{"alg": "HS265","typ": "JWT"
}
Payload(有效负载): 包含声明(有关用户实体和其他数据的声明),使用Base64进行编码
Base64是一种可逆的编码,因此不要在负载里存入敏感数据!
{"id": "1","name": "BLU","admin": true
}
Signature(签名):使用编码后的header和payload以及一个指定密钥,然后使用header中指定的算法(HS265)进行签名.
签名的作用是保证JWT没有被篡改过

负载

iss: jwt 的签发者

sub: jwt 所面向的用户

aud:接受jwt 的一方

exp: jwt的过期时间,这个过期时间必须要大于签发时间

nbf:定义在什么时间之前,该jwt 不可用的

iat: jwt的签发时间

jti:jwt 的唯一身份识别,主要用来作为一次性token,从而回避重放攻击

有很多公司在做jwt ,因为jwt 是标准,并不是实现,所以需要公司实现,比较有名的

auth0,java-jwt,jjwt

<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt -->
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
<dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.12.0</version>
</dependency>

2.2 JWT的使用测试:

1) java-jwt 版本

  • 依赖:
<dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.4.0</version>
</dependency>
  • 测试:
@Test
void getToken() {//HashMap<String,Object> map = new HashMap<String, Object>();Calendar instance = Calendar.getInstance();instance.add(Calendar.SECOND, 60);String token = JWT.create()//.withHeader(map)//设置Payload.withClaim("userId", 10).withClaim("username", "BLU")//设置token过期时间(60s).withExpiresAt(instance.getTime())//设置签名.sign(Algorithm.HMAC256("!@#$%^&*"));System.out.println(token);}
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MDA3NDA2MTUsInVzZXJJZCI6MTAsInVzZXJuYW1lIjoiQkxVIn0.0re-tA4dQm4blGhn1DvpnUl7Lrz_EWXwn8LfRbWQXCU
@Test
void TokenVerify() {//创建验证对象JWTVerifier verifier = JWT.require(Algorithm.HMAC256("!@#$%^&*")).build();DecodedJWT verify = verifier.verify("eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE2MDA3NDA2MTUsInVzZXJJZCI6MTAsInVzZXJuYW1lIjoiQkxVIn0.0re-tA4dQm4blGhn1DvpnUl7Lrz_EWXwn8LfRbWQXCU");System.out.println(verify.getClaim("userId").asInt());System.out.println(verify.getClaims().get("username").asString());System.out.println("过期时间:"+verify.getExpiresAt());
}
10
BLU
过期时间:Tue Sep 22 10:10:15 CST 2020

2) jjwt 版本

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.4.1</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>demo3</artifactId><version>0.0.1-SNAPSHOT</version><name>demo3</name><description>Demo project for Spring Boot</description><properties><java.version>11</java.version></properties><dependencies><!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt --><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>

验证

package com.example.demo3;import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;import java.util.Date;@SpringBootTest
class Demo3ApplicationTests {@Testvoid contextLoads() {JwtBuilder jwtBuilder= Jwts.builder()// 用户的id.setId("001")// 接受用户的角色信息.setSubject("Rose")// 签发时间.setIssuedAt(new Date())// 采用的算法.signWith(SignatureAlgorithm.HS256,"xxxx");String token=jwtBuilder.compact();System.out.println(token);}}

结果

eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIwMDEiLCJzdWIiOiJSb3NlIiwiaWF0IjoxNjA5NTcxNzg1fQ.pqau27EgQhVtqamer2_8z-gBQeATGNveBuUAyVlSac4

检验

    @Testpublic void verfity(){String token="eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIwMDEiLCJzdWIiOiJSb3NlIiwiaWF0IjoxNjA5NTcxNzg1fQ.pqau27EgQhVtqamer2_8z-gBQeATGNveBuUAyVlSac4";Claims claims= Jwts.parser().setSigningKey("xxxx").parseClaimsJws(token).getBody();System.out.println(claims.getId());System.out.println(claims.getSubject());System.out.println(claims.getIssuedAt());}

结果

001
Rose
Sat Jan 02 15:16:25 CST 2021

过期时间

    @Testvoid contextLoads() {JwtBuilder jwtBuilder= Jwts.builder()// 用户的id.setId("001")// 接受用户的角色信息.setSubject("Rose")// 签发时间.setIssuedAt(new Date())// 采用的算法.signWith(SignatureAlgorithm.HS256,"xxxx").setExpiration(new Date(System.currentTimeMillis()+60*1000));String token=jwtBuilder.compact();System.out.println(token);}

自定义claim

package com.example.demo3;import io.jsonwebtoken.*;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;import java.util.Date;@SpringBootTest
class Demo3ApplicationTests {@Testvoid contextLoads() {JwtBuilder jwtBuilder= Jwts.builder()// 用户的id.setId("001")// 接受用户的角色信息.setSubject("Rose")// 签发时间.setIssuedAt(new Date())// 采用的算法.signWith(SignatureAlgorithm.HS256,"xxxx")// .setExpiration(new Date(System.currentTimeMillis()+60*1000)).claim("name","joker").claim("login","sadas");String token=jwtBuilder.compact();System.out.println(token);}@Testpublic void verfity(){String token="eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiIwMDEiLCJzdWIiOiJSb3NlIiwiaWF0IjoxNjA5NTcyODU4LCJuYW1lIjoiam9rZXIiLCJsb2dpbiI6InNhZGFzIn0.-Z2YMakhk6pKa27xyEFgGb5Jjm0ebMUEMpLSFA42c7A";Claims claims= Jwts.parser().setSigningKey("xxxx").parseClaimsJws(token).getBody();System.out.println(claims.getId());System.out.println(claims.getSubject());System.out.println(claims.getIssuedAt());System.out.println(claims.get("name"));System.out.println(claims.get("login"));}}

2.3 SpringBoot与JWT整合:

  • 依赖
<dependencies><dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>3.4.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.2</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.22</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency>
</dependencies>
  • 配置
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/jwt?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=123456mybatis.type-aliases-package=com.blu.entity
mybatis.mapper-locations=classpath:mapper/*.xmllogging.level.com.blu.dao=debug
  • 数据库user表:
  • 实体类:
package com.blu.entity;import lombok.Data;
import lombok.experimental.Accessors;@Data
@Accessors(chain=true)
public class User {private String id;private String name;private String password;
}
  • UserDao:
package com.blu.dao;import org.apache.ibatis.annotations.Mapper;
import com.blu.entity.User;@Mapper
public interface UserDao {User login(User user);
}
  • UserMapper:
<?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.blu.dao.UserDao"><select id="login" parameterType="User" resultType="User">select * from user where name= #{name} and password= #{password}</select>
</mapper>
  • UserService:
package com.blu.service;import com.blu.entity.User;public interface UserService {User login(User user);
}
  • UserServiceImpl:
package com.blu.service.impl;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import com.blu.dao.UserDao;
import com.blu.entity.User;
import com.blu.service.UserService;@Service
public class UserServiceImpl implements UserService {@Autowiredprivate UserDao userDao;@Overridepublic User login(User user) {User userDB = userDao.login(user);if(userDB!=null) {return userDB;}throw new RuntimeException("认证失败!");}}
  • JWT的工具类封装:
package com.blu.utils;import java.util.Calendar;
import java.util.Map;import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;public class JWTUtils {private static final String SIGN= "!@#$%^&*123456789";/*** 生成Token*/public static String getToken(Map<String,String> map) {Calendar instance = Calendar.getInstance();instance.add(Calendar.DATE, 7);//创建JWTBuilderJWTCreator.Builder builder = JWT.create();//设置payloadmap.forEach((k,v)->{builder.withClaim(k, v);});//设置过期时间和签名,生成tokenString token = builder.withExpiresAt(instance.getTime()).sign(Algorithm.HMAC256(SIGN));return token;}/*** 验证token*/public static void TokenVerify(String token) {JWT.require(Algorithm.HMAC256(SIGN)).build().verify(token);}/*** 获取token信息 */public static DecodedJWT getTokenInfo(String token) {DecodedJWT verify = JWT.require(Algorithm.HMAC256(SIGN)).build().verify(token);return verify;}}
  • JWTInterceptor 拦截器
package com.blu.interceptors;import java.util.HashMap;
import java.util.Map;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;import org.springframework.web.servlet.HandlerInterceptor;import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.blu.utils.JWTUtils;
import com.fasterxml.jackson.databind.ObjectMapper;public class JWTInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception {//获取请求头中的tokenString token = request.getHeader("token");Map<String,Object> map = new HashMap<String, Object>();try {JWTUtils.TokenVerify(token);//放行请求return true;} catch (SignatureVerificationException e) {map.put("msg", "无效签名");e.printStackTrace();} catch (TokenExpiredException e) {map.put("msg", "token已过期");e.printStackTrace();} catch (AlgorithmMismatchException e) {map.put("msg", "算法不一致");e.printStackTrace();} catch (Exception e) {map.put("msg", "token无效");e.printStackTrace();}map.put("state",false);//使用jackson将map转为jsonString json = new ObjectMapper().writeValueAsString(map);response.setContentType("application/json;charset=UTF-8");response.getWriter().print(json);return false;}}
  • InterceptorConfig 配置类
package com.blu.config;import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;import com.blu.interceptors.JWTInterceptor;@Configuration
public class InterceptorConfig implements WebMvcConfigurer {@Overridepublic void addInterceptors(InterceptorRegistry registry) {registry.addInterceptor(new JWTInterceptor()).addPathPatterns("/**").excludePathPatterns("/user/login");}}
  • UserController
package com.blu.controller;import java.util.HashMap;
import java.util.Map;import javax.servlet.http.HttpServletRequest;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.blu.entity.User;
import com.blu.service.UserService;
import com.blu.utils.JWTUtils;import lombok.extern.slf4j.Slf4j;@RestController
@Slf4j
public class UserController {@Autowiredprivate UserService userService;@GetMapping("/user/login")public Map<String,Object> login(User user){log.info("用户名:[{}]",user.getName());log.info("密码:[{}]",user.getPassword());Map<String,Object> map = new HashMap<String, Object>();try {User userDB = userService.login(user);Map<String,String> payload = new HashMap<String, String>();payload.put("id", userDB.getId());payload.put("name", userDB.getName());String token = JWTUtils.getToken(payload);map.put("state",true);map.put("msg","认证成功");map.put("token", token);} catch (Exception e) {map.put("state",false);map.put("msg",e.getMessage());}return map;}@PostMapping("/user/test")public Map<String,Object> test(HttpServletRequest request){String token = request.getHeader("token");DecodedJWT tokenInfo = JWTUtils.getTokenInfo(token);log.info("用户id:[{}]",tokenInfo.getClaim("id").asString());log.info("用户名:[{}]",tokenInfo.getClaim("name").asString());Map<String,Object> map = new HashMap<String, Object>();map.put("state", true);map.put("msg","请求成功");return map;}}
  • 测试

登录获取token:

测试错误的token:

测试正确的token:

JWT 教程_1 SpringBoot与JWT整合相关推荐

  1. html jwt权限控制,SpringBoot+SpringSecurity+JWT实RESTfulAPI权限控制

    在整合jwt之前,我们首先要在SpringBoot中整合security的模块,来实现基于security的授权控制.用过security的人都知道,它的功能无比的强大比shiro还要强大,但是今天我 ...

  2. JWT教程_3 oauth和JWT 整合

    https://gitee.com/fakerlove/spring-security 4. oauth和JWT 整合 编写jwt 类 package com.example.demo3.config ...

  3. JWT教程_2 SpringSecurity与JWT整合

    3. SpringSecurity与JWT整合 依赖: <dependencies><dependency><groupId>org.mybatis.spring. ...

  4. 完整教程:Springboot 2.2整合elasticsearch 7.x (spring-boot-starter-data-elasticsearch)

    请注意,SpringBoot是2.2.0.RELEASE才兼容elasticsearch 7.x 废话不多说,直接上代码. 1.pom <?xml version="1.0" ...

  5. Springboot集成JWT做认证授权

    目录 1.1.JWT简介 1.2.JWT能做什么? 1.3.JWT认证流程是什么? 1.4.JWT的结构是什么? 1.5.使用JWT 1.生成token 2.解析token 1.6.封装工具类 1.7 ...

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

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

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

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

  8. 单realm模式下前后端分离实现springboot+shiro+jwt+vue整合

    shiro+jwt实现前后端分离 一.RBAC概念 基于角色的权限访问控制(Role-Based Access Control)作为传统访问控制(自主访问,强制访问)的有前景的代替受到广泛的关注.在R ...

  9. SpringBoot集成JWT实现Token登录验证

    目录 1.1 JWT是什么? 1.2 JWT主要使用场景 1.3 JWT请求流程 1.4 JWT结构 二,SpringBoot集成JWT具体实现过程 2.1添加相关依赖 2.2自定义跳出拦截器的注解 ...

最新文章

  1. linux脚本case语句,shell中的case语句,数组及函数
  2. 这些年,在工作中摸索的我
  3. xp 远程计算机需要远程验证登陆,xp远程桌面登陆需要身份验证问题解决
  4. c语言寻找James,[semi-tutorial]某亚里亚写在JamesM边上的OS笔记
  5. 举例什么时候会用到 call(), apply()
  6. C++11新特性(3)
  7. 计算机网络概念,组成,功能和分类
  8. java二次方程式答案_二次方程式Java?
  9. Spring Data 起步
  10. python配置文件封装_Python configparser模块封装及构造配置文件代码示例
  11. java trimprefix_MyBatis动态SQL中的trim标签的使用方法
  12. php 源代码 即时通讯,php开源免费即时通讯源码-目前有哪些完全的开源的PHP,商城代码...
  13. 参考文献引用格式实例
  14. 什么可以有助睡眠,助睡眠的生活好品
  15. Sketch(三)——插件
  16. 水星路由器短信认证配置流程
  17. 根据不同的厂商,分析师和IT用户对云计算的理解,我们将云计算细分以下几类?
  18. android蓝牙发送文件夹里,Android蓝牙发送文件问题
  19. 【最新计算机、电子毕业设计 本科 大专 设计+源码】
  20. 常被网友挂在嘴边的恐惧症,治疗方法可能更令人害怕

热门文章

  1. 编译C++11/14方法
  2. SpringBoot之安装H2数据库
  3. 搭建MyEclipse和Tomcat遇到的坑(JavaEE作业)
  4. python中使用什么获取两个集合的补集_python中求两个List的交集、并集和差集
  5. nginx清缓存,网站刷新不过来时用
  6. 查看服务器的性能和使用状态(top,free,df)
  7. 编译原理--中间代码生成(自己看)
  8. 已经发车的票还能取出来吗_火车票报销凭证是啥?能不打印吗?官方回应来了...
  9. linux删除win分区工具,Win 10 和 Linux 双系统,从硬盘删除Linux分区,Win 10引导修复...
  10. 鸿蒙os2.0官网公测报名,鸿蒙OS2.0公测版测试资格报名-鸿蒙OS2.0公测版测试资格报名官网地址预约 -友情手机站...