從零開始搭建日誌系統(3)-用戶登錄註冊邏輯完成

git 項目地址

git項目地址

https://github.com/MrITzhongzi/blog-system.git

邏輯梳理
  1. 用戶註冊需要提供手機號,密碼等信息,後臺會自動把密碼加密存入數據庫
  2. 同一個手機號只能註冊一個
  3. 登錄的時候會驗證手機號密碼
  4. 登錄成功後臺會根據用戶信息生成JWT密鑰token,後續api都需要這個token
遇到的坑

1.mybatis插入數據返回自增主鍵問題

 	/**
     * 插入用戶
     * @param user
     * @return
     */
    @Insert("insert into lhw_user(user_ip, user_name, user_password, user_nickname, user_telephone_number) values (#{userIp}, #{userName},#{userPassword},#{userNickname}, #{userTelephoneNumber});")
    @Options(useGeneratedKeys = true, keyProperty = "userId", keyColumn = "user_id", useCache = false)
    int insert(LhwUser user);

看這一段代碼,你一定以爲insert返回的是一個int類型的,我們插入的數據的主鍵id。其實這是錯的,這個 int類型的返回值是 我們插入數據的條數(一般爲1)

爲什麼使用了useGeneratedKeys = true, keyProperty = “userId”, keyColumn = “user_id” 還是返回行數 而不是主鍵ID

因爲Mybatis把返回的主鍵ID存入 user對象裏了,在我們調用 insert方法的時候我們一定是這樣的:

LhwUser user = new LhwUser();
// 賦值操作
int row = xxxx.insert(user);
// row是受影響的行數,主鍵ID存入 user對象裏了
//插入成功後,我們再輸出一下 user對象

 system.out.print(user);

當我們再輸出user的時候,發現user中userId字段已經有值了,就是我們插入數據庫的主鍵ID值。

  1. mybatis返回單個對象的問題(數據庫數據無法映射到相應對象裏)

    @Select("SELECT * FROM lhw_user WHERE user_telephone_number = #{phone};")
    LhwUser queryUserByPhone(String phone);

看這段代碼,我剛開始以爲會返回一個LhwUser對象,事實上他一直是 null。

然後我就用下面這段代碼測試:

 @Select("SELECT * FROM lhw_user WHERE user_telephone_number = #{phone};")
    Object queryUserByPhone(String phone);

我看一下Object的值是 查詢到數據的主鍵 ID,是一個long類型數字。

原因:
數據庫的字段無法映射到LhwUser類中的字段,需要在配置文件中把數據庫字段映射成駝峯命名的LhsUser的字段。
加入如下配置:

 # mybatis 下劃線轉駝峯配置,兩者都可以
#mybatis.configuration.mapUnderscoreToCamelCase=true
# 開啓此配置是爲了 在查詢單個對象時,可以直接把數據庫中的字段映射到返回的對象裏
mybatis:
  configuration:
    map-underscore-to-camel-case: true

這樣就可以使用mybatis 直接返回我們需要的對象了。

註冊登錄核心代碼
package com.lhw.blog.controller;

import com.lhw.blog.config.CommonParam;
import com.lhw.blog.domain.LhwUser;
import com.lhw.blog.service.UserService;
import com.lhw.blog.tool.IpUtil;
import com.lhw.blog.tool.JWTUtils;
import com.lhw.blog.tool.JsonBuilder;
import com.lhw.blog.tool.SecretUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @description:  用戶模塊
 * @author: linger
 * @time: 2020/4/8 1:42 下午
 */
@RestController
@RequestMapping("/api/user")
public class UserController {

    @Resource
    private UserService userService;

    /**
     * 用戶註冊 api
     * @param username
     * @param password
     * @param phone
     * @param nickname
     * @param request
     * @return
     */
    @RequestMapping(path = "register", method = RequestMethod.POST)
    public JsonBuilder userRegister(@RequestParam(value = "username") String username,
                                    @RequestParam(value = "password") String password,
                                    @RequestParam(value = "phone") String phone,
                                    @RequestParam(value = "nickname") String nickname,
                                    HttpServletRequest request){

        // 從數據庫查詢有沒有此用戶,有的話返回錯誤,沒有繼續

        LhwUser tempUser = userService.queryUserByPhone(phone);
        if(tempUser != null) {
            return JsonBuilder.buildError("該手機號已經註冊");
        }
        // 校驗 各個字段是否符合要求
        if(username.trim().isEmpty()
                || password.trim().isEmpty()
                || phone.trim().isEmpty()
                || nickname.trim().isEmpty()) {
            return JsonBuilder.buildError("輸入的信息有誤");
        } else if (username.contains(CommonParam.NULLSTRING)
                || password.contains(CommonParam.NULLSTRING)
                || phone.contains(CommonParam.NULLSTRING)
                || nickname.contains(CommonParam.NULLSTRING)) {
            return JsonBuilder.buildError("輸入的信息不能包含空格");
        }

        // 密碼加密,存入數據庫
        String newPwd = SecretUtils.generatePwd(password);
        if(newPwd == null) {
            return JsonBuilder.buildError("密碼加密失敗,請稍後再試。");
        }

        //獲取 ip
        String requestIp = IpUtil.getIpAddr(request);

        LhwUser user = new LhwUser();
        user.setUserPassword(newPwd);
        user.setUserTelephoneNumber(phone);
        user.setUserNickname(nickname);
        user.setUserName(username);
        user.setUserIp(requestIp);
        // 返回主鍵id  0 爲異常
        Integer row = userService.insert(user);
        if(row != 0) {
            Map<String,String> map = new HashMap<>();
            map.put("nickname", nickname);
            map.put("phone", phone);
            return JsonBuilder.buildSuccess("成功", map);
        }

        return JsonBuilder.buildError("失敗,請稍後重試");
    }


    @RequestMapping(path = "login", method = RequestMethod.POST)
    public JsonBuilder userRegister(@RequestParam(value="phone") String phone,
                                    @RequestParam(value = "password") String password){


        LhwUser user = userService.queryUserByPhone(phone);
        if(user == null) {
            return JsonBuilder.buildError("用戶不存在。");
        }

        String generatePwd = SecretUtils.generatePwd(password);
        if(phone.equals(user.getUserTelephoneNumber()) && generatePwd.equals(user.getUserPassword())) {
            String token = JWTUtils.generateToken(user);
            Map<String, String> map = new HashMap<>();
            map.put("username", user.getUserName());
            map.put("nickname", user.getUserNickname());
            map.put("phone", user.getUserTelephoneNumber());
            map.put("token", token);
            return JsonBuilder.buildSuccess(map);
        }


        return JsonBuilder.buildError("用戶名或密碼不正確");
    }
}

JWTUtils代碼
package com.lhw.blog.tool;

import com.lhw.blog.domain.LhwUser;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Value;

import java.util.Date;

/**
 * @description: 用於生成和解析JWT
 * @author: lihongwei
 * @time: 2020/4/8 4:01 下午
 */
public class JWTUtils {

    /**
     * 密鑰
     */
    private static String secret = "itzhongzi";

    /**
     * 過期時間
     */
    private static long expire = 1000 * 60 * 60 * 24 * 7;

    /**
     * 發行者
     */
    private static String subject = "lihongwei";

    /**
     *  使用 ID 和 pwssword 生成JWTtoken
     * @param user
     * @return
     */
    public static String generateToken(LhwUser user){
        if(user == null || user.getUserId() == null
                || user.getUserNickname().isEmpty()
                || user.getUserTelephoneNumber().isEmpty()
                || user.getUserPassword().isEmpty() ) {
            return null;
        }

        String jwtToken = Jwts.builder().setSubject(subject)
                .claim("id", user.getUserId())
                .claim("password", user.getUserPassword())
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + expire))
                .signWith(SignatureAlgorithm.HS256, secret)
                .compact();


        return  jwtToken;
    }

    /**
     * 檢驗 token
     * @param token
     * @return
     */
    public static Claims checkJWT(String token) {
        try {
            Claims body = Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
            return body;
        } catch (Exception e) { }

        return null;
    }

}

接口測試
  1. 註冊
  • localhost:8088/api/user/register?username=lihongwei&password=123456&phone=17862806858&nickname=以勒
	{
		    "code": 0,
		    "description": "成功",
		    "data": {
		        "phone": "17862806858",
		        "nickname": "以勒"
		    }
		}
  1. 登錄
  • localhost:8088/api/user/login?phone=17862806857&password=123456
{
    "code": 0,
    "description": "success",
    "data": {
        "phone": "17862806857",
        "nickname": "以勒",
        "username": "lihongwei",
        "token": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJsaWhvbmd3ZWkiLCJpZCI6NTYsInBhc3N3b3JkIjoiLTRuMzVvNGQxaWlxZjVqZGE4MDg2bDd2N2R0ODJmdTduIiwiaWF0IjoxNTg2NDg0MzI2LCJleHAiOjE1ODcwODkxMjZ9.acdQjApX99loBTPJdfpRYxdZDnFe0WRhp0KZlUAk75w"
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章