Jwt令牌创建
添加依赖
<dependencies>
<!-- jwt -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.51</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</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>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
<resources>
<!--注意这里要加上这些,不然证书无法加载-->
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<excludes>
<exclude>**/*.jks</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<includes>
<include>**/*.jks</include>
</includes>
</resource>
</resources>
</build>
普通方式创建jwt令牌
package com.example.demo;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.util.Date;
/**
* @author liuyalong
*/
public class JwtTest {
public static void main(String[] args) {
final String keyStr = "4379";
Key key = new SecretKeySpec(keyStr.getBytes(), SignatureAlgorithm.HS512.getJcaName());
// expire_time为token有效时长, 单位毫秒
final long expire_time =10000;
Date expiresDate = new Date(System.currentTimeMillis() + expire_time);
//生成jwt令牌
JwtBuilder jwtBuilder = Jwts.builder()
//设置jwt编码
.setId("66")
//设置jwt主题
.setSubject("我是主题")
//设置jwt签发日期
.setIssuedAt(new Date())
.claim("a", "admin")
.claim("b", "aaaa")
.claim("c", "yalong")
//设置jwt的过期时间,好像必须在claim后面
.setExpiration(expiresDate)
//注意,这里的密码应该使用Key类型,不应使用String类型
//如果使用String类型,比如4379123加密,那么解密使用4379也可以解开,
// 因为这个String类型是base64EncodedSecretKey
.signWith(SignatureAlgorithm.HS256, key);
//生成jwt
String jwtToken = jwtBuilder.compact();
System.out.println(jwtToken);
//解析jwt,得到其内部的数据
Claims claims = Jwts.parser().setSigningKey(key).parseClaimsJws(jwtToken).getBody();
System.out.println(claims.get("exp"));
System.out.println(claims);
}
}
使用keytool生成证书
keytool -genkeypair -alias test -keyalg RSA -keypass yalong -keystore "D://yalong.jks" -storepass yalong -validity 3650 -dname "CN=localhost,OU=localhost,O=localhost,L=SH,ST=SH,C=CN" -storetype pkcs12
注意:这里有个大坑,
keypass必须和storepass一样,不然私钥解不开,或许是keytool的原因造成的
- alias:密钥的别名
- keyalg:使用的hash算法
- keypass:密钥的访问密码
- keystore:密钥库文件名,yalong.jks保存了生成的证书
- storepass:密钥库的访问密码
- validity 3650 : 有效期10年
- dname :证书的相关信息,
- CN:名字与形式
- OU:组织单位名称
- O:组织机构名称
- L:城市信息
- ST:省份信息
- C:国家信息
查看密钥库
keytool -list -keystore "D://yalong.jks" -storepass liuyalong
导出公钥证书文件.cer
keytool -export -alias test -keystore "D://yalong.jks" -file "D://publicKey.cer" -storepass yalong
使用密钥对生成JWT并加密解密
使用私钥生成JWT令牌,使用公钥解密,公钥可以公开,私钥留在授权服务里,公钥可以导出,私钥不可以导出
package com.example.demo;
import java.io.FileInputStream;
import java.security.KeyPair;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.interfaces.RSAPrivateKey;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.fastjson.JSON;
import org.apache.commons.codec.binary.Base64;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.jwt.Jwt;
import org.springframework.security.jwt.JwtHelper;
import org.springframework.security.jwt.crypto.sign.RsaSigner;
import org.springframework.security.jwt.crypto.sign.RsaVerifier;
import org.springframework.security.rsa.crypto.KeyStoreKeyFactory;
/**
* @author liuyalong
*/
public class GetRsaKey {
public static void main(String[] args) throws Exception {
//证书库文件路径
// 这里使用ClassPathResource路径,所以不带D:/
String storePath = "yalong.jks";
//这个路径用来获取私钥
String storePath1 = "D:/yalong.jks";
//公钥证书文件路径
//从keystore 导出公钥证书文件.cer,命令如下
//keytool -export -alias test -keystore "D://yalong.keystore" -file "D://publicKey.cer"
String cerPath = "D:/publicKey.cer";
//证书别名
String alias = "test";
//证书库密码
String storePw = "yalong";
//证书密码
String keyPw = "yalong";
String publicKey = getPublicKey(cerPath);
String privateKey = getPrivateKey(storePath1, alias, storePw, keyPw);
System.out.println("从证书获取的公钥为:" + publicKey);
System.out.println("从证书获取的私钥为:" + privateKey);
Map<String, String> map = new HashMap<>();
map.put("company", "honbow");
map.put("address", "shenzhen");
String jwt = createJwt(storePath, alias, storePw, keyPw, map);
System.out.println("生成JWT为:" + jwt);
String s = parseJwt(jwt, publicKey);
System.out.println("校验后:" + s);
}
/**
* 从公钥证书中获取公钥
*
* @param cerPath 公钥证书的路径
*/
private static String getPublicKey(String cerPath) throws Exception {
CertificateFactory certificatefactory = CertificateFactory.getInstance("X.509");
FileInputStream fis = new FileInputStream(cerPath);
// X509Certificate cert = (X509Certificate) certificatefactory.generateCertificate(fis);
Certificate cert = certificatefactory.generateCertificate(fis);
PublicKey pk = cert.getPublicKey();
String pkString = new Base64().encodeToString(pk.getEncoded());
//这里需要拼接开头和结尾,不然无法解析出来结果,可能有其他验证方法
return "-----BEGIN PUBLIC KEY-----" + pkString + "-----END PUBLIC KEY-----";
}
private static String getPublicKey(String cerPath, String instanceType) throws Exception {
CertificateFactory certificatefactory = CertificateFactory.getInstance(instanceType);
FileInputStream fis = new FileInputStream(cerPath);
Certificate cert = certificatefactory.generateCertificate(fis);
PublicKey pk = cert.getPublicKey();
return new Base64().encodeToString(pk.getEncoded());
}
/**
* @param storePath 证书库的路径
* @param alias 证书别名,创建时指定的
* @param storePw 访问证书库的密码
* @param keyPw 访问证书的密码
* @param JwtMap 需要设置进Jwt的内容
* @return jwt 字符串
*/
private static String createJwt(String storePath,
String alias,
String storePw,
String keyPw,
Map<String, String> JwtMap) {
ClassPathResource classPathResource = new ClassPathResource(storePath);
KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(classPathResource, keyPw.toCharArray());
KeyPair keyPair = keyStoreKeyFactory.getKeyPair(alias, storePw.toCharArray());
//将当前的私钥转换为rsa私钥
RSAPrivateKey rsaPrivateKey = (RSAPrivateKey) keyPair.getPrivate();
Jwt jwt = JwtHelper.encode(JSON.toJSONString(JwtMap), new RsaSigner(rsaPrivateKey));
return jwt.getEncoded();
}
/**
* 生成私钥
*
* @param storePath 证书库的路径
* @param alias 证书别名,创建时指定的
* @param storePw 访问证书库的密码
* @param keyPw 访问证书的密码
*/
private static String getPrivateKey(String storePath, String alias, String storePw, String keyPw) throws Exception {
FileInputStream is = new FileInputStream(storePath);
KeyStore ks = KeyStore.getInstance("PKCS12");
ks.load(is, storePw.toCharArray());
is.close();
PrivateKey key = (PrivateKey) ks.getKey(alias, keyPw.toCharArray());
return new Base64().encodeToString(key.getEncoded());
}
private static String getPrivateKey(String storePath, String alias, String storePw, String keyPw, String storeType) throws Exception {
FileInputStream is = new FileInputStream(storePath);
KeyStore ks = KeyStore.getInstance(storeType);
ks.load(is, storePw.toCharArray());
is.close();
PrivateKey key = (PrivateKey) ks.getKey(alias, keyPw.toCharArray());
return new Base64().encodeToString(key.getEncoded());
}
/**
* @param jwt jwt字符串
* @param publicKey 公钥
* @return 解密后的字符串token
*/
private static String parseJwt(String jwt, String publicKey) {
Jwt token = JwtHelper.decodeAndVerify(jwt, new RsaVerifier(publicKey));
return token.getClaims();
}
}
RSA的公钥和私钥到底哪个才是用来加密和哪个用来解密?
- 既然是加密,那肯定是不希望别人知道我的消息,所以只有我才能解密,所以可得出公钥负责加密,私钥负责解密;同理,既然是签名,那肯定是不希望有人冒充我发消息,只有我才能发布这个签名,所以可得出私钥负责签名,公钥负责验证。
注:
JWT保证的是数据传输过程中的完整性而不是机密性。
由于payload是使用base64url编码的,所以相当于明文传输,如果在payload中携带了敏感信息(如存放密钥对的文件路径),单独对payload部分进行base64url解码,就可以读取到payload中携带的信息。
Jwt令牌创建的更多相关文章
- Spring Boot Security OAuth2 实现支持JWT令牌的授权服务器
概要 之前的两篇文章,讲述了Spring Security 结合 OAuth2 .JWT 的使用,这一节要求对 OAuth2.JWT 有了解,若不清楚,先移步到下面两篇提前了解下. Spring Bo ...
- 阶段5 3.微服务项目【学成在线】_day16 Spring Security Oauth2_13-SpringSecurityOauth2研究-JWT研究-生成JWT令牌&验证JWT令牌
生成jwt需要用私钥来签名.在Auth认证服务下创建测试类 创建密钥工厂,构造函数需要的参数 获取私钥 有了私钥就可以生成JWT令牌 使用jwtHelper是spring security里面的类 e ...
- 什么是JWT令牌认证?
当下,JWT(JSON Web Token)令牌认证已经变得越来越流行.本文主要介绍JWT令牌认证与传统的Session会话认证机制的区别. 为什么需要认证? HTTP是一种无状态协议,那就意味着当前 ...
- 畅购商城(八):微服务网关和JWT令牌
好好学习,天天向上 本文已收录至我的Github仓库DayDayUP:github.com/RobodLee/DayDayUP,欢迎Star,更多文章请前往:目录导航 畅购商城(一):环境搭建 畅购商 ...
- Spring Security OAuth2.0认证授权三:使用JWT令牌
Spring Security OAuth2.0系列文章: Spring Security OAuth2.0认证授权一:框架搭建和认证测试 Spring Security OAuth2.0认证授权二: ...
- JWT令牌简介及demo
一.访问令牌的类型 二.JWT令牌 1.什么是JWT令牌 JWT是JSON Web Token的缩写,即JSON Web令牌,是一种自包含令牌. JWT的使用场景: 一种情况是webapi,类似之 ...
- spring security oauth2搭建resource-server demo及token改造成JWT令牌
我们在上文讲了如何在spring security的环境中搭建基于oauth2协议的认证中心demo:https://www.cnblogs.com/process-h/p/15688971.html ...
- 微服务架构 | 7.2 构建使用 JWT 令牌存储的 OAuth2 安全认证
目录 前言 1. JWT 令牌存储基础知识 1.1 JSON Web Token 2. 构建使用 JWT 令牌存储的 OAuth2 服务器 2.1 引入 pom.xml 依赖文件 2.2 创建 JWT ...
- 阶段5 3.微服务项目【学成在线】_day18 用户授权_03-方法授权-jwt令牌包含权限
修改认证服务的UserDetailServiceImpl类,下边的代码中 permissionList列表中存放了用户的权限, 并且将权限标识按照中间使用逗号分隔的语法组成一个字符串,最终提供给Spr ...
随机推荐
- java多线程---张孝祥
1.java web 中,一次http请求是一个任务,因为服务器里面有线程池的,存在一个线程处理多个请求任务. 2.在java中,vector,hashtable,concurrentHashMap是 ...
- 手写一个最迷你的Web服务器
今天我们就仿照Tomcat服务器来手写一个最简单最迷你版的web服务器,仅供学习交流. 1. 在你windows系统盘的F盘下,创建一个文件夹webroot,用来存放前端代码. 2. 代码介绍: ( ...
- C#委托的详细总结
1.什么是委托 委托是C#中一种类型,它的作用相当于C语言中的函数指针,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用if- ...
- docker漏洞复现环境搭建
0x00 docker简介 把原来的笔记整理了一下,结合前几天的一个漏洞,整理一篇简单的操作文档,希望能帮助有缘人. docker是一个开源的应用容器引擎,开发者可以打包自己的应用到容器里面,然后迁移 ...
- Folx好用的下载功能介绍
Folx作为一款使用便捷的Mac系统下载软件,为用户提供了网页链接捕获.种子文件下载.智能标签等功能,而其Folx专业版更为用户提供了智能控制速度.计划下载任务.种子文件搜索下载等更加智能化的功能. ...
- Shell编程规范:Don't use ls | grep
目录 一.背景 二.ShellCheck的规范 三.修改写法 1.ls | grep file 2.ls | grep regexp 3.ls | grep -v multi 四.最后 五.参考 一. ...
- 理解与使用Treiber Stack
目录 背景 名称由来 CompletableFuture源码实现 FutureTask实现 Treiber Stack抽象实现 入栈 出栈 示例 参考 背景 最近在很多JDK源码中都看到了Treibe ...
- 牛客练习赛66 C公因子 题解(区间gcd)
题目链接 题目大意 给你一个长为n的数组,给所有数组元素加上一个非负整数x,使得这个数组的所有元素的gcd最大 题目思路 这主要是设计到一个多个数gcd的性质 gcd(a,b,c,d.....)=gc ...
- 通过Consul Raft库打造自己的分布式系统
通用的CP系统有etcd和consul, 通用的对立面就是专用系统. 所以在某些场合是有这种需求的. 然而etcd embed的可用性极差, Windows上面跑会出现各种问题, 而且不能定制协议, ...
- 加快alter table
mysql的alter table操作的性能对打表来说是个大问题. mysql执行大部分修改表结构的方法是用新的结构创建一个空表,从旧表中查出所有的数据插入新表,然后删除旧表.这样操作就可能需要花费很 ...