8月项目
用户登录
user表设计
- id 自增主键
- password:密码加密之后的密文 加密api
- phone
- status
- created
- updated
user类
一个对象对应一张表
@TableName("user") //对象与表一一对应 注意大小写
@Data //动态生成get/set方法
@Accessors(chain = true) //链式加载结构
public class User extends BasePojo {
@TableId(
type = IdType.AUTO
)
private Integer id;
private String username;
private String password;
private String phone;
private String email;
private Boolean status;
@TableField(
exist = false
)
private Role role;
public User() {
}
public boolean equals(final Object o) {
if (o == this) {
return true;
} else if (!(o instanceof User)) {
return false;
} else {
User other = (User)o;
if (!other.canEqual(this)) {
return false;
} else {
label95: {
Object this$id = this.getId();
Object other$id = other.getId();
if (this$id == null) {
if (other$id == null) {
break label95;
}
} else if (this$id.equals(other$id)) {
break label95;
}
return false;
}
Object this$status = this.getStatus();
Object other$status = other.getStatus();
if (this$status == null) {
if (other$status != null) {
return false;
}
} else if (!this$status.equals(other$status)) {
return false;
}
Object this$username = this.getUsername();
Object other$username = other.getUsername();
if (this$username == null) {
if (other$username != null) {
return false;
}
} else if (!this$username.equals(other$username)) {
return false;
}
label74: {
Object this$password = this.getPassword();
Object other$password = other.getPassword();
if (this$password == null) {
if (other$password == null) {
break label74;
}
} else if (this$password.equals(other$password)) {
break label74;
}
return false;
}
label67: {
Object this$phone = this.getPhone();
Object other$phone = other.getPhone();
if (this$phone == null) {
if (other$phone == null) {
break label67;
}
} else if (this$phone.equals(other$phone)) {
break label67;
}
return false;
}
Object this$email = this.getEmail();
Object other$email = other.getEmail();
if (this$email == null) {
if (other$email != null) {
return false;
}
} else if (!this$email.equals(other$email)) {
return false;
}
Object this$role = this.getRole();
Object other$role = other.getRole();
if (this$role == null) {
if (other$role != null) {
return false;
}
} else if (!this$role.equals(other$role)) {
return false;
}
return true;
}
}
}
protected boolean canEqual(final Object other) {
return other instanceof User;
}
public int hashCode() {
int PRIME = true;
int result = 1;
Object $id = this.getId();
int result = result * 59 + ($id == null ? 43 : $id.hashCode());
Object $status = this.getStatus();
result = result * 59 + ($status == null ? 43 : $status.hashCode());
Object $username = this.getUsername();
result = result * 59 + ($username == null ? 43 : $username.hashCode());
Object $password = this.getPassword();
result = result * 59 + ($password == null ? 43 : $password.hashCode());
Object $phone = this.getPhone();
result = result * 59 + ($phone == null ? 43 : $phone.hashCode());
Object $email = this.getEmail();
result = result * 59 + ($email == null ? 43 : $email.hashCode());
Object $role = this.getRole();
result = result * 59 + ($role == null ? 43 : $role.hashCode());
return result;
}
public String toString() {
return "User(id=" + this.getId() + ", username=" + this.getUsername() + ", password=" + this.getPassword() + ", phone=" + this.getPhone() + ", email=" + this.getEmail() + ", status=" + this.getStatus() + ", role=" + this.getRole() + ")";
}
}
用户登录业务实现流程
步骤1 : 用户输入完用户名和密码,点击登录按钮
步骤2 : 准备username/password数据,向后台服务器发送请求,请求类型:POST,
备注:用GET的话用户名和密码都在URL中不安全,所有的登录操作都是POST类型的请求
步骤3:后台服务器接收用户请求的username/password
步骤4 :根据用户名和密码查询数据库
结果: 有数据:用户名和密码正确|没有数据:用户名和密码错误
前后端是不同的服务器,所以在交互的时候,后端要返回一个业务回执
步骤5 :后端服务器应该返回一个业务回执,标识业务逻辑是否正确执行
步骤6 :前段服务器根据用户的状态码提示用户操作成功/操作失败
业务接口文档
说明:一般做前后端交互时,必须有业务接口文档,文档中详细阐述了业务需求/URL地址/参数/返回值信息等要素,前后端严格按照业务接口文档进行编码
系统返回值
SysResult对象说明: 该对象用来实现后端与前端业务交互
业务执行正确 status=200, 错误status=201
前后端交互的层级定义为vo层
前端页面解析(调用流程)
###前端细节
<el-form-item class="btns">
<el-button type="primary" @click="login">登录</el-button>
<el-button type="info" @click="reset">重置</el-button>
</el-form-item>
methods: {
reset(){
this.$refs.loginFormRef.resetFields()
},
//登录之前 先对数据进行校验
login(){
this.$refs.loginFormRef.validate(async valid => {
if(!valid) return
const {data: result} = await this.$http.post("/user/login",this.loginForm)
if(result.status !== 200) return this.$message.error("用户登录失败")
this.$message.success("用户登录成功")
//登录成功之后,将token信息保存到session中
window.sessionStorage.setItem('token',result.data)
//跳转到系统首页
this.$router.push("/home")
})
}
}
token的作用
说明:前端服务器:用户进行登录操作时 输入用户名和密码进行校验
将数据信息发送到后端服务器进行校验 查询数据库
假设:用户名和密码正确,页面应该跳转到首页“/home”
问题:是否可以在浏览器中直接输入“/home”?理论上不允许
解决方法:后端服务器返回一个独一无二的token数据,前端只要携带token,认为该用户已经登陆,可以跳转页面
token:用来标识用户已经登陆
/**
*设定路由导航守卫,当用户没有登陆时,不允许跳转其他页面
* to: 要跳转的页面
* form: 从哪里来的
* next: next 是一个函数 next()表示放行 next("/login") 表示发起/login请求
*/
router.beforeEach((to,from,next) => {
if(to.path === '/login') return next()
//获取用户页面token信息
let token = window.sessionStorage.getItem('token')
//如果token数据为null 则跳转到指定路径
if(!token) return next("/login")
next()
})
编辑UserController
业务要求:完成用户信息校验,并且返回特定的token
知识补充
MD5介绍
MD5信息摘要算法(英语:MD5 Message-Digest Algorithm),一种被广泛使用的密码散列函数,可以产生出一个128位(16字节)的散列值(hash value),用于确保信息传输完整一致。MD5由美国密码学家罗纳德·李维斯特(Ronald Linn Rivest)设计,于1992年公开,用以取代MD4算法。这套算法的程序在 RFC 1321 标准中被加以规范。1996年后该算法被证实存在弱点,可以被加以破解,对于需要高度安全性的数据,专家一般建议改用其他算法,如SHA-2。2004年,证实MD5算法无法防止碰撞(collision),因此不适用于安全性认证,如SSL公开密钥认证或是数字签名等用途。
- 信息摘要算法
- 通常可以将数字进行MD5加密 生成数字指纹
- 应用于各大网站中
- MD5加密以后,理论上无法由密文转化为明文,不可以用反向编译
(网上的破解都是将MD5反向查询) - 防止暴力破解: 限定输入密码的次数 3-5次锁定
核心算法:
hash算法
MD5改进:+盐值