接口文档:https://blog.csdn.net/qq_16804847/article/details/116671831?spm=1001.2014.3001.5502
一、用户登录模块 业务名user——构建user层级代码
1、用户登录实现
1)编辑pojo-根据接口文档和数据库表结构
package com.jt.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@Data
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
@TableName("user")//让pojo对象与表名一一映射
public class User extends BasePojo {
@TableId(type = IdType.AUTO)//标识主键
private Integer id;
// @TableField("username") //如果属性与字段名称一致(包含驼峰规则),则注解可以省略
private String username;
@TableField("password")
private String password;
private String phone;
private String email;
private Boolean status; //true 正常 false 停用
}
2)创建SysResult对象-vo层 全局响应用户的-根据接口文档
原因:用户点击登录后若是用户名和密码不正确要告诉/响应用户,不能让用户一直点;不论对错都要告知用户
写法:里面写静态方法:可以通过类名直接调用,方便返回给用户 注意重载
package com.jt.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.io.Serializable;
@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class SysResult implements Serializable {
private Integer status;//状态信息 200 成功 201 失败
private String msg;//服务器返回的提示信息
private Object data;/**注意:服务器返回值数据是Object类型*/
//响应数据类型是 SysResult对象.方法(),所以静态方法的返回值是 SysResult对象
/**注意:方法的参数列表有参数,一定要在方法里return 如重载2和3*/
/*一、登录失败*/
public static SysResult fail(){
return new SysResult(201,"业务调用失败!",null);//成功才返回业务数据,失败不返回
}
/*二、登录成功——用户登录成功的vo对象需要重载:方便按照用户不同的规则进行调用
* 下面方法里的参数列表里写了传的参数(比如重载2和3),那么就要把传进来的参数写进return里return给用户*/
//重载1 用户需求:有的用户要求 不返回提示信息,不返回业务数据
public static SysResult success(){
return new SysResult(200,"业务调用成功!",null);
}
//重载2 用户需求:有的用户要求 不返回提示信息,返回业务数据
/*public static SysResult success(String msg){ //用户需求:有的用户要求 返回提示信息,不返回业务数据
return new SysResult(200,msg,data);*///这个方法不能和下面的一个方法一起写,不构成重载Object类比String大且包含它
public static SysResult success(Object data){
return new SysResult(200,"业务调用成功!",data);
}
//重载3 用户需求:有的用户要求 返回提示信息,同时要求返回业务数据
public static SysResult success(String msg, Object data){
return new SysResult(200,msg,data);
}
}
3)用户登录实现
代码编辑
1>控制层
用户登录业务逻辑
当用户完成登录时,前端系统会向后端进行访问.后端服务器经过数据库查询.如果查询正确 则返回token密钥信息. 如果查询失败 说明用户名和密码错误 返回null
/**接收前端的参数传给service层*/
@PostMapping("/login")
public SysResult login(@RequestBody User user){
/*由接口文档可知返回的业务数据是密钥token信息,所以
由service层返回来的结果一定是String token,用String token接*/
String token = userService.login(user);
/**查询完service层传回来的数据 进行判断*/
if(token == null){
return SysResult.fail();
}
return SysResult.success(token);
}
2>业务层
业务逻辑:
1、用户传过来的密码是明文,数据库里存的密码是密文,所以需要在业务层将用户传的明文变为密文--用各种算法(此处用的是md5加密算法)
2、根据用户名和密码查询数据库
3、判断数据库查询的返回值userDB是否有值,如果有值,说明用户名和密码正确,按要求生成并返回给控制层一个独一无二的token密钥信息--用UUID.randomUUID 并用toString将其转化为字符串
知识点:Maven如何保证安全性/防止被篡改/如何将明文密码转化为为密文?
可以将密码明文,转化为密文的几种算法:sha1/md5算法/md5hash
常识性问题:
1.如果数据相同 算法相同 结果必然相同.
2.如果数据不同 算法相同 结果可能相同. hash碰撞问题.
md5加密算法:可以产生出一个128位(16字节)的散列值
规则:md5加密算法的数据可以穷举查询.但是不可以被破解.
sha1算法:SHA-1可以生成一个被称为消息摘要的160位(20字节)散列值,散列值
通常的呈现形式为40个十六进制数。
hash算法:1.对相同数据,采用相同的hash算法, 问: 结果是否相同? 答:必定相同
不同的数据,采用相同的hash算法, 问: 结果是否不同? 答:可能相同
会产生 hash碰撞问题!!!
关于hash碰撞说明:hash碰撞 不能避免,但可以有效地降低概率:比如密码需要大量
的数据才能碰撞破解成功,我们可以增大基数;或者减少次数-设置次数为3次数以内
2、结论:结果相等,数据大概率没有被篡改;
结果不相等,数据必定被篡改了
String login(User user);
//一、用户登录实现
@Override
public String login(User user) {
String password = user.getPassword();//利用传进来的user对象获取到用户输的明文密码
byte[] bytes = password.getBytes();//DigestUtils.md5DigestAsHex(需要一个byte字节数组)
//1.(利用工具API)将密码加密 因为数据库里密码都是密文,只有转换成密文才能进行查询业务
String md5Password = DigestUtils.md5DigestAsHex(bytes);//或者将 password.getBytes()直接写入
user.setPassword(md5Password);//将转变成的密文密码赋给user对象,去传给mapper层查询
//2.根据用户名和密码查询数据库 ----结果只有一个,用User接收
User userDB = userMapper.findUserByUP(user);
//3.判断mapper层传回来的userDB是否有值,userDB不一定有值
if(userDB == null){
//用户名和密码查询错误,返回null
return null;
}
//程序走到这里,说明用户名和密码正确 我们定义一个token并返回token字符串--
String token = UUID.randomUUID().toString();
return token;
}
3>持久层
User findUserByUP(User user);
映射文件:
<mapper namespace="com.jt.mapper.UserMapper">
<select id="findUserByUP" resultType="User">
select * from user /*工作时不能写*,要全部写出来*/
where username=#{username}
and password = #{password}
</select>
</mapper>
效果图
2、用户首页跳转(路由)
修改路由信息两步:上下两步都不能少(路径:router/index.js中)
效果图
二、左侧菜单列表展现 业务名rights——构建rights层级代码
点此跳转 左侧菜单列表展现 总结
*左侧菜单列表展现 (有两级菜单 同表一对多 自关联-关联查询 各级菜单都在一个表里 )
1>编辑pojo (一对多,同表封装子级 为children)
package com.jt.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.util.List;
/**
* @author 刘昱江
* 时间 2021/2/18
*/
@Data
@Accessors(chain = true)
@AllArgsConstructor
@NoArgsConstructor
@TableName("rights")
public class Rights extends BasePojo {
@TableId(type = IdType.AUTO)
private Integer id;//父级(一级)ID
//@TableField("name")
private String name;
private Integer parentId;
private String path;
private Integer level;
@TableField(exist = false) //当前属性不参与MP操作
private List<Rights> children; //List<Rights>父级 一对多 一个父级有多个子集列表
}
2>控制层
//三、左侧菜单列表展现
@GetMapping("/getRightsList")
public SysResult getRightsList(){
//根据接口文档 得data返回权限List集合 所以用List集合接
List<Rights> list = rightsService.getRightsList();
return SysResult.success(list);
}
3>业务层
List<Rights> getRightsList();
@Override
public List<Rights> getRightsList() {
return rightsMapper.getRightsList();
}
4>持久层
List<Rights> getRightsList();
映射文件:
规则:
要想查询谁的子级菜单,谁就要当父级id
原理说明: 左侧菜单划分为3级.但是显示时只显示2级.第三级在页面右半侧展示
数据库表中level
一级菜单获取: select * from rights where parent_id = 0
二级菜单获取: select * from rights where parent_id = 一级ID
三级菜单获取: select * from rights where parent_id = 二级ID