第1关:用户登录
任务描述
本关任务:实现用户登录功能。
相关知识
为了完成本关任务,你需要掌握:
- 什么是登录;
- 登录有什么用;
- 实现登录功能。
什么是登录
登录:列入,记载。登记记录用户输入的注册账号和密码。英文可以用 Login。技术层面上解释更准确,即用户输入注册账号和密码的时候,数据进行记录核对的过程,录入成功后,则登录成功。登录,则存在表层和底层的信息登记和记录核对的过程。登录成功后,才算正在进入网站可以查看登陆时看不到的内容。
登录有什么用
-
登录,解决了用户与系统间的“告知与识别”的问题;就像我们在路上遇到熟,他的脸“告知”了你的脑他是谁,你的脑才会把这个的信息、与你的关系等信息“调”出来, 你才能叫出对的名字。
-
其实登录就是这样的过程,将现实的我们与虚拟的我们进匹配——现实的我以登录的式“告知”了系统对应的虚拟的我是哪个,系统才能从后台精准调取相应的信息去展示给我,买了什么,能操作什么,数据是多少,每个用户都是不同的。
实现登录功能
思路:以用户名和密码作为条件查询数据库,如果有查询结果那么就登录成功。
- dao 层代码:
//根据用户名和加密加盐后的密码查询用户信息
@Select("select user_id,userName,userPhoneNumber,email,gender from users where userName=#{userName} and password=#{password}")
User login(String userName,String password);
//根据用户名 获取加密该用户密码的 盐值
@Select("select salt from users where username=#{userName}")
String getSalt(String userName);
- service 层: 因为数据库中存储的是加密加盐后的密码,所以这里需要给用户登录的密码加密加盐。
//根据用户名和加密加盐后的密码查询用户信息
//调用 dao 层方法获取盐值 salt
String salt = userDao.getSalt(userName);
if(StringUtils.isEmpty(salt))
return null;
//密码根据盐值 加密加盐
String DBPass = MD5Util.formPassToDBPass(formPass,salt);
//redis 中取值
Map<Object, Object> login_count = redisTemplate.opsForHash().entries(userName);
if(login_count.isEmpty()||login_count.get(userName)==null){
//如果 redis 中没有记录登录次数,次数设置为 1
login_count.put(userName,1);
}else{
//如果 redis 中记录了登录次数,次数设置为 +1
login_count.put(userName,(int) login_count.get(userName)+1);
}
//存入 redis
redisTemplate.opsForHash().putAll(userName,login_count);
- controller 层代码:
@Autowired
UserService userService;
@Autowired
User user;
/**
* 用户登录
* @param userMap
* @return
*/
@PostMapping(value = "/login")
public String userLogin(@RequestBody Map<String,String> userMap){
//调用 service 接口登陆方法,登录成功返回 "登录成功",失败返回 "登录失败"
String userName = userMap.get("userName");
String password = userMap.get("password");
User user = userService.login(userName, password);
if(user!=null){
return "登录成功";
}else{
return "登录失败";
}
}
- 数据库如下:
字段名称 类型 备注 约束 user_id int(11) 权限id 主键,自增 userName varchar(20) 用户名 无 password varchar(40) 密码 无 userPhoneNumber bigint(11) 电话号码 无 email varchar(20) 邮箱 无 gender char(2) 性别 无 salt varchar(20) 加密盐值 无 login_count int(11) 登录次数 无 register_time datetime 注册时间 无
编程要求
- 在 UserDao.java 、UserServiceImpl.java 、UserController.java 里 Begin-End 处补充代码。
- 实现用户登录功能。
测试说明
平台会对你编写的代码进行测试:发送请求验证登录且查询 redis 缓存来测试代码。
预期输入:
{
"userName":"admin",
"password":"123456"
}
预期输出: 登录成功redis缓存成功
开始你的任务吧,祝你成功!
UserDao.java
package com.www.dao;
import com.www.entity.User;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import org.springframework.stereotype.Repository;
@Repository
public interface UserDao {
//根据用户名和加密加盐后的密码查询用户信息
@Select("select user_id,userName,userPhoneNumber,email,gender from users where userName=#{userName} and password=#{password}")
User login(String userName,String password);
//根据用户名 获取加密该用户密码的 盐值
@Select("select salt from users where username=#{userName}")
String getSalt(String userName);
//更新用户的登录次数
@Update("update users set login_count=login_count+#{count} where username=#{username}")
void updateLoginCount(String username,int count);
}
UserServiceImpl.java
package com.www.service.impl;
import com.www.dao.UserDao;
import com.www.entity.User;
import com.www.service.UserService;
import com.www.utils.MD5Util;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;
import org.thymeleaf.util.StringUtils;
import java.util.Map;
/**
* serviceimpl
*/
@Service("userService")
public class UserServiceImpl implements UserService {
@Autowired
RedisTemplate redisTemplate;
@Autowired
private UserDao userDao;
@Override
public User login(String userName, String formPass) {
//根据用户名和加密加盐后的密码查询用户信息
//调用 dao 层方法获取盐值 salt
String salt = userDao.getSalt(userName);
if(StringUtils.isEmpty(salt))
return null;
//密码根据盐值 加密加盐
String DBPass = MD5Util.formPassToDBPass(formPass,salt);
//使用用户名和加密加盐后的密码调用登录方法,并得到用户信息 user
User user = userDao.login(userName,DBPass);
//返回用户信息 user
if(user!=null){
//redis 中取值
Map<Object, Object> login_count = redisTemplate.opsForHash().entries("login_count");
if(login_count.isEmpty()||login_count.get(userName)==null){
//如果 redis 中没有记录登录次数,次数设置为 1
login_count.put(userName,1);
}else{
//如果 redis 中记录了登录次数,次数设置为 +1
login_count.put(userName,(int) login_count.get(userName)+1);
}
//存入 redis
redisTemplate.opsForHash().putAll("login_count",login_count);
}
return user;
}
}
User.java
package com.www.entity;
import lombok.Data;
import org.springframework.stereotype.Component;
import java.io.Serializable;
/**
* @author liuxianchun
* @date 2021/1/17
* 鐢ㄦ埛
*/
@Data
@Component
public class User implements Serializable {
private int user_id;
private String userName;
private String password;
private String userPhoneNumber;
private String email;
private String gender;
}
UserController.java
package com.www.controller;
import com.www.entity.User;
import com.www.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Map;
@Slf4j
@RestController
@RequestMapping(value = "/user")
public class UserController {
@Autowired
UserService userService;
@Autowired
User user;
/**
* 用户登录
* @param userMap
* @return
*/
@PostMapping(value = "/login")
public String userLogin(@RequestBody Map<String,String> userMap){
//调用 service 接口登陆方法,登录成功返回 "登录成功",失败返回 "登录失败"
String userName = userMap.get("userName");
String password = userMap.get("password");
User user = userService.login(userName, password);
if(user!=null){
return "登录成功";
}else{
return "登录失败";
}
}
}
UserService.java
package com.www.service;
import com.www.entity.User;
import org.springframework.stereotype.Component;
/**
* service
*/
@Component
public interface UserService {
//定义登录接口
User login(String userName,String formPass);
}
加油哦,同学们!