开发者学堂课程【Spring Security知识精讲与实战演示(三):分布式整合之common工具模块搭建】学习笔记与课程紧密联系,让用户快速学习知识
课程地址:https://developer.aliyun.com/learning/course/732/detail/13069
分布式整合之common工具模块搭建
内容介绍:
一、创建副工程
二、创建一个放置工程类的模块
三、创建常用工具类
一、创建副工程
分布式认证有很多服务,首先创建一个副工程:
设置一个 model 为副工程,详细信息如下:
副工程里面导入一个包,任何一个工程都会用到spring boat。
所以将此包导入到副工程里面,这样以后不管怎么使用,都不需重复性导入。到此副工程的创建就初步完成了。
二、创建一个放置工程类的模块
此模块只是一个工具包,并非一个服务,并不会在里面进行启动等等,只是把工具类都在一块,方便大家使用。创建一个新的模块,起一个名字,是通用包,因为需要用到jwt,所以先到放入一个jwt的包,可以把jwt的架包粘贴过来,也可以从官网上直接粘贴。接下里需要复制进来相关工具,再创建一个com.itheima.utils,复制进来后会发现有报错。
<artifactId heima_common</artifactId
dependencies>
dependency
groupId>io.jsonwebtoken</groupId)
<artifactId
jjwt-api</artifactId<version>0.10.7</version>
(/dependency)
(dependency)
<groupId
io.jsonwebtoken</groupId
<artifactId>jjwt-impl</artifactId (version 0.10.7</version)
<scope>runtime</scope>
</dependency)
dependency>
groupId
io.jsonwebtoken</groupId (artifactIdjjwt-jackson</artifactId
(version>0.10.7</version)
<scope>runtime</scope>
</dependency)
/dependencies
首先是第一个报错的Jason的包,导入相关架包之后,会发现上面不再进行报错。
package comitheima.utils;
import com fasterxml.jackson.core.JsonProcessingException;
import com fasterxml.jackson.core.type.TypeReference;
import com fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j. LoggerFactory;
import java.io.IOException;
import java.util.List;
import java.util.Map; I
lauthor:黑马程序员
public class JsonUtils (
public static final ObjectMapper mapper = new0bjectMapper();
private
static
final Loggerlogger = LoggerFactory.getLogger(JsonUtils.class);
接下来是日志包,直接导入spring boot的整合日志包。这个工具类就无误了。Json的字符串要和前面一致,可以转成一个对象等等。最后的是泛型里面套入泛型。
public static<K,V> Map<K, V> toMap(String json, Class(K> kClass, Class<V> vClass)(
try (
returnmapper.readValue(json, mapper.getTypeFactory().constructMapType(Map.class, kClass, vClass)); catch(IOException e)(
logger.error("json
解析出错:”+ json, e);
return null;
public static <T> T natilRead(String json, TypeReference<T> type) (
try (
return mapper.readValue(json, type);
) catch (IOException e)(
logger.error(”json
解析出错:”+ json, e);
return null;
)
datetime是处理相关日期的工具,这里所使用的是joda-time。导入完成之后即可。
version>2.9.9</version
</dependency.
1--日志包一
dependency
groupIdorg. springframework.boot</groupId>
artifactId spring-boot-starter-logging</artifactId </dependency
dependency
groupId joda-time</groupId
artifactIdjoda-time(/artifactId
</dependency
dependency
groupId org.projectlombok</groupId
(artifactId lombol /artifactId
</dependency
/dependencies>
Ject
package com itheima.domain;
import lombok.Data;
import java.util.Date;
/**
@author 黑马程序员
为了方便后期获取token中的用户信息,将token中载荷部分单独封装成一个对象
@Data
public class Payload<T>(
private String id;
private T user Info;
private Date expiration;
)
上面需要明确,一个token中有三部分内容,头部载荷和签名。载荷是主要防止用户信息的,用户信息可能比较复杂,所以专门分装了一个对象,来放置用户对象,除了用户信息也可以放置一些过期时间、ip等等信息。这里专门分装了一个对象来分装载荷。
再次来到主页面,会发现已经没有报错:
param token 用户请求中的token
来@param publicKey 公钥
@return Jws<Claims>
*/
private static Jws<Claims> parserToken(String token, PublicKey publicKey) (
return Jwts.parser().setSigningKey(publicKey).parseClaimsJws(token);
private static String createJTI()(
return
new String(Base64.getEncoder().encode(UUID.randomUUID().toString().getBytes()));
水水
获取token中的用户信息
@param token 用户请求中的令牌
@param publicKey 公钥
*@return 用户信息
*/
public staticT> Payload<T> get InfoFromToken(String token, PublicKey publicKer. Class<T> userType) (
接下里查看jwt如何使用。首先来看怎么进行加密,在twt中进行查看id,用户信息,签名和配置。同时在这里也可以设置ID,ID是随机生成的,也可以设置过期时间,签名方式。
如下
baram user Info 载荷中的数据
*Cparam privateKey 私钥
*@param expire 过期时间,单位秒
来return JWT
*/
public static String generateTokenExpireInSeconds(Object userInfo, PrivateKey privateKey, int expire)(
return Jwts.builder()
.claim(JWT_PAYLOAD_USER_KEY, JsonUtils.toString(userInfo))
.setId(createJTI())
.setExpiration(DateTime.now().plusSeconds(expire).toDate())
.signWith(privateKey, SignatureAlgorithm RS256)
.compact(): I
/**
来公钥解析token
Cparam token 用户请求中的token
param publicKey 公钥
三、创建常用工具类
接下来查看一下常用的工具类,首先要找到如何生成token,解密有俩个方法。区别是第一个解密完之后可以直接分装一个对象过来,第二个是说明不用对象传俩个参数即可。这俩个方法的区别在于上面的加密是私钥加密,下面的是公钥加密,和思路是相吻合的。加密用私钥,解密用公钥。
private static final int DEFAULT_KEY_SIZE= 2048;
/*来
从文件中读取公钥
* @param filename 公钥保存路径,相对于classpath
* @return 公钥对象
*@throws Exception
*/
public static PublicKey getPublicKey(String filename)throws Exception (
byte[] bytes =readFile(filename);
return getPublicKey(bytes);
) I
**
从文件中读取密钥
*@param filename 私钥保存路径,相对于classpath
* @return 私钥对象
*@throws Exception
*/
public static PrivateKey getPrivateKey(String filename) throws Exception (
接下里查看一个方法叫genera key,此方法主要是为了生成公钥和私钥。生成的公钥和私钥去得到公钥的对象和私钥的对象。
bytes =Base64.getDecoder().decode(bytes);
X509EncodedKeySpec spec = new X509EncodedKeySpec(bytes);
KeyFactory factory = KeyFactory.getInstance(”RSA");
return factory.generatePublic(spec);
/**
*获取密钥
@param bytes 私钥的字节形式
@return T
@throws Exception
declared to be thrown by method getPrivateKey more... (Ctrl+ F1)
sewrrraveney wyvwu bytes) throws NoSuchAlgorithmException,InvalidKeySpecException(bytes = Base64.getDecoder().decode(bytes);
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(bytes);
KeyFactory factory = KeyFactory.getInstance(”RSA”);
return factory.generatePrivate(spec);
)
接着导入测试的架包,需要指定一个测试类,指定生成isa,使其帮助创建一个测试。需要指定公钥和私钥的地址,在上面定一个spring类型的字符串。在d盘新建一个文件夹来放置私钥和公钥,设置完俩个路径后,就可以生成公钥和私钥。如图所示:
package com itheima.utils;
import...
public class RsaUtilsTest (
private String privateFilePath =“D:\\auth_key\\id_key_rsa"private String publicFilePath =“D:\\auth_key\\id_key_rsa.pub"@Test
public void generateKey() (
@Test
public void getPublicKey()(
]
@Test
public void getPrivateKey()(
]
使用ios.genera之后,进入之后可以看到有四个参数:
根据密文,生存rsa公钥和私钥,并写入指定文件
*@baram publicKeyFilename 公钥文件路径
@param privateKeyFilename私钥文件路径
* Cparam secret 生成密钥的密文
*/
public static void generateKey(String publicKeyFilename, String privateKeyFilename,
String secret, int keySize) throws Exception
KeyPairGenerator
keyPairGenerator = KeyPairGenerator.getIIstance("RSA”);
SecureRandomsecureRandom = new SecureRandom(secret.getBytes());
keyPairGenerator.
initialize(Math. max(keySize, DEFAULT_KRY_SIZE), secureRandom);
KeyPair keyPair= keyPairGenerator.genKeyPair();
// 获取公钥并写出
byte[] publicKerBytes = keyPair.getPublic().getEncoded();
publicKeyBytes = Base64.getEncoder().encode(publicKeyBytes);
writeFile(publicKeyFilename,publicKeyBytes);
// 获取私钥并写出
byte[] privateKeyBytes = keyPair.getPrivate().getEncoded();
prirateKerBytes = Base64.getEncoder(O.encode(prirateKeyBytes);
writeFile(privateKeyFilename, privateKeyBytes);
左边第一个是公钥路径,第二个是私钥路径。
接下里加入一个盐,指定大小。大小跟上面保持一致即2048。有异常抛出即可,不用捕获。接下来指定执行此方法,如果成功,将在新建文件内看到俩个文件,一个公钥一个私钥。
如果想要得到私钥和公钥,可以输入public的路径,有异常直接抛。接下来需要将私钥的路径写上去,有异常抛出即可。
private String privateFilePath =“D:\\auth_key\\id_key_rsa"
private String publicFilePath=“D:\\auth_key\\id_key_rsa.pub"
@Test
public void generateKey() throws Exception (
RsaUtils.generateKey(publicFilePath,
privateFilePath, secret:"itheima”,keySize:2048);
@Test
public void getPublicKey() throws Exception (
System out.println(RsaUtils.getPublicKey(publicFilePath));
@Test
public void getPrivateKey()(
System. out.print ln(RsaUtils.getPrivateKey );
以上,工具类的准备已经完成了。