11 files added
2 files modified
| | |
| | | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
| | | <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> |
| | | <mybatis.plus.version>3.3.1</mybatis.plus.version> |
| | | <hutool.version>5.3.1</hutool.version> |
| | | <swagger.ui>2.9.2</swagger.ui> |
| | | <tomcat.version>9.0.31</tomcat.version> |
| | | </properties> |
| | | |
| | | <dependencies> |
| | | |
| | | <dependency> |
| | | <groupId>cn.hutool</groupId> |
| | | <artifactId>hutool-all</artifactId> |
| | | <version>${hutool.version}</version> |
| | | </dependency> |
| | | <!-- Spring系列 --> |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
New file |
| | |
| | | package cc.mrbird.febs.common.interceptor; |
| | | |
| | | import cc.mrbird.febs.common.entity.FebsResponse; |
| | | import cc.mrbird.febs.common.utils.AppContants; |
| | | import cc.mrbird.febs.common.utils.RedisUtils; |
| | | import cc.mrbird.febs.common.utils.SpringContextUtil; |
| | | import cc.mrbird.febs.video.entity.VideoMemberEntity; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.hutool.crypto.asymmetric.KeyType; |
| | | import cn.hutool.crypto.asymmetric.RSA; |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.springframework.http.HttpStatus; |
| | | import org.springframework.web.servlet.HandlerInterceptor; |
| | | import org.springframework.web.servlet.ModelAndView; |
| | | |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.IOException; |
| | | |
| | | @Slf4j |
| | | public class LoginInterceptor implements HandlerInterceptor { |
| | | |
| | | private final RedisUtils redisUtils = SpringContextUtil.getBean(RedisUtils.class); |
| | | |
| | | @Override |
| | | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { |
| | | String headerToken = request.getHeader("token"); |
| | | if (StringUtils.isBlank(headerToken)) { |
| | | responseUnAuth(response); |
| | | return false; |
| | | } |
| | | |
| | | String token = resolveToken(headerToken); |
| | | |
| | | if (token == null || AppContants.TIME_OUT.equals(token)) { |
| | | responseUnAuth(response); |
| | | return false; |
| | | } |
| | | |
| | | String userJsonStr = redisUtils.getString(token); |
| | | if (StringUtils.isBlank(userJsonStr)) { |
| | | responseUnAuth(response); |
| | | return false; |
| | | } |
| | | VideoMemberEntity member = JSON.parseObject(userJsonStr, VideoMemberEntity.class); |
| | | |
| | | request.getSession().setAttribute("member", member); |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { |
| | | |
| | | } |
| | | |
| | | @Override |
| | | public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { |
| | | |
| | | } |
| | | |
| | | private void responseUnAuth(HttpServletResponse response) throws IOException { |
| | | response.setCharacterEncoding("UTF-8"); |
| | | response.setContentType("application/json; charset=utf-8"); |
| | | response.getWriter().write(new ObjectMapper().writeValueAsString(new FebsResponse().code(HttpStatus.UNAUTHORIZED))); |
| | | } |
| | | |
| | | private String resolveToken(String token) { |
| | | try { |
| | | RSA rsa = new RSA(AppContants.PRIVATE_KEY, null); |
| | | String[] tokens = StrUtil.split(rsa.decryptStr(token, KeyType.PrivateKey), "_"); |
| | | if (verifyTokenExpired(Long.parseLong(tokens[1]))) { |
| | | return tokens[0]; |
| | | } else { |
| | | return AppContants.TIME_OUT; |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("#解析token异常#", e); |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | private Boolean verifyTokenExpired(Long time) { |
| | | boolean isDebug = true; |
| | | if (!isDebug) { |
| | | long currentTime = System.currentTimeMillis(); |
| | | return currentTime - time <= 30000; |
| | | } |
| | | return true; |
| | | } |
| | | } |
| | | |
New file |
| | |
| | | package cc.mrbird.febs.common.utils; |
| | | |
| | | public class AppContants { |
| | | |
| | | /** |
| | | * 系统用户 |
| | | */ |
| | | public static final String SYSTEM_USER = "system"; |
| | | |
| | | public static final String PUBLIC_KEY = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCzIfAF0gZs9zn9ENRtz6ocHa8MGljmMmCsjLsRvTIAilBMypMJz/VNooAOhd8GTdsWm8FNGVhRauv7RfxorFJ4Um2UbweUQBIZP2pzZMnclHxhUmYZsn/6IaPzijiUNfEjygtE7ezvso/67ecZJwqfrtlbEjqUbRgo17Qj23suwQIDAQAB"; |
| | | |
| | | public static final String PRIVATE_KEY = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALMh8AXSBmz3Of0Q1G3PqhwdrwwaWOYyYKyMuxG9MgCKUEzKkwnP9U2igA6F3wZN2xabwU0ZWFFq6/tF/GisUnhSbZRvB5RAEhk/anNkydyUfGFSZhmyf/oho/OKOJQ18SPKC0Tt7O+yj/rt5xknCp+u2VsSOpRtGCjXtCPbey7BAgMBAAECgYAAgn+23IalJ7z0AejA2T7wLotxet+24/zPcOUVY1bxlnMtDMSHWh6mFmjL4cilMXKGqXHO4NwV+zppsCTMPXVMniI1IhfcyECgFjUrpWNCk30DlqhKePtIUCHdyLrc21mMLLMOQD/Hbga5kHZpR8r5poUAJ5Tnm5rjeyggwDj3MwJBAOnY+dyd39cRPtNLH0ANuR0Hd/WuA/RSRNbBTlXIVlc0hF1QXkgIWT2zA4uvwrFsz3F11YdPdfLgUhkFHlQuhVMCQQDEGhJELXqZ3AMlE9ykhUgv9HaCofGuCvzJnBGDKh4B3ufWG728gCNruoaRmzU8TOeVCABIQ2Un3SAenq0ylYUbAkB1y9PJm0lneAtyulPKm18VTW7TNk5No6eDmqqQMbO0iALpUpO7q2Dw4J03n1jusUYp/FaMq61ZpEAW1Go7s5d7AkEArgsJjTLj7ewDaoPfPrD/6XfJOpVqPvKHepOmQ0g9C6H/FtrWIZeEWFdamZ4ruFH08yL/xSLzg1bQ6/wecZecYwJALY4OP1Z81fhNjzg1AQd1CQQJJXUIkQpxXD/zAS5Cgf7XWfELIA4+86WA8qU1ILYHClFuV0SfxyGvI4ZEmpFosg=="; |
| | | |
| | | /** |
| | | * app用户登陆redis前缀 |
| | | */ |
| | | public static final String APP_LOGIN_PREFIX = "app_"; |
| | | |
| | | public static final String PC_LOGIN_PREFIX = "pc_"; |
| | | |
| | | /** |
| | | * token头部 |
| | | */ |
| | | public static final String TOKEN_HEADER = "Authorization"; |
| | | |
| | | /** |
| | | * token start with |
| | | */ |
| | | public static final String TOKEN_START_WITH = "Bearer "; |
| | | |
| | | /** |
| | | * 账号类型-手机号 |
| | | */ |
| | | public static final String ACCOUNT_TYPE_MOBILE = "1"; |
| | | |
| | | /** |
| | | * 账号类型-邮箱 |
| | | */ |
| | | public static final String ACCOUNT_TYPE_EMAIL = "2"; |
| | | |
| | | /** |
| | | * 系统推荐人id |
| | | */ |
| | | public static final String SYSTEM_REFERER = "rxadr3"; |
| | | |
| | | |
| | | /** |
| | | * 验证码前缀 手机 |
| | | */ |
| | | public static final String VERIFY_CODE_PREFIX = "CODE_SMS_"; |
| | | |
| | | /** |
| | | * 图片后缀 |
| | | */ |
| | | public static final String UPLOAD_IMAGE_SUFFIX = ".jpg"; |
| | | |
| | | public static final String TIME_OUT = "time_out"; |
| | | |
| | | public static final int DEL_FLAG_Y = 1; |
| | | |
| | | public static final int DEL_FLAG_N = 2; |
| | | |
| | | public static final String REDIS_ORDER_OVERTIME_PREFIX = "order_overtime_"; |
| | | public static final String REDIS_ORDER_OVERTIME = "order_overtime_{}_{}"; |
| | | |
| | | public static final String AGENT_LEVEL = "AGENT_LEVEL"; |
| | | public static final String AGENT_LEVEL_REQUIRE = "AGENT_LEVEL_REQUIRE"; |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package cc.mrbird.febs.common.utils; |
| | | |
| | | import org.springframework.data.redis.core.RedisTemplate; |
| | | import org.springframework.stereotype.Component; |
| | | import org.springframework.util.CollectionUtils; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | @Component |
| | | public class RedisUtils { |
| | | |
| | | |
| | | @Resource |
| | | private RedisTemplate<String, Object> redisTemplate; |
| | | |
| | | |
| | | // =============================common============================ |
| | | /** |
| | | * 指定缓存失效时间 |
| | | * @param key 键 |
| | | * @param time 时间(秒) |
| | | * @return |
| | | */ |
| | | public boolean expire(String key, long time) { |
| | | try { |
| | | if (time > 0) { |
| | | redisTemplate.expire(key, time, TimeUnit.SECONDS); |
| | | } |
| | | return true; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 根据key 获取过期时间 |
| | | * @param key 键 不能为null |
| | | * @return 时间(秒) 返回0代表为永久有效 |
| | | */ |
| | | public long getExpire(String key) { |
| | | return redisTemplate.getExpire(key, TimeUnit.SECONDS); |
| | | } |
| | | |
| | | /** |
| | | * 判断key是否存在 |
| | | * @param key 键 |
| | | * @return true 存在 false不存在 |
| | | */ |
| | | public boolean hasKey(String key) { |
| | | try { |
| | | return redisTemplate.hasKey(key); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 删除缓存 |
| | | * @param key 可以传一个值 或多个 |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | public void del(String... key) { |
| | | if (key != null && key.length > 0) { |
| | | if (key.length == 1) { |
| | | redisTemplate.delete(key[0]); |
| | | } else { |
| | | redisTemplate.delete(CollectionUtils.arrayToList(key)); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // ============================String============================= |
| | | /** |
| | | * 普通缓存获取 |
| | | * @param key 键 |
| | | * @return 值 |
| | | */ |
| | | public Object get(String key) { |
| | | return key == null ? null : redisTemplate.opsForValue().get(key); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 普通缓存获取 |
| | | * @param key 键 |
| | | * @return 值 |
| | | */ |
| | | public String getString(String key) { |
| | | Object obj = key == null ? null : redisTemplate.opsForValue().get(key); |
| | | if(obj!=null){ |
| | | return obj.toString(); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * 普通缓存放入 |
| | | * @param key 键 |
| | | * @param value 值 |
| | | * @return true成功 false失败 |
| | | */ |
| | | public boolean set(String key, Object value) { |
| | | try { |
| | | redisTemplate.opsForValue().set(key, value); |
| | | return true; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 普通缓存放入并设置时间 |
| | | * @param key 键 |
| | | * @param value 值 |
| | | * @param time 时间(秒) time要大于0 如果time小于等于0 将设置无限期 |
| | | * @return true成功 false 失败 |
| | | */ |
| | | public boolean set(String key, Object value, long time) { |
| | | try { |
| | | if (time > 0) { |
| | | redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS); |
| | | } else { |
| | | set(key, value); |
| | | } |
| | | return true; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | public boolean setNotExist(String key, Object value, long time) { |
| | | return redisTemplate.opsForValue().setIfAbsent(key, value, time, TimeUnit.SECONDS); |
| | | } |
| | | |
| | | /** |
| | | * 递增 |
| | | * @param key 键 |
| | | * @param delta 要增加几(大于0) |
| | | * @return |
| | | */ |
| | | public long incr(String key, long delta) { |
| | | if (delta < 0) { |
| | | throw new RuntimeException("递增因子必须大于0"); |
| | | } |
| | | return redisTemplate.opsForValue().increment(key, delta); |
| | | } |
| | | |
| | | /** |
| | | * 递减 |
| | | * @param key 键 |
| | | * @param delta 要减少几(小于0) |
| | | * @return |
| | | */ |
| | | public long decr(String key, long delta) { |
| | | if (delta < 0) { |
| | | throw new RuntimeException("递减因子必须大于0"); |
| | | } |
| | | return redisTemplate.opsForValue().increment(key, -delta); |
| | | } |
| | | |
| | | |
| | | // ================================Map================================= |
| | | |
| | | /** |
| | | * HashGet |
| | | * @param key 键 不能为null |
| | | * @param item 项 不能为null |
| | | * @return 值 |
| | | */ |
| | | public Object hget(String key, String item) { |
| | | return redisTemplate.opsForHash().get(key, item); |
| | | } |
| | | |
| | | /** |
| | | * 获取hashKey对应的所有键值 |
| | | * @param key 键 |
| | | * @return 对应的多个键值 |
| | | */ |
| | | public Map<Object, Object> hmget(String key) { |
| | | return redisTemplate.opsForHash().entries(key); |
| | | } |
| | | /** |
| | | * HashSet |
| | | |
| | | * @param key 键 |
| | | * @param map 对应多个键值 |
| | | * @return true 成功 false 失败 |
| | | */ |
| | | public boolean hmset(String key, Map<String, Object> map) { |
| | | try { |
| | | redisTemplate.opsForHash().putAll(key, map); |
| | | return true; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return false; |
| | | } |
| | | } |
| | | /** |
| | | * HashSet 并设置时间 |
| | | * @param key 键 |
| | | * @param map 应多个键值 |
| | | * @param time 时间(秒) |
| | | * @return true成功 false失败 |
| | | */ |
| | | public boolean hmset(String key, Map<String, Object> map, long time) { |
| | | try { |
| | | redisTemplate.opsForHash().putAll(key, map); |
| | | if (time > 0) { |
| | | expire(key, time); |
| | | } |
| | | return true; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 向一张hash表中放入数据,如果不存在将创建 |
| | | * @param key 键 |
| | | * @param item 项 |
| | | * @param value 值 |
| | | * @return true 成功 false失败 |
| | | */ |
| | | public boolean hset(String key, String item, Object value) { |
| | | try { |
| | | redisTemplate.opsForHash().put(key, item, value); |
| | | return true; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return false; |
| | | } |
| | | } |
| | | /** |
| | | * 向一张hash表中放入数据,如果不存在将创建 |
| | | * @param key 键 |
| | | * @param item 项 |
| | | * @param value 值 |
| | | * @param time 时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间 |
| | | * @return true 成功 false失败 |
| | | */ |
| | | public boolean hset(String key, String item, Object value, long time) { |
| | | try { |
| | | redisTemplate.opsForHash().put(key, item, value); |
| | | if (time > 0) { |
| | | expire(key, time); |
| | | } |
| | | return true; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return false; |
| | | } |
| | | } |
| | | /** |
| | | * 删除hash表中的值 |
| | | * @param key 键 不能为null |
| | | * @param item 项 可以使多个 不能为null |
| | | */ |
| | | public void hdel(String key, Object... item) { |
| | | redisTemplate.opsForHash().delete(key, item); |
| | | } |
| | | /** |
| | | * 判断hash表中是否有该项的值 |
| | | * @param key 键 不能为null |
| | | * @param item 项 不能为null |
| | | * @return true 存在 false不存在 |
| | | */ |
| | | public boolean hHasKey(String key, String item) { |
| | | return redisTemplate.opsForHash().hasKey(key, item); |
| | | } |
| | | |
| | | /** |
| | | * hash递增 如果不存在,就会创建一个 并把新增后的值返回 |
| | | * @param key 键 |
| | | * @param item 项 |
| | | * @param by 要增加几(大于0) |
| | | * @return |
| | | */ |
| | | public double hincr(String key, String item, double by) { |
| | | return redisTemplate.opsForHash().increment(key, item, by); |
| | | } |
| | | |
| | | /** |
| | | * hash递减 |
| | | * @param key 键 |
| | | * @param item 项 |
| | | * @param by 要减少记(小于0) |
| | | * @return |
| | | */ |
| | | public double hdecr(String key, String item, double by) { |
| | | return redisTemplate.opsForHash().increment(key, item, -by); |
| | | } |
| | | // ============================set============================= |
| | | /** |
| | | * 根据key获取Set中的所有值 |
| | | * @param key 键 |
| | | * @return |
| | | */ |
| | | public Set<Object> sGet(String key) { |
| | | try { |
| | | return redisTemplate.opsForSet().members(key); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return null; |
| | | } |
| | | } |
| | | /** |
| | | * 根据value从一个set中查询,是否存在 |
| | | * @param key 键 |
| | | * @param value 值 |
| | | * @return true 存在 false不存在 |
| | | */ |
| | | public boolean sHasKey(String key, Object value) { |
| | | try { |
| | | return redisTemplate.opsForSet().isMember(key, value); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return false; |
| | | } |
| | | } |
| | | /** |
| | | * 将数据放入set缓存 |
| | | * @param key 键 |
| | | * @param values 值 可以是多个 |
| | | * @return 成功个数 |
| | | */ |
| | | public long sSet(String key, Object... values) { |
| | | try { |
| | | return redisTemplate.opsForSet().add(key, values); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | |
| | | return 0; |
| | | } |
| | | } |
| | | /** |
| | | 336 |
| | | * 将set数据放入缓存 |
| | | 337 |
| | | * @param key 键 |
| | | * @param time 时间(秒) |
| | | * @param values 值 可以是多个 |
| | | * @return 成功个数 |
| | | */ |
| | | public long sSetAndTime(String key, long time, Object... values) { |
| | | try { |
| | | Long count = redisTemplate.opsForSet().add(key, values); |
| | | if (time > 0) |
| | | expire(key, time); |
| | | return count; |
| | | |
| | | }catch(Exception e) { |
| | | e.printStackTrace(); |
| | | return 0; |
| | | } |
| | | } |
| | | /** |
| | | * 获取set缓存的长度 |
| | | * @param key 键 |
| | | * @return |
| | | */ |
| | | |
| | | public long sGetSetSize(String key) { |
| | | try { |
| | | return redisTemplate.opsForSet().size(key); |
| | | |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return 0; |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 移除值为value的 |
| | | * @param key 键 |
| | | * @param values 值 可以是多个 |
| | | * @return 移除的个数 |
| | | |
| | | */ |
| | | public long setRemove(String key, Object... values) { |
| | | try { |
| | | Long count = redisTemplate.opsForSet().remove(key, values); |
| | | return count; |
| | | |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return 0; |
| | | } |
| | | } |
| | | // ===============================list================================= |
| | | /** |
| | | * 获取list缓存的内容 * @param key 键 |
| | | * @param start 开始 |
| | | * @param end 结束 0 到 -1代表所有值 |
| | | * @return |
| | | */ |
| | | public List<Object> lGet(String key, long start, long end) { |
| | | try { |
| | | return redisTemplate.opsForList().range(key, start, end); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return null; |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 获取list缓存的长度 |
| | | * @param key 键 |
| | | |
| | | * @return |
| | | */ |
| | | public long lGetListSize(String key) { try { |
| | | return redisTemplate.opsForList().size(key); |
| | | } catch (Exception e) { |
| | | |
| | | e.printStackTrace(); |
| | | return 0; |
| | | } |
| | | } /** |
| | | * 通过索引 获取list中的值 |
| | | * @param key 键 |
| | | * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推 |
| | | * @return |
| | | */ |
| | | public Object lGetIndex(String key, long index) { |
| | | |
| | | try { |
| | | return redisTemplate.opsForList().index(key, index); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 将list放入缓存 |
| | | * @param key 键 |
| | | * @param value 值 |
| | | * @return |
| | | */ |
| | | public boolean lSet(String key, Object value) { |
| | | try { |
| | | redisTemplate.opsForList().rightPush(key, value); |
| | | return true; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 将list放入缓存 |
| | | * @param key 键 |
| | | * @param value 值 |
| | | * @param time 时间(秒) |
| | | * @return |
| | | */ |
| | | public boolean lSet(String key, Object value, long time) { |
| | | try { |
| | | redisTemplate.opsForList().rightPush(key, value); |
| | | if (time > 0) |
| | | expire(key, time); |
| | | return true; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return false; |
| | | } |
| | | } |
| | | /** |
| | | * 将list放入缓存 |
| | | * @param key 键 |
| | | * @param value 值 |
| | | * @return |
| | | */ |
| | | public boolean lSet(String key, List<Object> value) { |
| | | try { |
| | | redisTemplate.opsForList().rightPushAll(key, value); |
| | | return true; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return false; |
| | | } |
| | | } |
| | | /** |
| | | * 将list放入缓存 |
| | | * |
| | | * @param key 键 |
| | | * @param value 值 |
| | | * @param time 时间(秒) |
| | | * @return |
| | | */ |
| | | public boolean lSet(String key, List<Object> value, long time) { |
| | | try { |
| | | redisTemplate.opsForList().rightPushAll(key, value); |
| | | if (time > 0) |
| | | expire(key, time); |
| | | return true; |
| | | |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return false; |
| | | } |
| | | } |
| | | /** |
| | | * 根据索引修改list中的某条数据 |
| | | * @param key 键 |
| | | * @param index 索引 |
| | | * @param value 值 |
| | | * @return |
| | | */ |
| | | public boolean lUpdateIndex(String key, long index, Object value) { |
| | | try { |
| | | redisTemplate.opsForList().set(key, index, value); |
| | | return true; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 移除N个值为value |
| | | * @param key 键 |
| | | * @param count 移除多少个 |
| | | * @param value 值 |
| | | * @return 移除的个数 |
| | | */ |
| | | public long lRemove(String key, long count, Object value) { |
| | | try { |
| | | return redisTemplate.opsForList().remove(key, count, value); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return 0; |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | package cc.mrbird.febs.common.utils; |
| | | |
| | | import java.util.Random; |
| | | |
| | | public class ShareCodeUtil { |
| | | |
| | | /** |
| | | * 自定义进制(0,1没有加入,容易与o,l混淆) |
| | | */ |
| | | // private static final char[] r=new char[]{'q', 'w', 'e', '8', 'a', 's', '2', 'd', 'z', 'x', '9', 'c', '7', 'p', '5', 'i', 'k', '3', 'm', 'j', 'u', 'f', 'r', '4', 'v', 'y', 'l', 't', 'n', '6', 'b', 'g', 'h'}; |
| | | private static final char[] r = new char[]{'1', '2', '3', '4', '5', '6', '7', '8', '9'}; |
| | | |
| | | /** |
| | | * (不能与自定义进制有重复) |
| | | */ |
| | | private static final char b = '0'; |
| | | |
| | | /** |
| | | * 进制长度 |
| | | */ |
| | | private static final int binLen = r.length; |
| | | |
| | | /** |
| | | * 序列最小长度 |
| | | */ |
| | | private static final int s = 8; |
| | | |
| | | /** |
| | | * 根据ID生成六位随机码 |
| | | * |
| | | * @param id ID |
| | | * @return 随机码 |
| | | */ |
| | | public static String toSerialCode(long id) { |
| | | char[] buf = new char[32]; |
| | | int charPos = 32; |
| | | |
| | | while ((id / binLen) > 0) { |
| | | int ind = (int) (id % binLen); |
| | | buf[--charPos] = r[ind]; |
| | | id /= binLen; |
| | | } |
| | | buf[--charPos] = r[(int) (id % binLen)]; |
| | | String str = new String(buf, charPos, (32 - charPos)); |
| | | // 不够长度的自动随机补全 |
| | | if (str.length() < s) { |
| | | StringBuilder sb = new StringBuilder(); |
| | | sb.append(b); |
| | | Random rnd = new Random(); |
| | | for (int i = 1; i < s - str.length(); i++) { |
| | | sb.append(r[rnd.nextInt(binLen)]); |
| | | } |
| | | str += sb.toString(); |
| | | } |
| | | return str; |
| | | } |
| | | |
| | | /** |
| | | * 根据ID生成六位随机码 |
| | | * |
| | | * @param id ID |
| | | * @return 随机码 |
| | | */ |
| | | public static String toSerialNumberCode(long id) { |
| | | char[] buf = new char[32]; |
| | | int charPos = 32; |
| | | |
| | | while ((id / binLen) > 0) { |
| | | int ind = (int) (id % binLen); |
| | | buf[--charPos] = r[ind]; |
| | | id /= binLen; |
| | | } |
| | | buf[--charPos] = r[(int) (id % binLen)]; |
| | | String str = new String(buf, charPos, (32 - charPos)); |
| | | // 不够长度的自动随机补全 |
| | | if (str.length() < s) { |
| | | StringBuilder sb = new StringBuilder(); |
| | | sb.append(b); |
| | | Random rnd = new Random(); |
| | | for (int i = 1; i < s - str.length(); i++) { |
| | | sb.append(r[rnd.nextInt(binLen)]); |
| | | } |
| | | str += sb.toString(); |
| | | } |
| | | return str; |
| | | } |
| | | |
| | | public static long codeToId(String code) { |
| | | char chs[] = code.toCharArray(); |
| | | long res = 0L; |
| | | for (int i = 0; i < chs.length; i++) { |
| | | int ind = 0; |
| | | for (int j = 0; j < binLen; j++) { |
| | | if (chs[i] == r[j]) { |
| | | ind = j; |
| | | break; |
| | | } |
| | | } |
| | | if (chs[i] == b) { |
| | | break; |
| | | } |
| | | if (i > 0) { |
| | | res = res * binLen + ind; |
| | | } else { |
| | | res = ind; |
| | | } |
| | | } |
| | | return res; |
| | | } |
| | | } |
New file |
| | |
| | | package cc.mrbird.febs.video.controller; |
| | | |
| | | import cc.mrbird.febs.common.entity.FebsResponse; |
| | | import cc.mrbird.febs.video.dto.LoginDto; |
| | | import cc.mrbird.febs.video.dto.RegisterDto; |
| | | import cc.mrbird.febs.video.service.IApiVideoMemberService; |
| | | import io.swagger.annotations.Api; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | @Slf4j |
| | | @CrossOrigin("*") |
| | | @RequiredArgsConstructor |
| | | @RestController |
| | | @RequestMapping(value = "/api/login") |
| | | @Api(value = "ApiLoginController", tags = "登录注册类") |
| | | public class ApiLoginController { |
| | | |
| | | private final IApiVideoMemberService memberService; |
| | | |
| | | @ApiOperation(value = "app注册接口", notes = "app注册接口") |
| | | @PostMapping(value = "/register") |
| | | public FebsResponse register(@RequestBody RegisterDto registerDto) { |
| | | return memberService.register(registerDto); |
| | | } |
| | | |
| | | |
| | | @ApiOperation(value = "账号密码登录接口", notes = "账号密码登录接口") |
| | | @PostMapping(value = "/toLogin") |
| | | public FebsResponse login(@RequestBody LoginDto loginDto) { |
| | | return memberService.toLogin(loginDto); |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package cc.mrbird.febs.video.dto; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import javax.validation.constraints.NotBlank; |
| | | |
| | | @Data |
| | | @ApiModel(value = "LoginDto", description = "登录接口参数接收类") |
| | | public class LoginDto { |
| | | |
| | | @NotBlank(message = "账号不能为空") |
| | | @ApiModelProperty(value = "账号", example = "15773001234") |
| | | private String account; |
| | | |
| | | @NotBlank(message = "密码不能为空") |
| | | @ApiModelProperty(value = "密码", example = "123456") |
| | | private String password; |
| | | } |
New file |
| | |
| | | package cc.mrbird.febs.video.dto; |
| | | |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import javax.validation.constraints.NotBlank; |
| | | |
| | | @Data |
| | | @ApiModel(value = "RegisterDto", description = "用户注册参数接收类") |
| | | public class RegisterDto { |
| | | |
| | | @NotBlank(message = "账号不能为空") |
| | | @ApiModelProperty(value = "手机号", example = "15773001234") |
| | | private String account; |
| | | |
| | | @NotBlank(message = "密码不能为空") |
| | | @ApiModelProperty(value = "密码", example = "123456") |
| | | private String password; |
| | | |
| | | @ApiModelProperty(value = "类型 1-手机号 2-邮箱", example = "1") |
| | | private String type = "1"; |
| | | |
| | | // @NotBlank(message = "验证码不能为空") |
| | | // @ApiModelProperty(value = "验证码", example = "123456") |
| | | // private String code; |
| | | |
| | | // @NotBlank(message = "邀请码不能为空") |
| | | // @ApiModelProperty(value = "邀请码") |
| | | // private String inviteId; |
| | | |
| | | } |
| | |
| | | private Integer isVip; |
| | | |
| | | /** |
| | | * 是 |
| | | */ |
| | | public static final Integer ISVIP_STATUS_YES = 1; |
| | | /** |
| | | * 否 |
| | | */ |
| | | public static final Integer ISVIP_STATUS_NO = 2; |
| | | |
| | | /** |
| | | * 账号状态 1/正常 2/禁用 |
| | | */ |
| | | private Integer accountStatus; |
| | | /** |
| | | * 启用 |
| | | */ |
| | | public static final Integer ACCOUNT_STATUS_ENABLE = 1; |
| | | /** |
| | | * 禁用 |
| | | */ |
| | | public static final Integer ACCOUNT_STATUS_DISABLED = 2; |
| | | |
| | | /** |
| | | * 账号类型 1/正常 2/测试 |
| | | */ |
| | | private Integer accountType; |
| | | |
| | | /** |
| | | * 正常账号 |
| | | */ |
| | | public static final Integer ACCOUNT_TYPE_NORMAL = 1; |
| | | /** |
| | | * 测试账号 |
| | | */ |
| | | public static final Integer ACCOUNT_TYPE_TEST = 2; |
| | | } |
New file |
| | |
| | | package cc.mrbird.febs.video.mapper; |
| | | |
| | | import cc.mrbird.febs.video.entity.VideoMemberEntity; |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | | public interface VideoMemberMapper extends BaseMapper<VideoMemberEntity> { |
| | | |
| | | VideoMemberEntity selectInfoByAccount(@Param("account") String account); |
| | | |
| | | VideoMemberEntity selectInfoByInviteId(@Param("inviteId")String parentId); |
| | | |
| | | VideoMemberEntity selectInfoByAccountAndPwd(@Param("account") String account, @Param("password") String password); |
| | | |
| | | } |
New file |
| | |
| | | package cc.mrbird.febs.video.service; |
| | | |
| | | import cc.mrbird.febs.common.entity.FebsResponse; |
| | | import cc.mrbird.febs.video.dto.LoginDto; |
| | | import cc.mrbird.febs.video.dto.RegisterDto; |
| | | import cc.mrbird.febs.video.entity.VideoMemberEntity; |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | |
| | | public interface IApiVideoMemberService extends IService<VideoMemberEntity> { |
| | | |
| | | FebsResponse register(RegisterDto registerDto); |
| | | |
| | | FebsResponse toLogin(LoginDto loginDto); |
| | | } |
New file |
| | |
| | | package cc.mrbird.febs.video.service.impl; |
| | | |
| | | import cc.mrbird.febs.common.entity.FebsResponse; |
| | | import cc.mrbird.febs.common.exception.FebsException; |
| | | import cc.mrbird.febs.common.utils.AppContants; |
| | | import cc.mrbird.febs.common.utils.RedisUtils; |
| | | import cc.mrbird.febs.common.utils.ShareCodeUtil; |
| | | import cc.mrbird.febs.video.dto.LoginDto; |
| | | import cc.mrbird.febs.video.dto.RegisterDto; |
| | | import cc.mrbird.febs.video.entity.VideoMemberEntity; |
| | | import cc.mrbird.febs.video.mapper.VideoMemberMapper; |
| | | import cc.mrbird.febs.video.service.IApiVideoMemberService; |
| | | import cn.hutool.core.util.IdUtil; |
| | | import cn.hutool.core.util.ObjectUtil; |
| | | import cn.hutool.core.util.StrUtil; |
| | | import cn.hutool.crypto.SecureUtil; |
| | | import cn.hutool.crypto.asymmetric.KeyType; |
| | | import cn.hutool.crypto.asymmetric.RSA; |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | @Slf4j |
| | | @Service |
| | | @RequiredArgsConstructor |
| | | public class ApiVideoMemberServiceImpl extends ServiceImpl<VideoMemberMapper, VideoMemberEntity> implements IApiVideoMemberService { |
| | | |
| | | private final RedisUtils redisUtils; |
| | | |
| | | @Override |
| | | public FebsResponse register(RegisterDto registerDto) { |
| | | VideoMemberEntity videoMember = this.baseMapper.selectInfoByAccount(registerDto.getAccount()); |
| | | if (videoMember != null) { |
| | | throw new FebsException("该账号已被占用"); |
| | | } |
| | | |
| | | // String account = registerDto.getAccount(); |
| | | // String code = registerDto.getCode(); |
| | | // boolean flags = commonService.verifyCode(account, code); |
| | | // if(!flags) { |
| | | // throw new FebsException("验证码错误"); |
| | | // } |
| | | |
| | | videoMember = new VideoMemberEntity(); |
| | | videoMember.setPassword(SecureUtil.md5(registerDto.getPassword())); |
| | | |
| | | // 判断账号类型 |
| | | if (AppContants.ACCOUNT_TYPE_MOBILE.equals(registerDto.getType())) { |
| | | videoMember.setPhone(registerDto.getAccount()); |
| | | } else { |
| | | videoMember.setEmail(registerDto.getAccount()); |
| | | } |
| | | |
| | | // Integer count = this.baseMapper.selectCount(null); |
| | | // if (count != null && count != 0) { |
| | | // MallMember inviteMember = this.baseMapper.selectInfoByInviteId(registerDto.getInviteId()); |
| | | // if (inviteMember == null) { |
| | | // throw new FebsException("邀请码不存在"); |
| | | // } |
| | | // |
| | | // mallMember.setReferrerId(registerDto.getInviteId()); |
| | | // |
| | | // } |
| | | videoMember.setName(registerDto.getAccount()); |
| | | videoMember.setAccountStatus(VideoMemberEntity.ACCOUNT_STATUS_ENABLE); |
| | | videoMember.setAccountType(VideoMemberEntity.ACCOUNT_TYPE_NORMAL); |
| | | videoMember.setIsVip(VideoMemberEntity.ISVIP_STATUS_NO); |
| | | |
| | | this.baseMapper.insert(videoMember); |
| | | |
| | | String inviteId = ShareCodeUtil.toSerialCode(videoMember.getId()); |
| | | videoMember.setInviteId(inviteId); |
| | | |
| | | //推荐人和推荐人链 |
| | | boolean flag = false; |
| | | String parentId = videoMember.getRefererId(); |
| | | if (StrUtil.isBlank(parentId)) { |
| | | flag = true; |
| | | } |
| | | String ids = ""; |
| | | while (!flag) { |
| | | if (StrUtil.isBlank(ids)) { |
| | | ids += parentId; |
| | | } else { |
| | | ids += ("," + parentId); |
| | | } |
| | | VideoMemberEntity parentMember = this.baseMapper.selectInfoByInviteId(parentId); |
| | | if (parentMember == null) { |
| | | break; |
| | | } |
| | | parentId = parentMember.getRefererId(); |
| | | if (StrUtil.isBlank(parentMember.getRefererId())) { |
| | | flag = true; |
| | | } |
| | | } |
| | | |
| | | if (StrUtil.isNotBlank(ids)) { |
| | | videoMember.setRefererIds(ids); |
| | | } |
| | | this.baseMapper.updateById(videoMember); |
| | | |
| | | // MallMemberWallet wallet = new MallMemberWallet(); |
| | | // wallet.setBalance(BigDecimal.ZERO); |
| | | // wallet.setMemberId(mallMember.getId()); |
| | | // mallMemberWalletMapper.insert(wallet); |
| | | return new FebsResponse().success().message("注册成功"); |
| | | } |
| | | |
| | | @Override |
| | | public FebsResponse toLogin(LoginDto loginDto) { |
| | | String md5Pwd = SecureUtil.md5(loginDto.getPassword()); |
| | | |
| | | VideoMemberEntity videoMember = this.baseMapper.selectInfoByAccountAndPwd(loginDto.getAccount(), md5Pwd); |
| | | if (videoMember == null) { |
| | | throw new FebsException("用户不存在或账号密码错误"); |
| | | } |
| | | |
| | | if (videoMember.ACCOUNT_STATUS_DISABLED.equals(videoMember.getAccountStatus())) { |
| | | throw new FebsException("该账号存在异常, 暂限制登录"); |
| | | } |
| | | |
| | | String redisKey = AppContants.APP_LOGIN_PREFIX + videoMember.getId(); |
| | | String existToken = redisUtils.getString(redisKey); |
| | | if (StrUtil.isNotBlank(existToken)) { |
| | | Object o = redisUtils.get(existToken); |
| | | if (ObjectUtil.isNotEmpty(o)) { |
| | | redisUtils.del(existToken); |
| | | } |
| | | } |
| | | |
| | | String token = IdUtil.simpleUUID(); |
| | | redisUtils.set(token, JSONObject.toJSONString(videoMember), 360000); |
| | | redisUtils.set(redisKey, token, 360000); |
| | | Map<String, Object> authInfo = new HashMap<>(); |
| | | authInfo.put("token", token); |
| | | authInfo.put("rasToken", generateAsaToken(token)); |
| | | return new FebsResponse().success().data(authInfo); |
| | | } |
| | | |
| | | |
| | | public String generateAsaToken(String token) { |
| | | RSA rsa = new RSA(null, AppContants.PUBLIC_KEY); |
| | | return rsa.encryptBase64(token + "_" + System.currentTimeMillis(), KeyType.PublicKey); |
| | | } |
| | | } |
New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| | | <mapper namespace="cc.mrbird.febs.video.mapper.VideoMemberMapper"> |
| | | |
| | | <select id="selectInfoByAccount" resultType="cc.mrbird.febs.video.entity.VideoMemberEntity"> |
| | | select * from video_member where phone=#{account} or email=#{account} or invite_id=#{account} |
| | | </select> |
| | | |
| | | <select id="selectInfoByInviteId" resultType="cc.mrbird.febs.video.entity.VideoMemberEntity"> |
| | | select * from video_member where invite_id=#{inviteId} |
| | | </select> |
| | | |
| | | <select id="selectInfoByAccountAndPwd" resultType="cc.mrbird.febs.video.entity.VideoMemberEntity"> |
| | | select * from mall_member where (phone=#{account} or email=#{account}) and password=#{password} |
| | | </select> |
| | | |
| | | </mapper> |