JWT 进阶 -- JJWT

article/2025/11/9 15:54:02

这里写图片描述


###jwt是什么?

JWTs是JSON对象的编码表示。JSON对象由零或多个名称/值对组成,其中名称为字符串,值为任意JSON值。JWT有助于在clear(例如在URL中)发送这样的信息,可以被信任为不可读(即加密的)、不可修改的(即签名)和URL - safe(即Base64编码的)。


###jwt的组成

  • Header: 标题包含了令牌的元数据,并且在最小包含签名和/或加密算法的类型

  • Claims: Claims包含您想要签署的任何信息

  • JSON Web Signature (JWS): 在header中指定的使用该算法的数字签名和声明


例如:

Header:{"alg": "HS256","typ": "JWT"
}Claims:{"sub": "1234567890","name": "John Doe","admin": true
}Signature:base64UrlEncode(Header) + "." + base64UrlEncode(Claims),

加密生成的token:


这里写图片描述


###如何保证 JWT 安全

  • 有很多库可以帮助您创建和验证JWT,但是当使用JWT时,仍然可以做一些事情来限制您的安全风险。在您信任JWT中的任何信息之前,请始终验证签名。这应该是给定的。换句话说,如果您正在传递一个秘密签名密钥到验证签名的方法,并且签名算法被设置为“none”,那么它应该失败验证。

  • 确保签名的秘密签名,用于计算和验证签名。秘密签名密钥只能由发行者和消费者访问,不能在这两方之外访问。

  • 不要在JWT中包含任何敏感数据。这些令牌通常是用来防止操作(未加密)的,因此索赔中的数据可以很容易地解码和读取。

  • 如果您担心重播攻击,包括一个nonce(jti索赔)、过期时间(exp索赔)和创建时间(iat索赔)。这些在JWT规范中定义得很好。


这里写图片描述



###jwt的框架:JJWT

JJWT是一个提供端到端的JWT创建和验证的Java库。永远免费和开源(Apache License,版本2.0),JJWT很容易使用和理解。它被设计成一个以建筑为中心的流畅界面,隐藏了它的大部分复杂性。

  • JJWT的目标是最容易使用和理解用于在JVM上创建和验证JSON Web令牌(JWTs)的库。

  • JJWT是基于JWT、JWS、JWE、JWK和JWA RFC规范的Java实现。

  • JJWT还添加了一些不属于规范的便利扩展,比如JWT压缩和索赔强制。


####规范兼容:

  • 创建和解析明文压缩JWTs

  • 创建、解析和验证所有标准JWS算法的数字签名紧凑JWTs(又称JWSs):

  • HS256: HMAC using SHA-256

  • HS384: HMAC using SHA-384

  • HS512: HMAC using SHA-512

  • RS256: RSASSA-PKCS-v1_5 using SHA-256

  • RS384: RSASSA-PKCS-v1_5 using SHA-384

  • RS512: RSASSA-PKCS-v1_5 using SHA-512

  • PS256: RSASSA-PSS using SHA-256 and MGF1 with SHA-256

  • PS384: RSASSA-PSS using SHA-384 and MGF1 with SHA-384

  • PS512: RSASSA-PSS using SHA-512 and MGF1 with SHA-512

  • ES256: ECDSA using P-256 and SHA-256

  • ES384: ECDSA using P-384 and SHA-384

  • ES512: ECDSA using P-521 and SHA-512



###这里以github上的demo演示,理解原理,集成到自己项目中即可。

####应用采用 spring boot + angular + jwt


  • 结构图

这里写图片描述


  • Maven 引进 : pom.xml
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.nibado.example</groupId><artifactId>jwt-angular-spring</artifactId><version>0.0.2-SNAPSHOT</version><properties><maven.compiler.source>1.8</maven.compiler.source><maven.compiler.target>1.8</maven.compiler.target><commons.io.version>2.4</commons.io.version><jjwt.version>0.6.0</jjwt.version><junit.version>4.12</junit.version><spring.boot.version>1.5.3.RELEASE</spring.boot.version></properties><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>${spring.boot.version}</version><executions><execution><goals><goal>repackage</goal></goals></execution></executions></plugin></plugins></build><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>${spring.boot.version}</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>${commons.io.version}</version></dependency><dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>${jjwt.version}</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>${junit.version}</version></dependency></dependencies>
</project>

  • WebApplication.java
package com.nibado.example.jwtangspr;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;@EnableAutoConfiguration
@ComponentScan
@Configuration
public class WebApplication {//过滤器@Beanpublic FilterRegistrationBean jwtFilter() {final FilterRegistrationBean registrationBean = new FilterRegistrationBean();registrationBean.setFilter(new JwtFilter());registrationBean.addUrlPatterns("/api/*");return registrationBean;}public static void main(final String[] args) throws Exception {SpringApplication.run(WebApplication.class, args);}}

  • JwtFilter.java
package com.nibado.example.jwtangspr;import java.io.IOException;import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;import org.springframework.web.filter.GenericFilterBean;import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureException;public class JwtFilter extends GenericFilterBean {@Overridepublic void doFilter(final ServletRequest req,final ServletResponse res,final FilterChain chain) throws IOException, ServletException {final HttpServletRequest request = (HttpServletRequest) req;//客户端将token封装在请求头中,格式为(Bearer后加空格):Authorization:Bearer +tokenfinal String authHeader = request.getHeader("Authorization");if (authHeader == null || !authHeader.startsWith("Bearer ")) {throw new ServletException("Missing or invalid Authorization header.");}//去除Bearer 后部分final String token = authHeader.substring(7);try {//解密token,拿到里面的对象claimsfinal Claims claims = Jwts.parser().setSigningKey("secretkey").parseClaimsJws(token).getBody();//将对象传递给下一个请求request.setAttribute("claims", claims);}catch (final SignatureException e) {throw new ServletException("Invalid token.");}chain.doFilter(req, res);}}

  • UserController.java
package com.nibado.example.jwtangspr;import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import javax.servlet.ServletException;import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;@RestController
@RequestMapping("/user")
public class UserController {//这里模拟数据库private final Map<String, List<String>> userDb = new HashMap<>();@SuppressWarnings("unused")private static class UserLogin {public String name;public String password;}public UserController() {userDb.put("tom", Arrays.asList("user"));userDb.put("wen", Arrays.asList("user", "admin"));}/*以上是模拟数据库,并往数据库插入tom和sally两条记录*/@RequestMapping(value = "login", method = RequestMethod.POST)public LoginResponse login(@RequestBody final UserLogin login)throws ServletException {if (login.name == null || !userDb.containsKey(login.name)) {throw new ServletException("Invalid login");}//加密生成tokenreturn new LoginResponse(Jwts.builder().setSubject(login.name).claim("roles", userDb.get(login.name)).setIssuedAt(new Date()).signWith(SignatureAlgorithm.HS256, "secretkey").compact());}@SuppressWarnings("unused")private static class LoginResponse {public String token;public LoginResponse(final String token) {this.token = token;}}
}

  • ApiController.java
package com.nibado.example.jwtangspr;import io.jsonwebtoken.Claims;import java.util.List;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/api")
public class ApiController {@SuppressWarnings("unchecked")@RequestMapping(value = "role/{role}", method = RequestMethod.GET)public Boolean login(@PathVariable final String role,final HttpServletRequest request) throws ServletException {final Claims claims = (Claims) request.getAttribute("claims");return ((List<String>) claims.get("roles")).contains(role);}
}

  • index.html
<!doctype html>
<html ng-app="myApp">
<head><meta charset="utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/><title>JSON Web Token / AngularJS / Spring Boot example</title><meta name="description" content=""><meta name="viewport" content="width=device-width"><link rel="stylesheet" href="libs/bootstrap/css/bootstrap.css"><script src="libs/jquery/jquery.js"></script><script src="libs/bootstrap/js/bootstrap.js"></script><script src="libs/angular/angular.js"></script><script src="app.js"></script>
</head>
<body>
<div class="container" ng-controller='MainCtrl'><h1>{{greeting}}</h1><div ng-show="!loggedIn()">Please log in (tom and sally are valid names)</br><form ng-submit="login()">Username: <input type="text" ng-model="userName"/><span><input type="submit" value="Login"/></form></div><div class="alert alert-danger" role="alert" ng-show="error.data.message"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span><span class="sr-only">Error:</span>{{error.data.message}}</div>	<div ng-show="loggedIn()"><div class="row"><div class="col-md-6"><h3><span class="label label-success">Success!</span> Welcome {{userName}}</h3><a href ng-click="logout()">(logout)</a></div><div class="col-md-4"><div class="row header"><div class="col-sm-4">{{userName}} is a</div></div><div class="row"><div class="col-sm-2">User</div><div class="col-sm-2"><span class="glyphicon glyphicon-ok" aria-hidden="true" ng-show="roleUser"></span></div></div><div class="row"><div class="col-sm-2">Admin</div><div class="col-sm-2"><span class="glyphicon glyphicon-ok" aria-hidden="true" ng-show="roleAdmin"></span></div></div>	<div class="row"><div class="col-sm-2">Foo</div><div class="col-sm-2"><span class="glyphicon glyphicon-ok" aria-hidden="true" ng-show="roleFoo"></span></div></div>				</div></div></div>
</div>
</body>
</html>

  • app.js
var appModule = angular.module('myApp', []);appModule.controller('MainCtrl', ['mainService','$scope','$http',function(mainService, $scope, $http) {$scope.greeting = 'Welcome to the JSON Web Token / AngularJR / Spring example!';$scope.token = null;$scope.error = null;$scope.roleUser = false;$scope.roleAdmin = false;$scope.roleFoo = false;$scope.login = function() {$scope.error = null;mainService.login($scope.userName).then(function(token) {$scope.token = token;$http.defaults.headers.common.Authorization = 'Bearer ' + token;$scope.checkRoles();},function(error){$scope.error = error$scope.userName = '';});}$scope.checkRoles = function() {mainService.hasRole('user').then(function(user) {$scope.roleUser = user});mainService.hasRole('admin').then(function(admin) {$scope.roleAdmin = admin});mainService.hasRole('foo').then(function(foo) {$scope.roleFoo = foo});}$scope.logout = function() {$scope.userName = '';$scope.token = null;$http.defaults.headers.common.Authorization = '';}$scope.loggedIn = function() {return $scope.token !== null;}} ]);appModule.service('mainService', function($http) {return {login : function(username) {return $http.post('/user/login', {name: username}).then(function(response) {return response.data.token;});},hasRole : function(role) {return $http.get('/api/role/' + role).then(function(response){console.log(response);return response.data;});}};
});

  • 运行应用

这里写图片描述


效果


这里写图片描述


这里写图片描述


http://chatgpt.dhexx.cn/article/W4aVoucL.shtml

相关文章

JWT详解和使用(jjwt)

JWT详解和使用 JWT是啥 JWT&#xff08;JSON Web Token&#xff09;是一个开放标准(RFC 7519)&#xff0c;它定义了一种紧凑的、自包含的方式&#xff0c;用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任&#xff0c;因为它是数字签名的。 下列场景中使用…

JJWT 实现JWT

1什么是JJWT JJWT 是一个提供端到端的 JWT 创建和验证的 Java 库。永远免费和开源 (Apache License&#xff0c;版本2.0)&#xff0c;JJWT 很容易使用和理解。它被设计成一个以建筑为中心的流畅界面&#xff0c;隐藏了它的大部分复杂性。 2JJWT快速入门 2.1token的创建 2.1…

什么是JWT?

在HTTP接口调用的时候&#xff0c;服务端经常需要对调用方做认证&#xff0c;以保证安全性。一种常见的认证方式是使用JWT(Json Web Token)&#xff0c;采用这种方式时&#xff0c;经常在header传入一个authorization字段&#xff0c;值为对应的jwt_token&#xff0c;或者也有图…

JWT的学习和JJWT的使用

1.什么是JWT JWT&#xff08;JSON Web Token&#xff09;是一个开放的行业标准&#xff0c;它定义了一种简介的&#xff0c;自包含的协议格式&#xff0c;用于在通信双方传递json对象&#xff0c;传递的信息经过数字签名可以被验证和信任。JWT可以使用HMAC算法或者使用RSA的公…

JWT详解

本文从本人博客搬运&#xff0c;原文格式更加美观&#xff0c;可以移步原文阅读&#xff1a;JWT详解 JWT简介 1.什么是JWT 在介绍JWT之前&#xff0c;我们先来回顾一下利用token进行用户身份验证的流程&#xff1a; 客户端使用用户名和密码请求登录服务端收到请求&#xff…

JWT详解、JJWT使用、token 令牌

前言 在正式讲解JWT之前&#xff0c;我们先重温一下用户身份认证相关的一些概念&#xff1a; 有状态登录&#xff08;session认证&#xff09; 服务器当中记录每一次的登录信息&#xff0c;从而根据客户端发送的数据来判断登录过来的用户是否合法。 缺点&#xff1a; 每个用…

Java的JJWT实现JWT

1 什么是 JJWT JJWT 是一个提供端到端的 JWT 创建和验证的 Java 库。永远免费和开源 (Apache License&#xff0c;版本2.0)&#xff0c;JJWT 很容易使用和理解。它被设计成一个以建筑为中心的流畅界面&#xff0c;隐藏了它的大部分复杂性。 2 token 的创建 2.1 引入依赖 &l…

解决Red Hat虚拟机与主机网络不通

虚拟机版本&#xff1a;Red Hat Enterprise Linux 7 64 位 安装&#xff1a;自定义安装&#xff0c;带GUI的服务器&#xff0c;创建图形化界面 创建完毕后发现网络ping不通&#xff0c;经过查阅各种资料&#xff0c;在同事的帮助下终于解决。做一个记录。 1、VMware网络配置。…

虚拟机VMware和宿主机连接

文章目录 一、NAT连接1.查看宿主机IP地址2.设置VMnet8信息2.设置虚拟机模式3.设置虚拟网络4.设置虚拟机内系统IP&#xff08;Centos8.2为例&#xff09;4.1.图形化操作4.1.1DHCP4.1.2静态IP4.1.3 重启网卡&#xff08;修改网卡信息后&#xff09; 5.测试5.1.宿主机ping虚拟机5.…

VMware虚拟机三种网络连接模式详解

VMware虚拟机三种网络连接模式详解 Vmware提供了三种网络工作模式&#xff0c;分别是&#xff1a;&#xff08;1&#xff09;Bridged&#xff08;桥接模式&#xff09;&#xff1b;&#xff08;2&#xff09;NAT&#xff08;网络地址转换模式&#xff09;&#xff1b;&#xf…

虚拟机与主机之间通信

1.bridged(桥接方式&#xff0c;默认使用vmnet0虚拟网卡)&#xff1a; 选择这种模式&#xff0c;虚拟机等同于网络内的一台物理主机&#xff0c;可对手动设置IP&#xff0c;子网掩码。DNS&#xff0c;且IP地址要和主机的IP在同一网段内。这样。虚拟机就和主机如同连在一个HUB上…

虚拟机的几种网络连接方式

系列运维 文章目录 系列运维前言一、几种网络连接方式各是什么&#xff1f;二、网络连接的差异性总结 前言 VirtualBox中有4种网络连接方式&#xff1a; NAT Bridged Adapter Internal Host-only Adapter VMWare中有三种&#xff0c;VirtualBox只是比VMWare多了Internal方式。…

主机、虚拟机、开发板之间网络连接设置

最近在玩开发板&#xff0c;主机使用的无线网卡&#xff0c;开发板与主机网线直连&#xff0c;现在开发板想使用tftp直接从虚拟机下载镜像等文件&#xff0c;偶尔又需要虚拟机从主机下载文件&#xff0c;虚拟机有时候又需要网络&#xff0c;经过一番折腾算是调试成功。 1.主机…

vmware虚拟机与主机共享网络

我的虚拟机总是各种连不上网&#xff0c;每次都要折腾一番。现在我把虚拟机连不上网的原因总体排查一下&#xff0c;按照流程一步步来&#xff0c;基本上可以解决大部分人的问题。 首先&#xff0c;在VMware的编辑->虚拟网络编辑器重新建立&#xff2e;&#xff21;&#xf…

Virtualbox虚拟机与主机相互访问

刚从vmware切换到Virtualbox有些地方还是不太熟悉。网络连接这块就被卡了一下&#xff0c;后来发现其实很简单&#xff0c;是我想多了。 环境 主机&#xff1a; archlinux 虚拟机&#xff1a;windows 10 软件版本&#xff1a;VirtualBox 6.1 理论上这些环境不影响&#xff0…

虚拟机和主机无法连接

vm网络配置&#xff1a;https://www.cnblogs.com/aeolian/p/8882790.html 一、首先查看自己的虚拟机服务有没有开启&#xff0c;选择电脑里面的服务查看&#xff1b; 1.计算机点击右键选择管理 2.进入管理选择VM开头的服务如果没有开启的话就右键开启 二、虚拟机服务开启后就…

虚拟机和主机的网络访问

本人的问题是主机可以ping虚拟机&#xff0c;虚拟机可以正常访问端口&#xff0c;主机不能访问虚拟机端口&#xff0c;然后就进行各种问题的排查&#xff0c;一开始把所有的防火墙都关了还不行&#xff0c;所以来到了windows主机虚拟网卡这里设置&#xff0c;使用了手动设置虚拟…

VMwareWorkstationPro虚拟机与主机远程连接

目录 一 &#xff0c;虚拟机与主机远程连接环境设置 二 虚拟机与主机远程连接 一 &#xff0c;虚拟机与主机远程连接环境设置 1 点击设置打开系统选项 2 打开远程控制 3 点击设置打开更新和安全 4 关闭病毒防护和防火墙 &#xff08;注&#xff1a;主机与虚拟机都要执行…

ubutu虚拟机和主机共享同一网络

ubutu虚拟机和主机共享同一网络 前言一、使用场景二、vmware设置三、主机windows设置四、虚拟机ubuntu配置 前言 ​ 本文采用的是共享同一网卡的方式达到虚拟机使用和主机一样的网络的目的。主要参考了虚拟机共享主机网卡连接的第一部分内容&#xff0c;感兴趣的朋友可以去大佬…

虚拟机三种网络连接方式

第一种连接方式-桥接模式 原理图&#xff1a; 桥接模式效果&#xff1a;通过桥接&#xff0c;我们让vm虚拟机和真正主机pc3处在了一片局域网下&#xff0c;vm虚拟机可以访问pc123也可以外网&#xff08;Internet)&#xff0c;同时pc123也可以访问vm虚拟机。好处是vm虚拟机可以…