Browse Source

Merge remote-tracking branch 'origin/master'

Aslee 4 years ago
parent
commit
4ee827f13f

+ 6 - 1
pom.xml

@@ -84,7 +84,12 @@
             <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
             <version>2.1.0</version>
         </dependency>
-
+        <!-- jwt -->
+        <dependency>
+            <groupId>com.auth0</groupId>
+            <artifactId>java-jwt</artifactId>
+            <version>3.14.0</version>
+        </dependency>
 
 		<dependency>
 			<groupId>org.springframework.boot</groupId>

+ 36 - 0
src/main/java/com/caimei365/user/controller/LoginApi.java

@@ -0,0 +1,36 @@
+package com.caimei365.user.controller;
+
+import com.caimei365.user.model.BaseUser;
+import com.caimei365.user.model.JsonModel;
+import com.caimei365.user.service.LoginService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 登录API
+ *
+ * @author : Charles
+ * @date : 2021/3/8
+ */
+@RestController
+@RequiredArgsConstructor
+@RequestMapping("/user/login")
+public class LoginApi {
+
+    private LoginService loginService;
+
+    /**
+     * 登录(用户名,密码)
+     *
+     * @param mobileOrEmail 手机号或邮箱
+     * @param password 密码
+     * @return BaseUser
+     */
+    @PostMapping("/password")
+    public JsonModel<BaseUser> passwordLogin(String mobileOrEmail, String password) {
+        return loginService.passwordLogin(mobileOrEmail, password);
+    }
+
+}

+ 10 - 3
src/main/java/com/caimei365/user/mapper/BaseUserDao.java

@@ -12,11 +12,18 @@ import org.apache.ibatis.annotations.Param;
  */
 @Mapper
 public interface BaseUserDao {
+    /**
+     * 根据手机号获取用户
+     *
+     * @param mobile 手机号
+     * @return BaseUser
+     */
+    BaseUser getBaseUserByMobile(@Param("mobile") String mobile);
     /**
      * 根据手机号或邮箱获取用户
      *
-     * @param mobileOrEmail
-     * @return
+     * @param mobileOrEmail 手机号/邮箱
+     * @return BaseUser
      */
-    BaseUser selectByMobileOrEmail(@Param("mobileOrEmail") String mobileOrEmail, @Param("source") String source);
+    BaseUser getBaseUserByMobileOrEmail(@Param("mobileOrEmail") String mobileOrEmail);
 }

+ 42 - 2
src/main/java/com/caimei365/user/model/BaseUser.java

@@ -10,7 +10,47 @@ import lombok.Data;
  */
 @Data
 public class BaseUser {
-    private Integer id;
-    private String name;
+    /**
+     * 用户ID
+     */
+    private Integer userId;
+    /**
+     * 用户名
+     */
+    private String userName;
+    /**
+     * 邮箱
+     */
+    private String email;
+    /**
+     * 手机号码
+     */
     private String mobile;
+    /**
+     * 企业绑定手机号
+     */
+    private String bindMobile;
+    /**
+     * 用户权限 0游客 1 普通用户 2 会员机构 3 供应商 4 协销 5 普通机构
+     */
+    private Integer userPermission;
+    /**
+     * 用户身份 0、个人 1、协销 2、会员机构 3、供应商 4,普通机构
+     */
+    private Integer userIdentity;
+    /**
+     * 用户状态:
+     * 机构:90:已上线,91:已冻结,92:审查资料未通过,待补充资料,1:待审查资料,2:电话预约,3:已预约,20:待确认,21:待拜访,30:待员工推荐,40:已完成第一次采购
+     * 供应商:90:已上线,91:已下线,92:审核不通过,3:待审核
+     */
+    private Integer status;
+    /**
+     * 密码
+     */
+    private String password;
+    /**
+     * token
+     */
+    private String token;
+
 }

+ 22 - 0
src/main/java/com/caimei365/user/service/LoginService.java

@@ -0,0 +1,22 @@
+package com.caimei365.user.service;
+
+import com.caimei365.user.model.BaseUser;
+import com.caimei365.user.model.JsonModel;
+
+/**
+ * Description
+ *
+ * @author : Charles
+ * @date : 2021/3/8
+ */
+public interface LoginService {
+
+    /**
+     * 登录(用户名,密码)
+     *
+     * @param mobileOrEmail 手机号或邮箱
+     * @param password      密码
+     * @return BaseUser
+     */
+    JsonModel<BaseUser> passwordLogin(String mobileOrEmail, String password);
+}

+ 3 - 0
src/main/java/com/caimei365/user/service/impl/ClubServiceImpl.java

@@ -8,5 +8,8 @@ import com.caimei365.user.service.ClubService;
  * @author : Charles
  * @date : 2021/3/8
  */
+/*
 public class ClubServiceImpl implements ClubService {
+
 }
+*/

+ 89 - 0
src/main/java/com/caimei365/user/service/impl/LoginServiceImpl.java

@@ -0,0 +1,89 @@
+package com.caimei365.user.service.impl;
+
+import com.caimei365.user.mapper.BaseUserDao;
+import com.caimei365.user.model.BaseUser;
+import com.caimei365.user.model.JsonModel;
+import com.caimei365.user.service.LoginService;
+import com.caimei365.user.service.RedisService;
+import com.caimei365.user.utils.JwtUtil;
+import com.caimei365.user.utils.Md5Util;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+
+/**
+ * Description
+ *
+ * @author : Charles
+ * @date : 2021/3/8
+ */
+@Slf4j
+@Service
+public class LoginServiceImpl implements LoginService {
+
+    @Resource
+    private RedisService redisService;
+    @Resource
+    private BaseUserDao baseUserDao;
+
+    /**
+     * 登录(用户名,密码)
+     *
+     * @param mobileOrEmail 手机号或邮箱
+     * @param password      密码
+     * @return BaseUser
+     */
+    @Override
+    public JsonModel<BaseUser> passwordLogin(String mobileOrEmail, String password) {
+        if (mobileOrEmail.isEmpty()) {
+            return JsonModel.error("请填写账户名", null);
+        }
+        if (password.isEmpty()) {
+            return JsonModel.error("请填写密码", null);
+        }
+        //处理比对密码
+        BaseUser baseUser = baseUserDao.getBaseUserByMobileOrEmail(mobileOrEmail);
+        if (baseUser != null) {
+            String md5Password = Md5Util.md5(password);
+            String dbPassword = baseUser.getPassword();
+            if (md5Password.equals(dbPassword)) {
+                if (baseUser.getUserIdentity() == 1) {
+                    // 协销登录
+                    return JsonModel.success(baseUser);
+                } else {
+                    // 返回登录校验结果
+                    return logonVerify(baseUser);
+                }
+            }
+        }
+        return JsonModel.error("输入的密码和账户名不匹配", null);
+    }
+
+    /**
+     * 登录校验
+     * @param baseUser 用户信息
+     * @return BaseUser
+     */
+    private JsonModel<BaseUser> logonVerify(BaseUser baseUser) {
+        // 生成token给用户
+        String token = JwtUtil.createToken(baseUser.getUserId());
+        // 为了过期续签,将token存入redis,并设置超时时间
+        redisService.set(token, token, JwtUtil.getExpireTime());
+        baseUser.setToken(token);
+        if (baseUser.getStatus() == 91) {
+            //机构 / 供应商
+            return JsonModel.error(-2, "您的企业账号已被冻结,请联系客服处理", null);
+        }
+        // 供应商
+        if (baseUser.getUserIdentity() == 3) {
+            if (baseUser.getStatus() == 3) {
+                return JsonModel.error(-2, "您的企业账号正在加速审核中,审核通过后即可登录", null);
+            }
+            if (baseUser.getStatus() == 92) {
+                return JsonModel.error(-3, "您的企业账号审核未通过", baseUser);
+            }
+        }
+        return JsonModel.success("登录成功", baseUser);
+    }
+}

+ 1 - 1
src/main/java/com/caimei365/user/service/impl/UserServiceImpl.java

@@ -109,7 +109,7 @@ public class UserServiceImpl implements UserService {
             // 生成六位验证码
             String randomCode = CodeUtil.generateCodeInt(6);
             // 根据手机号查询用户
-            BaseUser baseUser = baseUserDao.selectByMobileOrEmail(mobile, "www");
+            BaseUser baseUser = baseUserDao.getBaseUserByMobile(mobile);
             if ("1".equals(activateCodeType)) {
                 if (null == baseUser) {
                     return JsonModel.error("该手机号尚未注册");

+ 149 - 0
src/main/java/com/caimei365/user/utils/JwtUtil.java

@@ -0,0 +1,149 @@
+package com.caimei365.user.utils;
+
+import com.auth0.jwt.JWT;
+import com.auth0.jwt.algorithms.Algorithm;
+import com.auth0.jwt.interfaces.DecodedJWT;
+import com.auth0.jwt.interfaces.JWTVerifier;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * JWT工具类
+ *
+ * 标准中注册的声明
+ * iss: jwt签发者
+ * sub: jwt所面向的用户
+ * aud: 接收jwt的一方
+ * exp: jwt的过期时间,这个过期时间必须要大于签发时间
+ * nbf: 定义在什么时间之前,该jwt都是不可用的.
+ * iat: jwt的签发时间
+ * jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。
+ *
+ *
+ * @author : Charles
+ * @date : 2021/3/8
+ */
+public class JwtUtil {
+    /**
+     * 设置过期时间: 2*60分钟
+     */
+    private static final long EXPIRE_TIME = 2 * 60 * 60 * 1000;
+    /**
+     * 服务端的私钥secret,在任何场景都不应该流露出去
+     */
+    private static final String TOKEN_SECRET = "zhengchao";
+
+    /**
+     * 生成签名,6EXPIRE_TIME过期
+     *
+     * @param **User**
+     * @param **password**
+     * @return
+     */
+    public static String createToken(Integer userID) {
+        try {
+            // 设置过期时间
+            Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
+            // 私钥和加密算法
+            Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
+            // 设置头部信息
+            Map<String, Object> header = new HashMap<>(2);
+            header.put("typ", "JWT");
+            header.put("alg", "HS256");
+            // 返回token字符串
+            return JWT.create()
+                    .withHeader(header)
+                    .withClaim("uid", userID)
+                    /*.withClaim("aud", mobileOrEmail)*/
+                    .withExpiresAt(date)
+                    .sign(algorithm);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+        public static String createTokenBySecret(String secret) {
+        try {
+            // 设置过期时间
+            Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
+            // 私钥和加密算法
+            Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
+            // 设置头部信息
+            Map<String, Object> header = new HashMap<>(2);
+            header.put("typ", "JWT");
+            header.put("alg", "HS256");
+            // 返回token字符串
+            return JWT.create()
+                    .withHeader(header)
+                    .withClaim("uid", secret)
+                    .withExpiresAt(date)
+                    .sign(algorithm);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * 检验token是否正确
+     *
+     * @param **token**
+     * @return
+     */
+    public static boolean isVerify(String token) {
+        try {
+            Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
+            JWTVerifier verifier = JWT.require(algorithm).build();
+            verifier.verify(token);
+            return true;
+        } catch (Exception e) {
+            return false;
+        }
+    }
+
+    /**
+     * 从token解析出uid信息,用户ID
+     *
+     * @param token
+     * @return
+     */
+    public static int parseTokenUid(String token) {
+        DecodedJWT jwt = JWT.decode(token);
+        return jwt.getClaim("uid").asInt();
+    }
+
+    /**
+     * 从token解析出aud信息,用户名
+     *
+     * @param token
+     * @return
+     */
+    /*public static String parseTokenAud(String token) {
+        DecodedJWT jwt = JWT.decode(token);
+        return jwt.getClaim("aud").asString();
+    }*/
+
+    /**
+     * 从token解析出过期日期时间
+     *
+     * @param token
+     * @return Date
+     */
+    public static Date paraseExpiresAt(String token) {
+        DecodedJWT jwt = JWT.decode(token);
+        return jwt.getExpiresAt();
+    }
+
+    /**
+     * 返回设置的过期秒数
+     *
+     * @return long 秒数
+     */
+    public static long getExpireTime() {
+        return EXPIRE_TIME / 1000;
+    }
+
+}

+ 35 - 12
src/main/resources/mapper/BaseUserMapper.xml

@@ -1,20 +1,43 @@
 <?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="com.caimei365.user.mapper.BaseUserDao">
-    <select id="selectByMobileOrEmail" resultType="com.caimei365.user.model.BaseUser">
-        select u.*,cu.mobile as operatorMobile from user u
+    <select id="getBaseUserByMobile" resultType="com.caimei365.user.model.BaseUser">
+        select u.userID as userId,
+               u.userName as userName,
+               u.mobile as mobile,
+               u.bindMobile as bindMobile,
+               u.email as email,
+               u.userPermission as userPermission,
+               u.userIdentity as userIdentity,
+               u.password as password
+        from user u
+        left join cm_mall_operation_user cu on cu.userID = u.userID
+        where (u.bindMobile = #{mobile}
+                or (cu.mobile = #{mobile} and cu.delFlag != 1)
+        ) AND u.userIdentity IN (1,2,3,4)
+        LIMIT 1
+    </select>
+    <select id="getBaseUserByMobileOrEmail" resultType="com.caimei365.user.model.BaseUser">
+        select u.userID as userId,
+            u.userName as userName,
+            u.mobile as mobile,
+            u.bindMobile as bindMobile,
+            u.email as email,
+            u.userPermission as userPermission,
+            u.userIdentity as userIdentity,
+            u.password as password,
+            case
+                when u.userIdentity = 3 then u.manufacturerStatus
+                when (u.userIdentity = 2 or u.userIdentity = 4) then u.clubStatus
+            else 0
+            end as status
+        from user u
         left join cm_mall_operation_user cu on cu.userID = u.userID
         where (u.bindMobile = #{mobileOrEmail}
-        or u.email = #{mobileOrEmail}
-        or (cu.mobile = #{mobileOrEmail} and cu.delFlag != 1))
-        AND u.userIdentity IN (1,2,3,4)
-        AND (u.userOrganizeID = '2' OR u.userOrganizeID IS NULL)
-        <if test="source == 'www'">
-            AND u.registerUserTypeID IN (1,3,4)
-        </if>
-        <if test="source == 'crm'">
-            AND u.registerUserTypeID IN (1,2,3,32,4)
-        </if>
+                or u.email = #{mobileOrEmail}
+                or (cu.mobile = #{mobileOrEmail} and cu.delFlag != 1)
+        ) AND u.userIdentity IN (1,2,3,4)
         LIMIT 1
     </select>
+
 </mapper>