threadLocal = new ThreadLocal<>();
+
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+ String accessToken = request.getHeader("token");
+
+ if (accessToken == null) {
+ accessToken = request.getParameter("token");
+ }
+
+ //不为空
+ if (StringUtils.isNotBlank(accessToken)) {
+ Claims claims = JWTUtil.checkJWT(accessToken);
+ if (claims == null) {
+ //未登录
+ CommonUtil.sendJsonMessage(response, JsonData.buildResult(BizCodeEnum.ACCOUNT_UNLOGIN));
+ return false;
+ }
+ long userId = Long.valueOf(claims.get("id").toString());
+ String headImg = (String) claims.get("head_img");
+ String name = (String) claims.get("name");
+ String mail = (String) claims.get("mail");
+
+ LoginUser loginUser = new LoginUser();
+ loginUser.setId(userId);
+ loginUser.setMail(mail);
+ loginUser.setHeadImg(headImg);
+ loginUser.setName(name);
+
+ //通过threadlocal传递用户信息
+ threadLocal.set(loginUser);
+ return true;
+ }
+ //未登录
+ CommonUtil.sendJsonMessage(response, JsonData.buildResult(BizCodeEnum.ACCOUNT_UNLOGIN));
+ return false;
+ }
+
+ @Override
+ public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
+ HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
+ }
+
+ @Override
+ public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
+ HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
+ }
+}
diff --git a/xdclass-common/src/main/java/net/jieyuu/model/LoginUser.java b/xdclass-common/src/main/java/net/jieyuu/model/LoginUser.java
new file mode 100644
index 0000000..5d337f2
--- /dev/null
+++ b/xdclass-common/src/main/java/net/jieyuu/model/LoginUser.java
@@ -0,0 +1,29 @@
+package net.jieyuu.model;
+
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Data;
+
+@Data
+public class LoginUser {
+ /**
+ * 主键
+ */
+ private Long id;
+
+ /**
+ * 名称
+ */
+ private String name;
+
+ /**
+ * 头像
+ */
+ @JsonProperty("head_img")
+ private String headImg;
+ /**
+ * 邮箱
+ */
+ private String mail;
+
+}
diff --git a/xdclass-common/src/main/java/net/jieyuu/utils/CommonUtil.java b/xdclass-common/src/main/java/net/jieyuu/utils/CommonUtil.java
index 03ea281..d05dbbb 100644
--- a/xdclass-common/src/main/java/net/jieyuu/utils/CommonUtil.java
+++ b/xdclass-common/src/main/java/net/jieyuu/utils/CommonUtil.java
@@ -1,12 +1,20 @@
package net.jieyuu.utils;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.extern.slf4j.Slf4j;
+
import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Writer;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.util.Random;
import java.util.UUID;
+@Slf4j
public class CommonUtil {
/**
@@ -108,11 +116,13 @@ public class CommonUtil {
/**
* 获取当前时间戳
+ *
* @return
*/
- public static long getCurrentTimestamp(){
+ public static long getCurrentTimestamp() {
return System.currentTimeMillis();
}
+
/**
* 生成指定长度随机串
*
@@ -120,6 +130,7 @@ public class CommonUtil {
* @return
*/
private static final String ALL_CHAR_NUM = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
public static String getStringNumRandom(int length) {
//生成随机数字和字母,
Random random = new Random();
@@ -130,4 +141,26 @@ public class CommonUtil {
return saltString.toString();
}
+ /**
+ * 响应json数据给前端
+ * @param response
+ * @param obj
+ */
+ public static void sendJsonMessage(HttpServletResponse response, Object obj) {
+ ObjectMapper objectMapper = new ObjectMapper();
+
+ response.setContentType("application/json; charset=utf-8");
+
+ try(PrintWriter writer=response.getWriter()){
+ writer.print(objectMapper.writeValueAsString(obj));
+ writer.close();
+
+ response.flushBuffer();
+
+ }catch(IOException e){
+ log.warn("响应json数据给前端异常:{}",e);
+ }
+
+ }
+
}
diff --git a/xdclass-common/src/main/java/net/jieyuu/utils/JWTUtil.java b/xdclass-common/src/main/java/net/jieyuu/utils/JWTUtil.java
new file mode 100644
index 0000000..149eb13
--- /dev/null
+++ b/xdclass-common/src/main/java/net/jieyuu/utils/JWTUtil.java
@@ -0,0 +1,81 @@
+package net.jieyuu.utils;
+
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import lombok.extern.slf4j.Slf4j;
+import net.jieyuu.model.LoginUser;
+
+import java.util.Date;
+
+
+@Slf4j
+public class JWTUtil {
+
+ /**
+ * 过期时间
+ * 1000毫秒 * 60秒 * 60分钟 * 24小时 * 7天 * 10
+ */
+ private static final long EXPIRE = 1000 * 60 * 60 * 24 * 7 * 10;
+
+ /**
+ * 加密密钥
+ */
+ private static final String SECRET = "jieyuu.xyz";
+ /**
+ * 令牌前缀
+ */
+ private static final String TOKEN_PREFIX = "Jieyuushop";
+
+ /**
+ * 令牌前缀
+ */
+ private static final String SUBJECT = "Jieyuu";
+
+ /**
+ * 根据用户信息,生成令牌
+ *
+ * @param loginUser
+ * @return
+ */
+ public static String geneJsonWebToken(LoginUser loginUser) {
+ if (loginUser == null) {
+ throw new NullPointerException("loginUser对象为空");
+ }
+ long userid = loginUser.getId();
+
+ String token = Jwts.builder().setSubject(SUBJECT)
+ .claim("head_img", loginUser.getHeadImg())
+ .claim("id", userid)
+ .claim("name", loginUser.getName())
+ .claim("mail", loginUser.getMail())
+ .setIssuedAt(new Date())
+ .setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
+ .signWith(SignatureAlgorithm.HS256, SECRET).compact();
+
+ token = TOKEN_PREFIX + token;
+ return token;
+ }
+
+
+ /**
+ * 校验token的方法
+ *
+ * @param token
+ * @return
+ */
+ public static Claims checkJWT(String token) {
+ try {
+ final Claims claims = Jwts.parser()
+ .setSigningKey(SECRET)
+ .parseClaimsJws(token.replace(TOKEN_PREFIX, ""))
+ .getBody();
+
+ return claims;
+
+ } catch (Exception e) {
+ log.info("jwt token解密失败");
+ return null;
+ }
+ }
+}
diff --git a/xdclass-user-service/src/main/java/net/jieyuu/config/InterceptorConfig.java b/xdclass-user-service/src/main/java/net/jieyuu/config/InterceptorConfig.java
new file mode 100644
index 0000000..8226b8f
--- /dev/null
+++ b/xdclass-user-service/src/main/java/net/jieyuu/config/InterceptorConfig.java
@@ -0,0 +1,30 @@
+package net.jieyuu.config;
+
+
+import lombok.extern.slf4j.Slf4j;
+import net.jieyuu.interceptor.LoginInterceptor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+@Slf4j
+public class InterceptorConfig implements WebMvcConfigurer {
+
+ @Bean
+ public LoginInterceptor loginInterceptor() {
+ return new LoginInterceptor();
+ }
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ registry
+ .addInterceptor(loginInterceptor())
+ //拦截的路径
+ .addPathPatterns("/api/user/*/**", "/api/address/*/**")
+ //放行的路径
+ .excludePathPatterns("/api/user/*/send_code", "/api/user/*/captcha",
+ "/api/user/*/register", "/api/user/*/login", "/api/user/*/upload");
+ }
+}
diff --git a/xdclass-user-service/src/main/java/net/jieyuu/controller/UserController.java b/xdclass-user-service/src/main/java/net/jieyuu/controller/UserController.java
index e2b5833..9f877a7 100644
--- a/xdclass-user-service/src/main/java/net/jieyuu/controller/UserController.java
+++ b/xdclass-user-service/src/main/java/net/jieyuu/controller/UserController.java
@@ -5,17 +5,21 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import net.jieyuu.enums.BizCodeEnum;
+import net.jieyuu.request.UserLoginRequest;
import net.jieyuu.request.UserRegisterRequest;
import net.jieyuu.service.AddressService;
import net.jieyuu.service.FileService;
import net.jieyuu.service.NotifyService;
import net.jieyuu.service.UserService;
+import net.jieyuu.utils.CommonUtil;
import net.jieyuu.utils.JsonData;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpRequest;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
+import java.util.Map;
/**
*
@@ -73,10 +77,35 @@ public class UserController {
public JsonData register(
@ApiParam(value = "用户注册对象", required = true)
@RequestBody UserRegisterRequest registerRequest) {
- userService.register(registerRequest);
+ JsonData jsonData = userService.register(registerRequest);
- return JsonData.buildSuccess();
+ return jsonData;
}
+ /**
+ * 登录
+ *
+ * @param loginRequest
+ * @return
+ */
+ @ApiOperation("用户登录")
+ @PostMapping("login")
+ public JsonData userLogin(@ApiParam("用户登陆对象") @RequestBody UserLoginRequest loginRequest) {
+
+ JsonData jsonData = userService.login(loginRequest);
+ return jsonData;
+ }
+
+
+ @ApiOperation("刷新accessToken")
+ @PostMapping("refresh")
+ public JsonData getRefreshToken(Map param) {
+ //先从redis寻找refresh_token
+ //refresh_token存在, 解密accessToken
+ //重新调用JWTUtil 重新生成token
+
+ return null;
+ //不存在 重新登录
+ }
}
diff --git a/xdclass-user-service/src/main/java/net/jieyuu/request/UserLoginRequest.java b/xdclass-user-service/src/main/java/net/jieyuu/request/UserLoginRequest.java
new file mode 100644
index 0000000..ad5e2e1
--- /dev/null
+++ b/xdclass-user-service/src/main/java/net/jieyuu/request/UserLoginRequest.java
@@ -0,0 +1,17 @@
+package net.jieyuu.request;
+
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+@ApiModel(value = "登录对象", description = "用户登录请求对象")
+public class UserLoginRequest {
+
+ @ApiModelProperty(value = "邮箱", example = "123456@qq.com")
+ private String mail;
+
+ @ApiModelProperty(value = "密码", example = "123456")
+ private String pwd;
+}
diff --git a/xdclass-user-service/src/main/java/net/jieyuu/service/UserService.java b/xdclass-user-service/src/main/java/net/jieyuu/service/UserService.java
index a8c3d92..c2c99f8 100644
--- a/xdclass-user-service/src/main/java/net/jieyuu/service/UserService.java
+++ b/xdclass-user-service/src/main/java/net/jieyuu/service/UserService.java
@@ -2,6 +2,7 @@ package net.jieyuu.service;
import net.jieyuu.model.UserDO;
import com.baomidou.mybatisplus.extension.service.IService;
+import net.jieyuu.request.UserLoginRequest;
import net.jieyuu.request.UserRegisterRequest;
import net.jieyuu.utils.JsonData;
@@ -15,5 +16,9 @@ import net.jieyuu.utils.JsonData;
*/
public interface UserService extends IService {
+ //用户注册
JsonData register(UserRegisterRequest userRegisterRequest);
+
+ //用户登录
+ JsonData login(UserLoginRequest loginRequest);
}
diff --git a/xdclass-user-service/src/main/java/net/jieyuu/service/impl/UserServiceImpl.java b/xdclass-user-service/src/main/java/net/jieyuu/service/impl/UserServiceImpl.java
index dea47ca..28ac379 100644
--- a/xdclass-user-service/src/main/java/net/jieyuu/service/impl/UserServiceImpl.java
+++ b/xdclass-user-service/src/main/java/net/jieyuu/service/impl/UserServiceImpl.java
@@ -1,23 +1,31 @@
package net.jieyuu.service.impl;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import net.jieyuu.enums.BizCodeEnum;
import net.jieyuu.enums.SendCodeEnum;
+import net.jieyuu.model.LoginUser;
import net.jieyuu.model.UserDO;
import net.jieyuu.mapper.UserMapper;
+import net.jieyuu.request.UserLoginRequest;
import net.jieyuu.request.UserRegisterRequest;
import net.jieyuu.service.NotifyService;
import net.jieyuu.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import net.jieyuu.utils.CommonUtil;
+import net.jieyuu.utils.JWTUtil;
import net.jieyuu.utils.JsonData;
import org.apache.commons.codec.digest.Md5Crypt;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.Date;
+import java.util.List;
/**
*
@@ -32,10 +40,13 @@ import java.util.Date;
public class UserServiceImpl extends ServiceImpl implements UserService {
@Autowired
- NotifyService notifyService;
+ private NotifyService notifyService;
@Autowired
- UserMapper userMapper;
+ private UserMapper userMapper;
+
+ @Autowired
+ private RedisTemplate redisTemplate;
/**
* 用户注册
@@ -67,9 +78,9 @@ public class UserServiceImpl extends ServiceImpl implements
//设置创建时间
userDO.setCreateTime(new Date());
- //todo 设置密码 加密
+ //设置密码 加密
// userDO.setPwd(userRegisterRequest.getPwd());
- //生成密钥 盐
+ //生成密钥 盐e
userDO.setSecret("$1$" + CommonUtil.getStringNumRandom(8));
//密码加盐处理
@@ -99,8 +110,12 @@ public class UserServiceImpl extends ServiceImpl implements
* @return
*/
private boolean checkUnique(String mail) {
- //todo : 实现
- return true;
+ //todo 高并发的思考
+ QueryWrapper queryWrapper = new QueryWrapper().eq("mail", mail);
+
+ List list = userMapper.selectList(queryWrapper);
+
+ return list.size() > 0 ? false : true;
}
@@ -112,4 +127,48 @@ public class UserServiceImpl extends ServiceImpl implements
private void userRegisterInitTask(UserDO userDO) {
}
+
+ /**
+ * 用户登陆注册
+ *
+ * 判断用户注册情况
+ * 使用密钥+密文加密,判断密文匹配
+ *
+ * @param loginRequest
+ * @return
+ */
+ @Override
+ public JsonData login(UserLoginRequest loginRequest) {
+ List userDOList = userMapper.selectList(new QueryWrapper().eq("mail", loginRequest.getMail()));
+
+ if (userDOList != null && userDOList.size() == 1) {
+ //已经注册
+ UserDO userDO = userDOList.get(0);
+ String cryptPwd = Md5Crypt.md5Crypt(loginRequest.getPwd().getBytes(), userDO.getSecret());
+ if (cryptPwd.equals(userDO.getPwd())) {
+ //登陆成功
+ //生成token令牌并且返回
+ LoginUser loginUser = new LoginUser();
+ BeanUtils.copyProperties(userDO, loginUser);
+ //accessToken
+ String accessToken = JWTUtil.geneJsonWebToken(loginUser);
+ // accessToken过期时间
+ //UUID生成一个token
+ String refreshToken = CommonUtil.generateUUID();
+// redisTemplate.opsForValue().set(refreshToken, "1", 1000 * 60 * 60 * 24 * 30);
+
+
+ return JsonData.buildSuccess(accessToken);
+ } else {
+ return JsonData.buildResult(BizCodeEnum.ACCOUNT_PWD_ERROR);
+ }
+
+ } else {
+ //未注册
+ //这里选择 账号或密码错误,防止被爆破
+ return JsonData.buildResult(BizCodeEnum.ACCOUNT_PWD_ERROR);
+ }
+ }
+
+
}