从零用java实现 小红书 springboot vue uniapp (6)用户登录鉴权及发布笔记
前言
移动端演示 http://8.146.211.120:8081/#/
前面的文章我们主要完成了前端页面的开发
从今天开始我们开始前后端业务交互
首先讲解登录
- 前端传入手机号(目前演示不做限制)
- 后台根据传入的账号确定创建还是直接登录
- 返回前端token 前端携带token访问鉴权后的接口
登录代码
@ApiOperation(value = "验证码登陆")
@ApiOperationSupport(order = 1)
@PostMapping("/api/checkCode")
@Transactional
@OperLog(operModule = "获取验证码",operType = OperType.OTHER,operDesc = "验证码登陆")
public ResultBean<Author> checkCode(@RequestBody PhoneLoginDto phoneLoginDto) {
loginService.checkCode(phoneLoginDto);
//验证后登陆
Author author = authorService.selectAuthorByPhoneNumber(phoneLoginDto.getPhoneNumber());
if(author==null){
author = authorService.createNewAuthor(phoneLoginDto.getPhoneNumber());
}
//根据用户id生成token
final String token = jwtTokenUtil.generateTokenByUserId(author.getAuthorId());
author.setToken(token);
return ResultBean.success(author);
}
具体代码中,在 checkCode 方法里,先调用 loginService.checkCode 进行验证登录,接着通过手机号查找用户,若不存在则调用 createNewAuthor 方法创建新用户,之后根据用户 id 生成 token 并设置到用户对象中返回给前端。
创建用户后会随机生成一个人机昵称 规则 形容词 + 名词 +数字 例如(卑微小猪74)小红书号 预设头像 背景 当前登录ip和ip归属
public Author createNewAuthor(String phoneNumber) {
Author author = new Author();
author.setPhoneNumber(phoneNumber);
//随机生成昵称
author.setAuthorName(RandomXiaohongshuAuthorName.generateAuthorName());
author.setAuthorNo(StringUtil.getNumberForPK() + StringUtil.createCode(2));
author.setDescription("我是" + author.getAuthorName());
//生成随机头像因为没有点击上传所有没有头像id
author.setAvatarUrl("http://8.146.211.120:8080/upload/avatar/avatar ("+ StringUtil.createCode(1) +").jpg");
author.setBackGroundUrl("http://8.146.211.120:8080/upload/notes/note (6).jpg");
author.setIpAddress(IPUtils.getIpAddr(request)); // 请求IP
author.setIpRealAddress(AddressUtils.getRealAddress(author.getIpAddress())); //ip真实地址
this.save(author);
return author;
}
前端拿到token后每次请求都携带token
// 根据项目需要完成数据验证工作
app.post('/checkCode', {phoneNumber:this.phoneno,code:formData.pwd}, '','', (res => {
if(res.code == 200){
//保存token
app.setStorage('token',res.data.token)
app.setStorage('user',res.data)
app.navigate('/pages/switchPages/index','reLaunch')
}
}))
携带token后后台怎么处理呢
我们需要实现一个 拦截器 用于登录后接口的鉴权 判断登录者身份显示相应数据
创建一个拦截器
@Configuration
public class GolbalConfig implements WebMvcConfigurer {
@Autowired
private ApiInterceptor apiInterceptor;
// 注册拦截器的方法
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(apiInterceptor)
.addPathPatterns("/api/auth/**"); // 拦截/api下所有请求路径
}
}
ApiInterceptor的具体实现
@Component
public class ApiInterceptor implements HandlerInterceptor {
@Autowired
private JwtTokenUtil jwtTokenUtil;
@Autowired
private AuthorService authorService;
@Autowired
HttpServletRequest httpServletRequest;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 预请求过滤
if(RequestMethod.OPTIONS.name().equals(request.getMethod())) {
return true;
}
String token = request.getHeader("token");
if (StrUtil.isBlank(token)) {
throw new ApiException("请登录后访问");
}
//解析token
System.out.println(token);
String authorId = jwtTokenUtil.getUsernameFromToken(token);
request.setAttribute("authorId",authorId);
// Author author = authorService.getById(authorId);
// request.setAttribute("author",author);
return true;
}
}
注 拦截器有时候会拿不到token 结果发现会有options请求 我们直接返回true if(RequestMethod.OPTIONS.name().equals(request.getMethod())) {
return true;
}
之后 我们就可以通过
@ApiOperation(value = "获取博主信息")
@ApiOperationSupport(order = 1)
@GetMapping("/api/auth/getMine")
@OperLog(operModule = "获取博主信息",operType = OperType.QUERY,operDesc = "获取博主信息")
public ResultBean<Author> getMine() {
String authorId = String.valueOf(request.getAttribute("authorId"));
Author author = authorService.getById(authorId);
return ResultBean.success(author);
}
这样的方式获取当前登录者信息了
之后我们就可以创建我们自己的笔记了
点击tab的+号 进入笔记创作页面
基本原理是先上传图片 上传后返回文件id 然后文件id集合和标题内容一并传入后台
一个笔记怎么对应多张图片呢 图片字段不能创建到当前笔记上
需要有一个关联表
传入笔记id 图片id 笔记和图片形成一对多的关系 并加上排序
具体实现
@ApiOperation(value = "创建笔记")
@ApiOperationSupport(order = 1)
@PostMapping("/api/auth/addNote")
@OperLog(operModule = "创建笔记",operType = OperType.ADD,operDesc = "创建笔记")
public ResultBean addNote(@RequestBody NoteDto noteDto) {
String authorId = String.valueOf(request.getAttribute("authorId"));
Author author = authorService.getById(authorId);
Note note = BeanUtil.copyProperties(noteDto, Note.class);
note.setAuthorId(author.getAuthorId());
note.setAuthorName(author.getAuthorName());
note.setAuthorAvatar(author.getAvatarUrl());
note.setIpAddress(IPUtils.getIpAddr(request)); // 请求IP
note.setIpRealAddress(AddressUtils.getRealAddress(note.getIpAddress()));
noteService.save(note);
List<String> imgs = noteDto.getImgs();
List<NoteImg> noteImgList = new ArrayList<>();
for(int i=0;i<imgs.size();i++){
NoteImg noteImg = new NoteImg();
noteImg.setAuthorId(authorId);
noteImg.setNoteId(note.getNoteId());
noteImg.setImgSort(i);
File file = fileService.selectFileByFileId(imgs.get(i));
String serverName = request.getServerName();
System.out.println(serverName);
noteImg.setImgUrl("http://" + serverName + ":" + port + file.getFilePath());
noteImgList.add(noteImg);
}
noteImgService.saveBatch(noteImgList);
Note updateNote = noteService.getById(note.getNoteId());
updateNote.setFirstPicture(noteImgList.get(0).getImgUrl());
noteService.updateById(updateNote);
return ResultBean.success();
}
因为是登录后接口 我们已经拿到了作者信息
基本鉴权 创建笔记开发完毕 后续我们完成点赞收藏关注功能
代码地址
https://gitee.com/ddeatrr/springboot_vue_xhs