首页 > 其他分享 >springboot+vue前后端分离项目-项目搭建15-集成JWT token权限验证

springboot+vue前后端分离项目-项目搭建15-集成JWT token权限验证

时间:2024-08-02 16:41:57浏览次数:10  
标签:15 springboot demo JWT token ServiceException import com example

1. 对之前的代码改造,之前将user存储到sessionStorage,改成存储到localStorage,全局搜索修改

 之前Result.code等于0代表success,改成200代表success, vue文件全局搜索修改

一、前端部分

1. 改造request.js,登录时将user已经存储到localStorage里,这里将user获取到,将user里的token放到请求头,后台根据请求头里的token进行校验

 2. 后台token校验不通过,返回401,这时重定向到登录页

 3. 修改退出系统按钮,退出时清空token和用户信息

 二、后端部分

1. pom.xml 里引入java-jwt包

 2. 创建 com/example/demo/common/JwtInterceptor.java 文件,内容是拦截规则

package com.example.demo.common;

import cn.hutool.core.util.StrUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.example.demo.entity.User;
import com.example.demo.exception.ServiceException;
import com.example.demo.mapper.UserMapper;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

public class JwtInterceptor implements HandlerInterceptor {

    @Resource
    private UserMapper userMapper;

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler){
        String token = request.getHeader("token");  // header里面传的参数
        if (StrUtil.isBlank(token)){
            token = request.getParameter("token");  // url参数
        }
        // 方法上有AuthAccess注解时,直接返回true,即取消拦截,直接通过
        if (handler instanceof HandlerMethod) {
            AuthAccess annotation = ((HandlerMethod) handler).getMethodAnnotation(AuthAccess.class);
            if (annotation != null) {
             return true;
            }
        }
        // 执行认证
        if (StrUtil.isBlank(token)) {
            throw new ServiceException("401", "请登录"); //401 权限错误
        }
        // 获取token中的userId
        String userID;
        try {
            userID = JWT.decode(token).getAudience().get(0); // JWT.decode(token) 解码
        } catch (JWTDecodeException e) {
            throw new ServiceException("401", "请登录");
        }

        // 根据token中的userId查询数据库
        User user = userMapper.selectById(Integer.valueOf(userID));
        if (user == null) {
            throw new ServiceException("401","请登录"); //权限错误
        }
        // 通过用户密码加密后生成一个验证器
        JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
        try {
            jwtVerifier.verify(token);  // 验证token
        } catch (JWTVerificationException e) {
            throw new ServiceException("401", "请登录");
        }
        return true;
    }
}

3. 创建 com/example/demo/common/config/InterceptorConfig.java 文件,将上一步自定义的 JwtInterceptor 拦截规则传入,使规则生效,定义拦截路径和不拦截路径

package com.example.demo.common.config;

import com.example.demo.common.JwtInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

@Configuration
public class InterceptorConfig extends WebMvcConfigurationSupport {

    protected void addInterceptors(InterceptorRegistry registry){
        registry.addInterceptor(jwtInterceptor())  //配置jwt的拦截器规则,传入JwtInterceptor自定义的规则
                .addPathPatterns("/**") //拦截所有的请求路径
                .excludePathPatterns("/user/login","/files/*"); //将特定请求取消拦截,也可以通过AuthAccess注解实现
        super.addInterceptors(registry);
    }

    @Bean
    public JwtInterceptor jwtInterceptor() {
        return new JwtInterceptor();
    }
}

3. 创建 com/example/demo/exception/ServiceException.java,拦截成功时会抛出 ServiceException 异常,这是个自定义的异常

package com.example.demo.exception;

import lombok.Getter;

@Getter
public class ServiceException extends RuntimeException {

    private final String code;
  
    public ServiceException(String msg){
        super(msg);
        this.code = "500";
    }

    public ServiceException(String code,String msg){
        super(msg);
        this.code = code;
    }
}

4. 创建com/example/demo/exception/GlobalException.java,定义 抛出 ServiceException 异常时进行的处理,返回Result

package com.example.demo.exception;

import com.example.demo.common.Result;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

@ControllerAdvice
public class GlobalException {

    @ExceptionHandler(ServiceException.class)
    @ResponseBody
    public Result<?> serviceException(ServiceException e){
        return Result.error(e.getCode(), e.getMessage());
    }
}

5. 第二种 取消拦截的方式,创建 com/example/demo/common/AuthAccess.java 注解

package com.example.demo.common;

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AuthAccess {
}

在方法上使用这个注解,拦截规则里获取 方法上的这个注解,如果获取到就取消拦截

6.user实体类增加token属性

7.改造登录方法,账号密码校验不通过时抛出 ServiceException 异常,账号密码正确时,生成token,存储到user里返回

测试:

登录时不进入拦截器,登录成功后跳转到用户管理,查询全部用户,这时跳转到拦截器,可以看到token已经生成并由前端传到后端

 

 页面本地存储里也有token

 

标签:15,springboot,demo,JWT,token,ServiceException,import,com,example
From: https://www.cnblogs.com/xiexieyc/p/18338722

相关文章

  • LeetCode 152 乘积最大子数组
    题目描述给你一个整数数组nums,请你找出数组中乘积最大的非空连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。测试用例的答案是一个32位整数。思路这一题用普通的连续子数组思路求解时有一个问题:子问题的最优解不一定是总体的最优局部解。也就是不满足最优......
  • 基于SpringBoot的智能购房推荐系统-09040(免费领源码)可做计算机毕业设计JAVA、PHP、爬
    Springboot智能购房推荐系统摘 要近年来随着我国经济的高速发展,房地产业也随之蓬勃发展,尤其是最近国家新出台的房改政策。鼓励居民购房,这对房产公司无疑是一个极好的发展势头。尤为重要的是,近几年随着信息技术和电子商务的快速发展,许多企业都开发了自己房产信息软件。智......
  • SpringBoot入门、进阶、强化、扩展、知识体系完善等知识点学习、性能优化、源码分析专
    场景作为一名Java开发者,SpringBoot已经成为日常开发所必须。势必经历过从入门到自学、从基础到进阶、从学习到强化的过程。当经历过几年企业级开发的磨炼,再回头看之前的开发过程、成长阶段发现确实是走了好多的弯路。作为一名终身学习的信奉者,秉承Java体系需持续学习、持续优......
  • Springboot Docker Redis Mysql集成
    尽管网上关于SpringbootDockerRedisMysql集成的文档很多,但是很多都是老文档,问题不少,所以我专门整理了这份文档。我家里的笔记本是mac,所以我就在mac上详细说明下我的搭建过程。首先我们需要安装docker,mac上本来就有docker的安装包,因此对于mac来说,安装docker就是一件比较轻松的......
  • 基于springboot+vue.js+uniapp在线考试系统的附带文章源码部署视频讲解等
    在这里插入图片描述@toc前言......
  • 基于Java+SpringBoot+Mysql+Vue实现的4S店保养与维修系统部分功能设计与实现八
    一、前言介绍:1.1项目摘要随着社会经济的不断发展,人们对汽车养护和维修的重视程度日益提高。然而,传统的汽车保养与维修服务存在诸多问题,如信息不对称、服务质量参差不齐等。这些问题不仅影响了消费者的服务体验,也制约了汽车后市场的健康发展。因此,为了解决这些问题,提升汽......
  • 基于Java+SpringBoot+Mysql+Vue实现的4S店保养与维修系统部分功能设计与实现九
    一、前言介绍:1.1项目摘要随着社会经济的不断发展,人们对汽车养护和维修的重视程度日益提高。然而,传统的汽车保养与维修服务存在诸多问题,如信息不对称、服务质量参差不齐等。这些问题不仅影响了消费者的服务体验,也制约了汽车后市场的健康发展。因此,为了解决这些问题,提升汽......
  • A086-基于SpringBoot+vue实现的在线小说阅读平台(源码+数据库+部署文档+包运行)
    (=======如需源码请查看博主个人信息介绍,可联系博主获取源码=============)开发语言和框架:JDK版本:确保使用JDK1.8,以支持SpringBoot的最新特性和性能优化。服务器:使用Tomcat7作为您的应用程序的服务器,提供可靠的运行环境和良好的性能。数据库:选择MySQL5.7作为......
  • A100-基于Springboot的网页时装购物系统的设计与实现(源码+论文+开题报告+PPT+包运行)
    3研究的内容目前许多人仍将传统的纸质工具作为信息管理的主要工具,而网络技术的应用只是起到辅助作用。在对网络工具的认知程度上,较为传统的office软件等仍是人们使用的主要工具,而相对全面且专业的时装购物系统的信息管理软件仍没有得到大多数人的了解或认可。本选题则旨在通......
  • 题解:CF1537E2 Erase and Extend (Hard Version)
    CF1537E2EraseandExtend题解分析通过观察题目,可以证明结果一定是由多次前缀复制得来的。题目要求你进行删和复制的操作,与其交替着操作,不如直接先删到最优的前缀再进行复制。现在就是要找最优的前缀。从头一位一位往后遍历。用\(l\)来存储目前最优前缀的长度,第\(i\)位......