小程序登录接口
This commit is contained in:
@@ -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));
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
Reference in New Issue
Block a user