04 SB实战 -微头条之头条模块(登录验证拦截器+发布文章+修改文章)

本文详细介绍了如何在SpringMVC应用中实现登录验证,包括使用JWTtoken、创建拦截器检查登录状态以及处理发布和修改文章操作时的登录校验。着重展示了如何通过拦截器保护headline相关功能,确保只有登录用户才能访问受限资源。
摘要由CSDN通过智能技术生成

1.登陆验证

为什么还要做登陆验证?
尽管先前我们已经进行过登录, 但是要知道token是有有效期的, 而用户登陆后有可能长时间停留在页面不退出, 甚至这个停留的时间超出token有效期, 因此,尽管用户已经登录, 但是, 在需要登录才能进行的操作(进入发布页前、发布新闻前、进入修改页前)前, 仍需再对token进行登陆验证, 确保token仍在有效期.

  1. 接口描述

    url地址:user/checkLogin

    请求方式:get

    请求参数: 无

    请求头: token: 用户token

    响应数据:

    未过期:

{
    "code":"200",
    "message":"success",
    "data":{}
}
  过期:
{
    "code":"504",
    "message":"loginExpired",
    "data":{}
}
  1. 代码实现
    1. controller 验证token有效性
@Autowired
private JwtHelper jwtHelper;
    
@GetMapping("checkLogin")
public Result checkLogin(@RequestHeader String token){
    //校验token是否有效,可以直接调用jwtHelper的方法
    if (StringUtils.isEmpty(token) || jwtHelper.isExpiration(token)){
        //没有传或者过期 未登录
        return Result.build(null, ResultCodeEnum.NOTLOGIN);
    }
    
    return Result.ok(null);
}

编写完controller即可简单测试,先用post传json登录获取token, 再用该handler测试用token能不能登录
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

2. 创建拦截器

在这里插入图片描述

需要进行登录验证的功能有很多, 而头条下的功能涉及对数据库的修改, 因此都需要登录验证, 而头条的相关功能都位于/headline下, 因此不妨对/headline整体做个拦截器, 只要经过/headline的请求都要过一次拦截器校验登录状态是否有效.

  1. 需求描述

    • 客户端在进入发布页前、发布新闻前、进入修改页前、修改前、删除新闻前先向服务端发送请求携带token请求头
    • 后端接收token请求头后,校验用户登录是否过期并做响应
    • 前端根据响应信息提示用户进入登录页还是进入正常业务页面
      在这里插入图片描述
  2. 新建一个interceptor文件夹, 新建一个LoginProtectInterceptor拦截器 【所有/headline开头都需要检查登陆】

@Component
package com.sunsplanter.interceptor;

import com.alibaba.druid.util.StringUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sunsplanter.utils.JwtHelper;
import com.sunsplanter.utils.Result;
import com.sunsplanter.utils.ResultCodeEnum;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerAdapter;
import org.springframework.web.servlet.HandlerInterceptor;

/**
 * 检查请求头是否包含token
 */
@Component
public class LoginProtectInterceptor implements HandlerInterceptor {

    @Autowired
    private JwtHelper jwtHelper;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        String token = request.getHeader("token");
        if (StringUtils.isEmpty(token) || jwtHelper.isExpiration(token)){
            Result result = Result.build(null, ResultCodeEnum.NOTLOGIN);
            ObjectMapper objectMapper = new ObjectMapper();
            String json = objectMapper.writeValueAsString(result);
            response.getWriter().print(json);
            //拦截
            return false;
        }else{
            //放行
            return true;
        }
    }
}
  3. 新建一个config文件夹, 新建一个WebMVCConfig拦截器配置类
 package com.sunsplanter.config;

import com.sunsplanter.interceptor.LoginProtectInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMVCConfig implements WebMvcConfigurer {

    @Autowired
    private LoginProtectInterceptor loginProtectInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginProtectInterceptor).addPathPatterns("/headline/**");
    }
}

至此, 完成了拦截器的配置, 今后所有经过经过headline的请求都会先过拦截器,如果token有效则无感通过, 前往handler, 否则报错.

3. 发布文章

  1. 需求描述

    • 用户在客户端输入发布的新闻信息完毕后
    • 发布前先请求后端的登录校验接口验证登录
    • 登录通过则提交新闻信息
    • 后端将新闻信息存入数据库

在这里插入图片描述

  1. 接口描述

    url地址:headline/publish

    请求方式:post

    请求头: 用户token

    请求参数:

{
    "title":"尚硅谷宣布 ... ...",   // 文章标题
    "article":"... ...",          // 文章内容
    "type":"1"                    // 文章类别
}
响应数据:

未登录
{
    "code":"504",
    "message":"loginExpired",
    "data":{}
}
成功
{
    "code":"200",
    "message":"success",
    "data":{}
}
  1. 代码实现
    1. controller
/**
 * 实现步骤:
 *   1. token获取userId [无需校验,拦截器会校验]
 *   2. 封装headline数据
 *   3. 插入数据即可
 */
@PostMapping("publish")
public Result publish(@RequestBody Headline headline,@RequestHeader String token){

        //进既然进到了/headline/publish,说明拦截器已经校验token有效性,我们无需再管
        /**已知的信息只有token,title,article,type(文章类别),
         * 要完成插入headline表,必须补全headline表所需的其他信息:发布者ID,日期,阅读量
         * 正常来说这个是业务层的工作,congtroller只负责获取和返回参数,
         * 但要获取发布者ID的唯一办法是根据传入的token获取, 而接收传入参数又是controller的工作
         * 故在controller通过jwthelper逆向获取该登录用户的ID
         * 
         */
        int userId = jwtHelper.getUserId(token).intValue();
        headline.setPublisher(userId);
        Result result = headlineService.publish(headline);
        return result;
}
  1. service

@Override
public Result publish(Headline headline) {
    headline.setCreateTime(new Date());
    headline.setUpdateTime(new Date());
    headline.setPageViews(0);
    headlineMapper.insert(headline);
    return Result.ok(null);
}
  1. 即可测试. 测试两种情形
    a. 未登录状态下,直接走headline/publish
    在这里插入图片描述
    在这里插入图片描述

b. 先登录获取token, 再携带token走headline/publish
在这里插入图片描述在这里插入图片描述在这里插入图片描述
在这里插入图片描述
进headline表中即可找到新增的表项.

4. 修改文章

  1. 需求描述

    • 前端先调用登录校验接口,校验登录是否过期
    • 登录校验通过后 ,则根据新闻id查询新闻的完整信息并响应给前端
  2. 接口描述

    url地址:headline/findHeadlineByHid

    请求方式:post

    请求参数:Param传参hid

    响应数据:

    成功

{
    "code":"200",
    "message":"success",
    "data":{
        "headline":{
            "hid":"1",
            "title":"修改测试",
            "article":"... ... ",
            "type":"2"
        }
    }
}
  1. 代码实现
    1. headlineController
 /**
     *     url地址:headline/findHeadlineByHid
     *     请求方式:post
     *     请求参数:Param传参hid
     */
    @PostMapping("update")
    public Result update(@RequestBody Headline headline) {
        Result result = headlineService.updateHeadLine(headline);
        return result;
    }
  1. headlineService:
    Result updateHeadLine(Headline headline);
  1. headlineServiceImpl:
  @Override
    public Result updateHeadLine(Headline headline) {
        /**
         * 涉及对数据库的修改,加乐观锁
         * 1.查询version版本
         * 2.请求的参数为"hid","title","article","type",未请求的参数中作者ID与创建时间无需改变,仅更改UpdateTime和Version字段即可
         * 3.将更改的参数set入headline对象中,并用headline对象调用update方法
         * MP检测到修改,自动比对新旧Version
         */
            Integer version = headlineMapper.selectById(headline.getHid()).getVersion();

            headline.setVersion(version);
            headline.setUpdateTime(new Date());

            headlineMapper.updateById(headline);

            return Result.ok(null);
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值