当前位置: 首页 > news >正文

SpringBoot学习day2-前后端的交互搭建以及跨域问题、拦截过滤器问题的解决

  • 搭建前端项目,实现前后端交互
    • 跨域问题处理
    • 生成token
    • 前端保存用户token,账号
    • 在后端搭建管理员token验证的拦截器
    • 测试拦截器

搭建前端项目,实现前后端交互

1.复制之前宿舍管理系统的前端项目 命名为newsweb

跨域问题处理

2.前端发送异步请求,出现跨域问题

image-20250611183339351

在后端创建跨域处理过滤器如下图

image-20250611183415684

代码如下

package org.example.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import java.util.Collections;/*
* @Configuration注解表明这是一个配置类,可以包含@Bean注解的方法,这些方法将会在Spring容器中注册为Bean。
* */
@Configuration
public class CorsConfig {@Beanpublic CorsFilter corsFilter() {CorsConfiguration corsConfiguration = new CorsConfiguration();//1,允许任何来源corsConfiguration.setAllowedOriginPatterns(Collections.singletonList("*"));//2,允许任何请求头corsConfiguration.addAllowedHeader(CorsConfiguration.ALL);//3,允许任何方法corsConfiguration.addAllowedMethod(CorsConfiguration.ALL);//4,允许凭证corsConfiguration.setAllowCredentials(true);UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();source.registerCorsConfiguration("/**", corsConfiguration);return new CorsFilter(source);}
}

3.在后端登录成功后,

生成token

导入jwt jar包

<!--        jwt--><!-- https://mvnrepository.com/artifact/com.auth0/java-jwt --><dependency><groupId>com.auth0</groupId><artifactId>java-jwt</artifactId><version>4.4.0</version></dependency>

导入JWTUtil

package com.ffyc.ssm.util;import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.ffyc.ssm.model.Admin;
import org.springframework.stereotype.Component;import java.util.Date;
import java.util.HashMap;
import java.util.Map;/*** JWT工具类*/
@Component
public class JWTUtil {/*** 根据用户id,账号生成token* @param* @return*/public static String getToken(Admin admin) {String token = "";try {//过期时间 为1970.1.1 0:0:0 至 过期时间  当前的毫秒值 + 有效时间Date expireDate = new Date(new Date().getTime() + 10000*1000);//秘钥及加密算法Algorithm algorithm = Algorithm.HMAC256("ZCEQIUBFKSJBFJH2020BQWE");//设置头部信息Map<String,Object> header = new HashMap<>();header.put("typ","JWT");header.put("alg","HS256");//携带id,账号信息,生成签名token = JWT.create().withHeader(header).withClaim("id", admin.getAccount()).withExpiresAt(expireDate).sign(algorithm);}catch (Exception e){e.printStackTrace();return  null;}return token;}/*** 验证token是否有效* @param token* @return*/public static boolean verify(String token){try {//验签Algorithm algorithm = Algorithm.HMAC256("ZCEQIUBFKSJBFJH2020BQWE");JWTVerifier verifier = JWT.require(algorithm).build();DecodedJWT jwt = verifier.verify(token);return true;} catch (Exception e) {//当传过来的token如果有问题,抛出异常return false;}}/*** 获得token 中playload部分数据,按需使用* @param token* @return*/public static DecodedJWT getTokenInfo(String token){return JWT.require(Algorithm.HMAC256("ZCEQIUBFKSJBFJH2020BQWE")).build().verify(token);}}

前端对应的代码router

//路由导航守卫,每当前端发生一次路由跳转时,会自动触发beforeEach().
rout.beforeEach((to,from,next)=>{if(to.path=='/login'){//如果访问登录组件,不需要做任何判断,直接放行return next();//放行到目标组件}else{var token =  sessionStorage.getItem("adminToken");if(token==null){ //用户信息为空,说明用户没有登录return next("/login");}else{//说明用户已经登录next();}}
}

main.js

import Vue from 'vue'
import App from './App.vue'Vue.config.productionTip = false/* 导入路由 */
import router from './router/index.js'
Vue.use(router);/* 导入 elementUI*/
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
Vue.use(ElementUI);//导入axios组件
import axios from 'axios';
//设置后端默认地址
axios.defaults.baseURL="http://127.0.0.1:8080/";
//将axios对象挂载到vue对象上,并为其指定一个别名
Vue.prototype.$http=axios;//axios 请求拦截, 每当我们使用axios框架向后端发送请求时,都会经过拦截器
axios.interceptors.request.use(config =>{//为请求头对象,添加 Token 验证的 token 字段config.headers.token = sessionStorage.getItem('adminToken');return config;
})// 添加响应拦截器
axios.interceptors.response.use((resp) =>{//正常响应拦截if(resp.data.code==500){ElementUI.Message({message:resp.data.desc,type:"error"});}if(resp.data.code==401){ElementUI.Message({message:resp.data.desc,type:"error"});router.replace("/login");}return resp;
});new Vue({render: h => h(App),router,
}).$mount('#app')

前端保存用户token,账号

登录界面代码(存储token、accout、password)

<!-- 一个.vue文件是一个组件,可以理解为一个页面,但是和页面不同 内容都写在一个template标签中,template标签必须有一个根标签
-->
<template><div class="login_container"><!-- <audio ref="audio" :src="require('./assets/m.mp3')" loop autoplay  controls></audio> --><!-- 登录盒子--><div class="login_box"><!-- 头像盒子--><div class="img_box"><img src="./assets/logo.png" /></div><div style="margin-top: 100px; padding-right: 30px;"><el-form ref="form"  label-width="80px"><el-form-item label="账号"><el-input v-model="form.account"></el-input></el-form-item><el-form-item label="密码"><el-input v-model="form.password" type="password"></el-input></el-form-item><el-form-item><el-button type="primary" @click="login()">登录</el-button><el-button>取消</el-button></el-form-item></el-form></div></div></div>
</template><script>
/* 导出组件,并为组件定义数据,函数,生命周期函数 */export default{data(){return{form:{account:"admin",password:"111"}}},methods:{login(){if(this.form.account.length==0){this.$message({message: '账号不能为空!',type: 'warning'});return;}if(this.form.password.length==0){this.$message({message: '密码不能为空!',type: 'warning'});return;}//与后端进行交互this.$http.post("loginCtl/login",this.form).then((resp)=>{//根据后端响应回来的结果进行处理resp.data(result对象)if(resp.data.code==200){//前端浏览器中存储用户信息sessionStorage.setItem("adminToken",resp.data.data.adminToken);sessionStorage.setItem("account",resp.data.data.account);sessionStorage.setItem("password",resp.data.data.password);this.$router.push("/main");}else if(resp.data.code==201){this.$message({message: resp.data.desc,type: 'warning'});return;}else{this.$message({message: resp.data.desc,type: 'warning'});return;}});}}}
</script><style>.login_container{height: 100vh;margin: 0px;padding: 0px;background-image: url(assets/bg.jpg);}.login_box{width: 450px;height: 350px;background-color: #fff;border-radius: 10px;position: absolute;left: 50%;top: 50%;transform: translate(-50%,-50%);opacity: 0.95;}.img_box{width: 130px;height: 130px;position: absolute;left: 50%;transform: translate(-50%,-50%);background-color: #fff;border-radius: 50%;padding: 5px;border: 1px solid #eee;}.img_box img{width: 100%;height: 100%;border-radius: 50%;background-color: #eee;}
</style>

在后端搭建管理员token验证的拦截器

jar包

<!--spring中提供的解决跨域问题的过过滤器--><dependency><groupId>com.thetransactioncompany</groupId><artifactId>cors-filter</artifactId><version>2.5</version></dependency>

添加拦截器类

image-20250611192656119

package org.example.interceptor;import org.example.util.JWTUtil;
import org.springframework.web.servlet.HandlerInterceptor;import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;//定义拦截器
public class AdminTokenInterceptor implements HandlerInterceptor {@Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println("进入到了拦截器");//获得tokenString adminToken  =   request.getHeader("Token");System.out.println("token:"+adminToken);if(JWTUtil.verify(adminToken)){return true; //拦截器中返回true, 请求就会离开拦截器,继续向后执行,到达处理器}else{response.setContentType("text/html;charset=utf-8");PrintWriter writer = response.getWriter();writer.write("token验证失败");return false;//拦截器中返回false. 不会继续向后执行.  可以在拦截器中向用户做出响应}}
}

配置拦截器设置WebConfig

image-20250611193307339

package org.example.config;import org.example.interceptor.AdminTokenInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*;@Configuration
public class WebConfig implements WebMvcConfigurer{public void addInterceptors(InterceptorRegistry registry) {InterceptorRegistration inter =  registry.addInterceptor(new AdminTokenInterceptor());inter.addPathPatterns("/**"); //都得进入拦截器inter.excludePathPatterns("/loginCtl/login");//放行地址inter.addPathPatterns("/user/**"); //用户需要拦截过滤地址}}

测试拦截器

image-20250611194900306

登录进去之后删除Token,点击测试方法

前端测试方法

test(){this.$http.get("loginCtl/test");}

后端测试方法

@RequestMapping(path = "/test")public String test(@RequestBody Admin admin){return "success";}

清空Token

image-20250611195111291

激活test()方法

image-20250611195144658

响应拦截器,返回到了登录界面

对应main.js代码如下

// 添加响应拦截器
axios.interceptors.response.use((resp) =>{//正常响应拦截if(resp.data.code==500){ElementUI.Message({message:resp.data.desc,type:"error"});}if(resp.data.code==401){ElementUI.Message({message:resp.data.desc,type:"error"});//   删除Token、account、passwordsessionStorage.clear();router.replace("/login");}return resp;
});

image-20250611195239341

后端响应

image-20250611195251423

相关文章:

  • FEMFAT许可使用数据分析工具介绍
  • Jetson NX 从nvme恢复的emmc启动的方法
  • 华为交换机远程登录配置
  • 从C学C++(2)
  • uni-app项目实战笔记1--创建项目和实现首页轮播图功能
  • Visual Stdio程序弹出的黑框内容如何复制
  • ElasticJob初探
  • 6.11 note
  • ImportError: cannot import name ‘PfeifferConfig‘ from ‘transformers‘【已解决】
  • 再说一说LangChain Runnable接口
  • 酒店管理系统开发:量身定制,助力酒店高效管理与服务升级
  • uniapp uni.createAnimation为文件交换位置动画效果
  • Uniapp实现多选下拉框
  • Linux C学习路线全概括及知识点笔记3-网络编程
  • uniapp音乐播放createInnerAudioContext
  • # include<heαd.h>和# include″heαd.h″的区别
  • Argocd 运维与最佳实践
  • 【uniapp】小程序中input输入框的placeholder-class不生效
  • 【C++】来学习使用set和map吧
  • matlab分布式电源微电网潮流
  • 上海做网站公司哪家好/软件推广怎么赚钱
  • 海口网络建站模板/上海培训机构
  • 网页开发和网站开发一样吗/注册城乡规划师
  • 二合一子母被的好处/十堰seo优化
  • 做网站软件 wordpage/成都网站建设方案托管
  • 大连网站建设连城传媒/网站页面优化内容包括哪些