目录
- 前言
- 项目结构
- 依赖导入
- 建数据库表
- 建表语句
- 使用插件生成增删改查
- 添加MyRealm
- 添加ShiroConfig
- 添加JwtFilter
- JWT相关得类
- JwtToken
- JwtAudience
- JwtHelper
- 添加BeanFactory
- 只贴出主要得类,具体得可以看我的gitee,接口都自测过的。
前言
最近项目中涉及到使用shiro来作为权限认证,之前对shiro没有做太多的了解,所以一段时间不用的话,忘记得很快,好记性不如烂笔头。在闲暇之余整理springboot整合shiro得demo,我看了网上一些整合得案列,有写得好的,也有些残差不全。我结合目前使用得项目中代码,整合了一遍。基本上可以直接放在项目中使用。如果有什么缺陷,希望大家指正,目前博客只贴出主要的类供大家参考,具体的请移步gitee上看详细类容
。
git地址 :https://gitee.com/zqf960314/springboot-elasticsearch.git
项目结构
依赖导入
<artifactId>spring-boot-starter-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.2.4.RELEASE</version>
</parent>
<properties>
<java.version>11</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-boot.version>2.3.7.RELEASE</spring-boot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.15</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.crazycake</groupId>
<artifactId>shiro-redis</artifactId>
<version>2.4.2.1-RELEASE</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
<version>2.14.2</version>
</dependency>
<!-- Token生成与解析-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
建数据库表
建表语句
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
`username` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户名',
`password` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '密码',
`salt` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '盐值',
`locked` tinyint(1) NULL DEFAULT 0 COMMENT '是否锁定',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `idx_sys_users_username`(`username`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1605473016302256130 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
DROP TABLE IF EXISTS `user_role`;
CREATE TABLE `user_role` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
`user_id` bigint(20) NULL DEFAULT NULL COMMENT '用户编号',
`role_id` bigint(20) NULL DEFAULT NULL COMMENT '角色编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1605473016520359938 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
DROP TABLE IF EXISTS `permission`;
CREATE TABLE `permission` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
`permission` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '权限编号',
`description` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '权限描述',
`rid` bigint(20) NULL DEFAULT NULL COMMENT '此权限关联角色的id',
`available` tinyint(1) NULL DEFAULT 0 COMMENT '是否锁定',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `idx_sys_permissions_permission`(`permission`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
DROP TABLE IF EXISTS `role`;
CREATE TABLE `role` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '角色编号',
`role` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '角色名称',
`description` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '角色描述',
`pid` bigint(20) NULL DEFAULT NULL COMMENT '父节点',
`available` tinyint(1) NULL DEFAULT 0 COMMENT '是否锁定',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `idx_sys_roles_role`(`role`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
ROP TABLE IF EXISTS `role_permission`;
CREATE TABLE `role_permission` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',
`role_id` bigint(20) NULL DEFAULT NULL COMMENT '角色编号',
`permission_id` bigint(20) NULL DEFAULT NULL COMMENT '权限编号',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of role_permission
-- ------------------
SET FOREIGN_KEY_CHECKS = 1;
使用插件生成增删改查
添加MyRealm
@Slf4j
@Service
public class MyRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
private final JwtAudience jwtAudience;
@Autowired
public MyRealm(JwtAudience jwtAudience) {
this.jwtAudience = jwtAudience;
}
/**
* 大坑!,必须重写此方法,不然Shiro会报错
*/
@Override
public boolean supports(AuthenticationToken token) {
return token instanceof JwtToken;
}
/**
* 授权,例如checkRole,checkPermission之类的
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
LoginUser loginUser = JwtHelper.verifySignedAndGetUser(principals.toString(), jwtAudience.getBase64Secret());
if (Objects.isNull(loginUser)) {
throw new UnauthorizedException("授权失败");
}
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
simpleAuthorizationInfo.addRoles(loginUser.getRoles());
//simpleAuthorizationInfo.addStringPermissions(loginUser.getPerms());
log.debug("loginUser:{}", loginUser);
return simpleAuthorizationInfo;
}
/**
* 认证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException {
String token = (String) auth.getCredentials();
// 解密获得username,用于和数据库进行对比
LoginUser loginUser = JwtHelper.verifySignedAndGetUser(token, jwtAudience.getBase64Secret());
if (loginUser == null) {
throw new AuthenticationException("认证失败");
}
return new SimpleAuthenticationInfo(token, token, "my_realm");
}
}
添加ShiroConfig
**
* @Author zqf
* @Date 2022/12/15 16:16
* @Description: shiro配置
*/
@Configuration
public class ShiroConfig {
@Bean("securityManager")
public DefaultWebSecurityManager getManager(MyRealm realm) {
DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
// 使用自己的realm
manager.setRealm(realm);
/*
* 关闭shiro自带的session,详情见文档
* http://shiro.apache.org/session-management.html#SessionManagement-StatelessApplications%28Sessionless%29
*/
DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
manager.setSubjectDAO(subjectDAO);
StateLessSubjectFactory subjectFactory = new StateLessSubjectFactory();
manager.setSubjectFactory(subjectFactory);
return manager;
}
@Bean("shiroFilterFactoryBean")
@DependsOn("springContextUtils")
public ShiroFilterFactoryBean factory(DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
// 添加自己的过滤器并且取名为jwt
Map<String, Filter> filterMap = new HashMap<>();
filterMap.put("jwt", new JwtFilter());
factoryBean.setFilters(filterMap);
factoryBean.setSecurityManager(securityManager);
factoryBean.setUnauthorizedUrl("/401");
/*
* 自定义url规则
* http://shiro.apache.org/web.html#urls-
*/
Map<String, String> filterRuleMap = new HashMap<>();
// 所有请求通过我们自己的JWT Filter
filterRuleMap.put("/**", "jwt");
// 访问401和404页面不通过我们的Filter
filterRuleMap.put("/401", "anon");
filterRuleMap.put("/404", "anon");
filterRuleMap.put("/swagger-ui.html", "anon");
filterRuleMap.put("swagger/**", "anon");
factoryBean.setFilterChainDefinitionMap(filterRuleMap);
return factoryBean;
}
/**
* 下面的代码是添加注解支持
*/
@Bean
@DependsOn("lifecycleBeanPostProcessor")
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
// 强制使用cglib,防止重复代理和可能引起代理出错的问题
// https://zhuanlan.zhihu.com/p/29161098
defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
return defaultAdvisorAutoProxyCreator;
}
@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}
}
/**
* 扩展自DefaultWebSubjectFactory,对于无状态的TOKEN 类型不创建session
* @author zqf
* @date 11/27/2018
*/
public class StateLessSubjectFactory extends DefaultWebSubjectFactory {
@Override
public Subject createSubject(SubjectContext context) {
AuthenticationToken token = context.getAuthenticationToken();
if((token instanceof JwtToken)){
// 当token为HmacToken时, 不创建 session
context.setSessionCreationEnabled(false);
}
return super.createSubject(context);
}
}
添加JwtFilter
public class JwtFilter extends BasicHttpAuthenticationFilter {
private final RedisTemplate<String, Serializable> redisTemplate;
private static final Logger logger = LoggerFactory.getLogger(JwtFilter.class);
public JwtFilter() {
redisTemplate = SpringContextUtils.getBean("ddbRedisTemplate", RedisTemplate.class);
}
/**
* 判断用户是否想要登入。
* 检测header里面是否包含Authorization字段即可
*/
@Override
protected boolean isLoginAttempt(ServletRequest request, ServletResponse response) {
String authorization = super.getAuthzHeader(request);
LoginUser loginUser;
if (StringUtils.isBlank(authorization) || (loginUser = JwtHelper.checkAndGetUser(authorization)) == null) {
loginUser = new LoginUser();
}
LoginUserUtils.setUser(loginUser);
return true;
}
/**
*登录
*/
@Override
protected boolean executeLogin(ServletRequest request, ServletResponse response) {
String authorization = super.getAuthzHeader(request);
LoginUser loginUser = JwtHelper.checkAndGetUser(authorization);
if (loginUser == null) {
return false;
}
JwtToken token = new JwtToken(authorization.replaceFirst("Bearer ", ""));
// 提交给realm进行登入,如果错误他会抛出异常并被捕获
getSubject(request, response).login(token);
logger.debug("登录成功");
// 如果没有抛出异常则代表登入成功,返回true
return true;
}
/**
* 这里我们详细说明下为什么最终返回的都是true,即允许访问
* 例如我们提供一个地址 GET /article
* 登入用户和游客看到的内容是不同的
* 如果在这里返回了false,请求会被直接拦截,用户看不到任何东西
* 所以我们在这里返回true,Controller中可以通过 subject.isAuthenticated() 来判断用户是否登入
* 如果有些资源只有登入用户才能访问,我们只需要在方法上面加上 @RequiresAuthentication 注解即可
* 但是这样做有一个缺点,就是不能够对GET,POST等请求进行分别过滤鉴权(因为我们重写了官方的方法),但实际上对应用影响不大
*/
@Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
if (isLoginAttempt(request, response)) {
try {
executeLogin(request, response);
} catch (Exception e) {
logger.error("登录错误:", e);
return false;
}
}
return true;
}
/**
* 操作完成后清除登录信息
*/
@Override
public void afterCompletion(ServletRequest request, ServletResponse response, Exception exception) throws Exception {
logger.debug("清除用户信息");
super.afterCompletion(request, response, exception);
LoginUserUtils.clear();
}
}
JWT相关得类
JwtToken
package com.zqf.shiro.filter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import org.apache.shiro.authc.AuthenticationToken;
;
/**
* @author zqf
* @date 11/27/2018
*/
@Api("JwtToken")
public class JwtToken implements AuthenticationToken {
@ApiModelProperty("访问用token")
private String accessToken;
@ApiModelProperty("刷新用token")
private String refreshToken;
@ApiModelProperty("token类型")
private String tokenType;
@ApiModelProperty("过期时间")
private long expiresIn;
public JwtToken(String accessToken) {
this.accessToken = accessToken;
}
public JwtToken(String accessToken, String refreshToken) {
this.accessToken = accessToken;
this.refreshToken = refreshToken;
}
public JwtToken(String accessToken, String refreshToken, String tokenType, long expiresIn) {
this.accessToken = accessToken;
this.refreshToken = refreshToken;
this.tokenType = tokenType;
this.expiresIn = expiresIn;
}
@JsonIgnore
@Override
public Object getPrincipal() {
return accessToken;
}
@JsonIgnore
@Override
public Object getCredentials() {
return accessToken;
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public String getRefreshToken() {
return refreshToken;
}
public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
public String getTokenType() {
return tokenType;
}
public void setTokenType(String tokenType) {
this.tokenType = tokenType;
}
public long getExpiresIn() {
return expiresIn;
}
public void setExpiresIn(long expiresIn) {
this.expiresIn = expiresIn;
}
}
JwtAudience
package com.zqf.shiro.jwt;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* @author Hero
* @date 7/12/2017
*/
@ConfigurationProperties(prefix = "jwt.audience")
@Configuration
public class JwtAudience {
/**
* 授权者
*/
private String iss;
/**
* 鉴权者
*/
private String aud;
/**
* Base64编码后的密钥
*/
private String base64Secret;
/**
* token 有效时间: 单位s
*/
private int expirationSeconds;
public String getIss() {
return iss;
}
public void setIss(String iss) {
this.iss = iss;
}
public String getAud() {
return aud;
}
public void setAud(String aud) {
this.aud = aud;
}
public String getBase64Secret() {
return base64Secret;
}
public void setBase64Secret(String base64Secret) {
this.base64Secret = base64Secret;
}
public int getExpirationSeconds() {
return expirationSeconds;
}
public void setExpirationSeconds(int expirationSeconds) {
this.expirationSeconds = expirationSeconds;
}
}
JwtHelper
package com.zqf.shiro.utils;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.zqf.shiro.pojo.LoginUser;
import io.jsonwebtoken.*;
import org.apache.commons.beanutils.BeanMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.crypto.spec.SecretKeySpec;
import java.math.BigInteger;
import java.security.Key;
import java.util.Base64;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @author Hero
* @date 7/12/2017
*/
public class JwtHelper {
private static final Logger log = LoggerFactory.getLogger(JwtHelper.class);
public static boolean veritySigned(String jsonWebToken, String base64Security) {
return Jwts.parser()
.setSigningKey(Base64.getDecoder().decode(base64Security))
.isSigned(jsonWebToken);
}
public static boolean verify(String jsonWebToken, String base64Security) {
try {
final Claims claims = (Claims) Jwts.parser()
.setSigningKey(base64Security)
.parse(jsonWebToken)
.getBody();
return true;
} catch (ExpiredJwtException e) {
log.debug("token过期失效");
return false;
} catch (MalformedJwtException e) {
log.debug("未知错误");
return false;
} catch (SignatureException e) {
log.debug("token签名失效");
return false;
} catch (IllegalArgumentException e) {
log.debug("非法参数");
return false;
}
}
public static String createAccessToken(LoginUser user, String iss, String aud, long ttlMillis, String base64Security) {
// 采用椭圆曲线加密算法, 提升加密速度
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
//生成签名密钥
SignatureAlgorithm signatureAlgorithm = getAlgorithm();
Key signingKey = getKey(base64Security, signatureAlgorithm.getJcaName());
Map<String, Object> claims = user2map(user);
//添加构成JWT的参数
JwtBuilder builder = Jwts.builder().setHeaderParam("typ", "JWT")
.addClaims(claims)
.setIssuer(iss)
.setAudience(aud)
.setSubject(user.getUsername())
.signWith(signatureAlgorithm, signingKey);
//添加Token过期时间
if (ttlMillis >= 0) {
long expMillis = nowMillis + ttlMillis;
Date exp = new Date(expMillis);
builder.setExpiration(exp).setNotBefore(now);
}
//生成JWT
return builder.compact();
}
public static String createRefreshToken(String userName, String iss, String aud, long ttlMillis, String base64Security) {
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
//生成签名密钥
SignatureAlgorithm signatureAlgorithm = getAlgorithm();
Key signingKey = getKey(base64Security, signatureAlgorithm.getJcaName());
//添加构成JWT的参数
JwtBuilder builder = Jwts.builder().setHeaderParam("typ", "JWT")
.claim("scope", "REFRESH")
.setIssuer(iss)
.setAudience(aud)
.setSubject(userName)
.signWith(signatureAlgorithm, signingKey);
//添加Token过期时间
if (ttlMillis >= 0) {
long expMillis = nowMillis + ttlMillis;
Date exp = new Date(expMillis);
builder.setExpiration(exp).setNotBefore(now);
}
//生成JWT
return builder.compact();
}
/**
* 获取jwt 唯一身份识别码
*
* @return 登录用户信息
*/
public static String createJti() {
return String.valueOf(System.nanoTime());
}
public static LoginUser verifyAndGetUser(String jwt, String base64Security) {
if (StringUtils.isBlank(jwt)) {
log.debug("JWT校验commons:jwt为空,校验失败");
throw new IllegalArgumentException("jwt 不能为空");
}
if (StringUtils.isBlank(base64Security)) {
log.debug("JWT校验commons:base64Security为空,校验失败");
throw new IllegalArgumentException("key 不能为空");
}
if (verify(jwt, base64Security)) {
String userStr = new String(Base64.getUrlDecoder().decode(jwt.split("[.]")[1]));
return JSON.parseObject(userStr, LoginUser.class);
} else {
log.debug("JWT校验commons:verify()失败,校验失败");
}
return null;
}
/**
* 校验jwt
*/
public static LoginUser verifySignedAndGetUser(String jwt, String base64Security) {
if (StringUtils.isBlank(jwt)) {
log.debug("JWT校验commons:jwt为空,校验失败");
throw new IllegalArgumentException("jwt 不能为空");
}
if (StringUtils.isBlank(base64Security)) {
log.debug("JWT校验commons:base64Security为空,校验失败");
throw new IllegalArgumentException("key 不能为空");
}
if (veritySigned(jwt, base64Security)) {
String userStr = new String(Base64.getUrlDecoder().decode(jwt.split("[.]")[1]));
return JSON.parseObject(userStr, LoginUser.class);
} else {
log.debug("JWT校验commons:verify()失败,校验失败");
}
return null;
}
/**
* 获取加密算法
*/
private static SignatureAlgorithm getAlgorithm() {
return SignatureAlgorithm.HS256;
}
private static Key getKey(String base64Security, String algorithm) {
byte[] apiKeySecretBytes = Base64.getDecoder().decode(base64Security);
return new SecretKeySpec(apiKeySecretBytes, algorithm);
}
public static LoginUser checkAndGetUser(String authorization) {
//为空不合法
if (StringUtils.isBlank(authorization)) {
return null;
}
// 格式不合法
if (!authorization.startsWith("Bearer ")) {
return null;
}
String[] jwt = authorization.split("[.]");
if (jwt.length < 3) {
return null;
}
String payload = new String(Base64.getUrlDecoder().decode(jwt[1]));
if (StringUtils.isEmpty(payload)) {
return null;
}
return JSON.parseObject(payload, LoginUser.class);
}
private static Map<String, Object> user2map(LoginUser bean) {
Map<String, Object> map = new HashMap<>(16);
new BeanMap(bean).forEach((k, v) -> {
if ((v instanceof Long || v instanceof BigInteger) && v != null) {
map.put(String.valueOf(k), String.valueOf(v));
} else {
map.put(String.valueOf(k), v);
}
});
map.remove("authenticated");
return map;
}
}
添加BeanFactory
/**
* @Author zqf
* @Date 2022/12/15 16:44
* @Description: bean工厂
*/
@Configuration
public class BeanFactory {
@Autowired
private RedisConnectionFactory redisConnectionFactory;
@Bean("ddbRedisTemplate")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
template.setConnectionFactory(redisConnectionFactory);
JdkSerializationRedisSerializer jdkSerializationRedisSerializer = new JdkSerializationRedisSerializer();
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
template.setKeySerializer(stringRedisSerializer);
template.setValueSerializer(jdkSerializationRedisSerializer);
template.setHashKeySerializer(stringRedisSerializer);
template.setHashValueSerializer(jdkSerializationRedisSerializer);
template.afterPropertiesSet();
return template;
}
}