勋的要求
1 登录后 后端返回一个token
2 数据库 用户表 事项表
用户表:用户名 密码 用户标识(id)
1 zhangsan 123456
2 zhangsan2 123456
3 zhangsan3 123456
事项表:事项基本信息(事项id,名称、创建时间、完成状态、完成时间),所属用户 权限?
id name uid datetime status ...
1 学习VUE 3 .....
2 学习HTML 3 .....
3 学习VUE 1 .....
4 学习VUE 2 .....
3 添加事项:
前端通过POST:事项的基本信息(post),token
后端:解析token,将uid和事项信息存储数据库(INSERT)
返回:返回操作的结果(成功、失败)
4 查询事项:
前端:GET请求,携带token
后端:解析token,得到uid,在数据库中查询(SELECT)Where uid=?
返回:返回查询结果(List)【事项id,事项名称,事项状态...】
5 修改事项:
前端:POST请求,携带token,事项id,更新后的事项的数据
后端:解析token得到uid,更具事项id(1,2,3,4,5,6,7),更新数据库中的事项内容(UPDATE where id = ? and uid = ?)
@RestController
@RequestMapping("/tasks")
public class TaskController {@Autowiredprivate TaskService taskService;@Autowiredprivate UserService userService; // 确保 UserService 能够被注入@GetMapping("/mytasks")public ResponseEntity<?> getMyTasks(@RequestHeader("Authorization") String token) {try {// 从 token 中获取用户信息User user = userService.getUserInfoByToken(token);// 使用用户ID获取任务列表List<Task> tasks = taskService.getTasksByUserId(user.getId());return ResponseEntity.ok(tasks);} catch (Exception e) {return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(e.getMessage());}}
}@Service
public class TaskService {@Autowiredprivate TaskMapper taskMapper;@Transactional(readOnly = true)public List<Task> getTasksByUserId(Integer userId) {return taskMapper.findByUserId(userId);}
}@Mapper
public interface TaskMapper {List<Task> findByUserId(Integer userId);
}XML文件<select id="findByUserId" resultMap="taskResultMap">SELECT * FROM tasks WHERE uid = #{userId}</select>
后端实现
配置环境
实体类代码:
import lombok.Data;
import java.util.Date;@Data
public class User {private Integer id;private String username;private String password;private String name;private String gender;private Date birthDate;
}
import lombok.Data;@Data
public class Task {private Long id;private String name;private Integer uid;private Boolean completed;}
前后端交互统一响应结果 Result
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;@Data
@NoArgsConstructor
@AllArgsConstructor
public class Result {private Integer code;//响应码,1 代表成功; 0 代表失败private String msg; //响应信息 描述字符串private Object data; //返回的数据//增删改 成功响应public static Result success(){return new Result(1,"success",null);}//查询 成功响应public static Result success(Object data){return new Result(1,"success",data);}//失败响应public static Result error(String msg){return new Result(0,msg,null);}
}
数据库格式:
`tasks`(`id`, `name`, `uid`, `completed`)
`user`(`id`, `username`, `password`, `name`, `gender`, `birth_date`)
数据库建表语句:
CREATE TABLE User (id INT AUTO_INCREMENT PRIMARY KEY,username VARCHAR(255) NOT NULL,password VARCHAR(255) NOT NULL,name VARCHAR(255),gender VARCHAR(10),birth_date DATE
);
CREATE TABLE Task (id BIGINT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(255) NOT NULL,uid INT,completed TINYINT(1) DEFAULT 0
);
配置文件代码:
spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/demo0414username: rootpassword: 123456mybatis:configuration:#配置mybatis的日志, 指定输出到控制台log-impl: org.apache.ibatis.logging.stdout.StdOutImpl#开启mybatis的驼峰命名自动映射开关 a_column ------> aCloumnmap-underscore-to-camel-case: true
配置 mapper XML文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.minjie.mapper.UserMapper"></mapper>
JWT令牌实现登录校验
引入依赖
<dependency><groupId>io.jsonwebtoken</groupId><artifactId>jjwt</artifactId><version>0.9.1</version>
</dependency>
<dependency><groupId>javax.xml.bind</groupId><artifactId>jaxb-api</artifactId><version>2.3.1</version>
</dependency>
JwtUtils 代码
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
import java.util.Map;public class JwtUtils {private static String signKey = "itheima";private static Long expire = 43200000L;/*** 生成JWT令牌* @param claims JWT第二部分负载 payload 中存储的内容* @return*/public static String generateJwt(Map<String, Object> claims){String jwt = Jwts.builder().addClaims(claims).signWith(SignatureAlgorithm.HS256, signKey).setExpiration(new Date(System.currentTimeMillis() + expire)).compact();return jwt;}/*** 解析JWT令牌* @param jwt JWT令牌* @return JWT第二部分负载 payload 中存储的内容*/public static Claims parseJWT(String jwt){Claims claims = Jwts.parser().setSigningKey(signKey).parseClaimsJws(jwt).getBody();return claims;}
}
在 controller 进行发令牌的判断和操作
添加用户请求体内容
{"username":"郑爽","password":"111","name":"爽","gender":"女","birthdate":"1989-01-01"
}
MD5密码加密
理论学习
对称加密:使用同一把密钥
非对称加密:公钥:加密 / 私钥:解密
摘要算法:哈希算法 / 散列算法,不可逆,MD5
代码实现
前端实现
勋的实现:
<template><div class="task-list"><el-card class="box-card"><div slot="header" class="clearfix"><span>我的任务列表</span></div><el-table :data="tasks" style="width: 100%"><el-table-column prop="name" label="任务名称" width="180"></el-table-column><el-table-column prop="completed" label="完成状态" width="100"><template slot-scope="scope"><el-tag :type="scope.row.completed ? 'success' : 'info'">{{ scope.row.completed ? '已完成' : '未完成' }}</el-tag></template></el-table-column></el-table></el-card></div>
</template><script>
import axios from 'axios';export default {data() {return {tasks: []};},created() {this.fetchTasks();},methods: {fetchTasks() {const token = localStorage.getItem('token');axios.get('/api/tasks/mytasks', {headers: {'Authorization': token}}).then(response => {this.tasks = response.data;}).catch(error => {this.$message.error('获取任务列表失败');});}}
};
</script><style scoped>
.task-list {margin: 20px;
}
.box-card {width: 500px;
}
</style>
知识点
1. MD5 和 JWT 并没有直接的关系,因为它们解决的问题和功能不同。在实际的身份验证流程中,MD5 可能用于加密用户密码,而 JWT 则可能用于生成和验证用户的身份令牌,这样用户可以在多个服务中进行身份验证而无需重复登录。
2.
如图,加了 @JsonIgnore 之后就添加也会忽略,报错 500
报错
405:post 请求写成 get 请求
500:加了 @JsonIgnore