小程序登录接口

This commit is contained in:
2023-09-25 09:17:53 +08:00
parent e06438f776
commit e0fd0c9822
27 changed files with 1139 additions and 7 deletions

View File

@@ -0,0 +1,64 @@
package com.atguigu.ssyx.common.utils;
import io.jsonwebtoken.*;
import org.springframework.util.StringUtils;
import java.util.Date;
/**
* ClassName: JwtHelper
* Package: com.atguigu.ssyx.common.utils
*
* @author yovinchen
* @Create 2023/9/22 15:50
*/
public class JwtHelper {
private static final long tokenExpiration = 365L * 24 * 60 * 60 * 1000;
private static final String tokenSignKey = "ssyx";
public static String createToken(Long userId, String userName) {
String token = Jwts.builder()
.setSubject("ssyx-USER")
.setExpiration(new Date(System.currentTimeMillis() + tokenExpiration))
.claim("userId", userId)
.claim("userName", userName)
.signWith(SignatureAlgorithm.HS512, tokenSignKey)
.compressWith(CompressionCodecs.GZIP)
.compact();
return token;
}
public static Long getUserId(String token) {
if (StringUtils.isEmpty(token)) return null;
Jws<Claims> claimsJws = Jwts.parser()
.setSigningKey(tokenSignKey)
.parseClaimsJws(token);
Claims claims = claimsJws.getBody();
Integer userId = (Integer) claims.get("userId");
return userId.longValue();
// return 1L;
}
public static String getUserName(String token) {
if (StringUtils.isEmpty(token)) return "";
Jws<Claims> claimsJws = Jwts.parser()
.setSigningKey(tokenSignKey)
.parseClaimsJws(token);
Claims claims = claimsJws.getBody();
return (String) claims.get("userName");
}
public static void removeToken(String token) {
//jwttoken无需删除客户端扔掉即可。
}
public static void main(String[] args) {
String token = JwtHelper.createToken(7L, "admin");
System.out.println(token);
System.out.println(JwtHelper.getUserId(token));
System.out.println(JwtHelper.getUserName(token));
}
}

View File

@@ -0,0 +1,50 @@
package com.atguigu.ssyx.common.auth;
import com.atguigu.ssyx.vo.user.UserLoginVo;
/**
* ClassName: AuthContextHolder
* Package: com.atguigu.ssyx.common.auth
*
* @author yovinchen
* @Create 2023/9/22 17:40
*/
//ThreadLocal工具类
public class AuthContextHolder {
//用户id
private static final ThreadLocal<Long> userId = new ThreadLocal<>();
//用户仓库id
private static final ThreadLocal<Long> wareId = new ThreadLocal<>();
//用户信息对象
private static final ThreadLocal<UserLoginVo> userLoginVo = new ThreadLocal<>();
public static Long getUserId() {
return userId.get();
}
//userId操作的方法
public static void setUserId(Long _userId) {
userId.set(_userId);
}
public static Long getWareId() {
return wareId.get();
}
public static void setWareId(Long _wareId) {
wareId.set(_wareId);
}
public static UserLoginVo getUserLoginVo() {
return userLoginVo.get();
}
public static void setUserLoginVo(UserLoginVo _userLoginVo) {
userLoginVo.set(_userLoginVo);
}
}

View File

@@ -0,0 +1,30 @@
package com.atguigu.ssyx.common.auth;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import javax.annotation.Resource;
/**
* ClassName: LoginMvcConfigurerAdapter
* Package: com.atguigu.ssyx.common.auth
*
* @author yovinchen
* @Create 2023/9/22 23:58
*/
@Configuration
public class LoginMvcConfigurerAdapter extends WebMvcConfigurationSupport {
@Resource
private RedisTemplate redisTemplate;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new UserLoginInterceptor(redisTemplate))
.addPathPatterns("/api/**")
.excludePathPatterns("/api/user/weixin/wxLogin/*");
super.addInterceptors(registry);
}
}

View File

@@ -0,0 +1,53 @@
package com.atguigu.ssyx.common.auth;
import com.atguigu.ssyx.common.constant.RedisConst;
import com.atguigu.ssyx.common.utils.JwtHelper;
import com.atguigu.ssyx.vo.user.UserLoginVo;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* ClassName: UserLoginInterceptor
* Package: com.atguigu.ssyx.common.auth
*
* @author yovinchen
* @Create 2023/9/22 23:47
*/
public class UserLoginInterceptor implements HandlerInterceptor {
private final RedisTemplate redisTemplate;
public UserLoginInterceptor(RedisTemplate redisTemplate) {
this.redisTemplate = redisTemplate;
}
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
this.getUserLoginVo(request);
return true;
}
private void getUserLoginVo(HttpServletRequest request) {
//从请求头获取token
String token = request.getHeader("token");
//判断token不为空
if (!StringUtils.isEmpty(token)) {
//从token获取userId
Long userId = JwtHelper.getUserId(token);
//根据userId到Redis获取用户信息
UserLoginVo userLoginVo = (UserLoginVo) redisTemplate.opsForValue()
.get(RedisConst.USER_LOGIN_KEY_PREFIX + userId);
//获取数据放到ThreadLocal里面
if (userLoginVo != null) {
AuthContextHolder.setUserId(userLoginVo.getUserId());
AuthContextHolder.setWareId(userLoginVo.getWareId());
AuthContextHolder.setUserLoginVo(userLoginVo);
}
}
}
}

View File

@@ -0,0 +1,105 @@
package com.atguigu.ssyx.common.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.lang.reflect.Method;
import java.time.Duration;
/**
* ClassName: RedisConfig
* Package: com.atguigu.ssyx.common.config
* Redis配置类
*
* @author yovinchen
* @Create 2023/9/22 15:55
*/
@Configuration
@EnableCaching
public class RedisConfig {
// 使用默认标签做缓存
@Bean
public KeyGenerator wiselyKeyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass()
.getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
}
};
}
// 声明模板
/*
ref = 表示引用
value = 具体的值
<bean class="org.springframework.data.redis.core.RedisTemplate" >
<property name="defaultSerializer" ref = "">
</bean>
*/
// 工具类:
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
// 将Redis 中 string hash 数据类型,自动序列化!
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// 配置序列化(解决乱码的问题),过期时间600秒
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofDays(365))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
return cacheManager;
}
}

View File

@@ -0,0 +1,49 @@
package com.atguigu.ssyx.common.constant;
/**
* ClassName: RedisConst
* Package: com.atguigu.ssyx.common.constant
* Redis常量配置类
*
* @author yovinchen
* @Create 2023/9/22 15:57
*/
public class RedisConst {
public static final String SKUKEY_PREFIX = "sku:";
public static final String SKUKEY_SUFFIX = ":info";
//单位:秒
public static final long SKUKEY_TIMEOUT = 24 * 60 * 60;
// 定义变量,记录空对象的缓存过期时间 缓存穿透key的过期时间
public static final long SKUKEY_TEMPORARY_TIMEOUT = 10 * 60;
//单位:秒 尝试获取锁的最大等待时间
public static final long SKULOCK_EXPIRE_PX1 = 1;
//单位:秒 锁的持有时间
public static final long SKULOCK_EXPIRE_PX2 = 1;
public static final String SKULOCK_SUFFIX = ":lock";
public static final String USER_KEY_PREFIX = "user:";
public static final String USER_CART_KEY_SUFFIX = ":cart";
public static final long USER_CART_EXPIRE = 60 * 60 * 24 * 7;
public static final String SROCK_INFO = "stock:info:";
public static final String ORDER_REPEAT = "order:repeat:";
//用户登录
public static final String USER_LOGIN_KEY_PREFIX = "user:login:";
public static final String ADMIN_LOGIN_KEY_PREFIX = "admin:login:";
// public static final String userinfoKey_suffix = ":info";
public static final int USERKEY_TIMEOUT = 365;
public static final String ORDER_SKU_MAP = "order:sku:";
//秒杀商品前缀
public static final String SECKILL_TIME_MAP = "seckill:time:map";
public static final String SECKILL_SKU_MAP = "seckill:sku:map";
public static final String SECKILL_SKU_LIST = "seckill:sku:list:";
public static final String SECKILL_USER_MAP = "seckill:user:map:";
public static final String SECKILL_ORDERS_USERS = "seckill:orders:users";
public static final String SECKILL_STOCK_PREFIX = "seckill:stock:";
public static final String SECKILL_USER = "seckill:user:";
//用户锁定时间 单位:秒
public static final int SECKILL__TIMEOUT = 60 * 60;
}