当前位置: 代码迷 >> 综合 >> springboot拦截器实现权限认证 axios中get或post请求变成OPTIONS(遇到的Request Method: OPTIONS已解决)handler instanceof Hand
  详细解决方案

springboot拦截器实现权限认证 axios中get或post请求变成OPTIONS(遇到的Request Method: OPTIONS已解决)handler instanceof Hand

热度:115   发布时间:2023-11-24 02:57:39.0

参考博客:
axios中Post请求变成OPTIONS的几种解决方案

一、拦截器引入前

1.首先登录:
Login.vue

axios.post(url,{
    "userName":this.userName,"password":this.password}).then(response=>{
    if(response.data.code==0) {
    //console.log(response.data.token);window.localStorage.setItem("token",response.data.token);//路由跳转 登录成功后 跳转this.$router.replace('/phoneBook')}else {
    this.errorInfo = response.data.msg;}}).catch(error=>{
    this.errorInfo=error;
})

2.登录成功后跳转至电话簿列表页面:
PhoneBook.vue

export default {
    name: "PhoneBook",methods: {
    getPhoneBooks() {
    let url  = getServerUrl("phoneBook/loadAll")axios.get(url).then(response=>{
    console.log(response)}).catch(error=>{
    console.log(error)})}},mounted() {
    this.getPhoneBooks(); //加载所有电话簿信息}}

发起loadAll请求:

	/*** 查询所有电话簿信息 正常情况下要把token带过来才允许请求此方法* @return* @throws Exception*/@RequestMapping("/loadAll")public R loadAll()throws Exception{
    return R.ok("电话簿信息");}

在这里插入图片描述
很显然,下面的请求是没有携带token的
在这里插入图片描述
因此这很不合理,所以下面引入拦截器

二、拦截器的引入

1.SysInterceptor实现HandlerInterceptor接口

public class SysInterceptor implements HandlerInterceptor {
    @Overridepublic boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    String contextPath = request.getRequestURI();  //完整的请求地址System.out.println("路径:"+contextPath);String token = request.getHeader("token"); //从请求中取出tokenif(handler instanceof HandlerMethod){
    if(StringUtil.isEmpty(token)){
    System.out.println("签名验证不存在");//即token 不存在print(response, R.error(SystemConstant.JWT_ERRCODE_NULL,"签名验证不存在"));return false;}else {
    CheckResult checkResult = JwtUtils.validateJWT(token);if(checkResult.isSuccess()){
    System.out.println("签名验证通过");return true;}else {
    switch (checkResult.getErrCode()){
    case SystemConstant.JWT_ERRCODE_FAIL:System.out.println("签名验证不通过");print(response,R.error(SystemConstant.JWT_ERRCODE_NULL,"签名验证不通过"));break;case SystemConstant.JWT_ERRCODE_EXPIRE:System.out.println("签名验证已过期");print(response,R.error(SystemConstant.JWT_ERRCODE_EXPIRE,"签名验证已过期"));break;}return false;}}}return false;}private void print(HttpServletResponse response, Object message){
    try {
    response.setStatus(HttpStatus.OK.value());response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);response.setHeader("Cache-Control", "no-cache, must-revalidate");PrintWriter writer = response.getWriter();writer.write(message.toString());writer.flush();writer.close();} catch (IOException e) {
    e.printStackTrace();}}
}

JwtUtils在另一篇博客里面。
2.配置类里面配置拦截器

/**解决跨域问题 配置类*/
@Configuration
public class WebAppConfigurer implements WebMvcConfigurer {
    @Overridepublic void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**").allowedOrigins("*").allowCredentials(true).allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE","OPTIONS").maxAge(3600);}/** 这里配置把拦截器添上* 配置不需要拦截的请求* @param registry*/@Overridepublic void addInterceptors(InterceptorRegistry registry) {
    String[] patterns = new String[] {
    "/login","/*.html","/image"};registry.addInterceptor(new SysInterceptor()).addPathPatterns("/**").excludePathPatterns(patterns);}
}

3.首先测试,前端请求时不加token的情况
果然报错 说 签名验证不存在,因为前端发起请求时还未携带token呢!
在这里插入图片描述
下面 在前端请求时加上token:

export default {
    name: "PhoneBook",methods: {
    getPhoneBooks() {
    let token = window.localStorage.getItem("token")axios.defaults.headers.common['token']=tokenlet url  = getServerUrl("phoneBook/loadAll")axios.get(url).then(response=>{
    console.log(response)}).catch(error=>{
    console.log(error)})}},mounted() {
    this.getPhoneBooks(); //加载所有电话簿信息}}

3.下面报错了,让我们一探究竟
报错一:request.getHeader(“token”); //从请求中取出token为啥是空?
在这里插入图片描述

报错二:if语句里面的 handler instanceof HandlerMethod 为啥是false?

三.报错原因:

原来,我们在使用axios时,遇到了Request Method: OPTIONS

每个接口都调了两次,刚开始没太注意感觉两次请求是一摸一样的,仔细看了一圈,发现第一次调用的 Request Method: OPTIONS ,第二次调用的 Request Method: GET

至于为啥调用接口两次,参考这个博客:
使用axios时遇到的Request Method: OPTIONS

下面演示:

1.点击登录后 正常取出了localStorage里面的token:
在这里插入图片描述
2.点击OK
然后在请求 phoneBook/loadAll 之前 下面进入了拦截器:
在这里插入图片描述
很明显,上图中显示的 是第一次请求的OPTIONS 我们 返回true
然后我们将此次请求放行
3.下面来到第二次请求:
在这里插入图片描述
继续往下走:

在这里插入图片描述
token终于取到了,
在这里插入图片描述

四、小结:

主要就是下面代码:

 /* 每个接口都调了两次,刚开始没太注意感觉两次请求是一摸一样的,仔细看了一圈,发现第一次调用的 Request Method: OPTIONS ,第二次调用的 Request Method: POST或是GET 这里是GET所以下面必须加上这句 处理一下第一次请求的OPTIONS,否则我们就无法从request里面取出token了*/if(request.getMethod().equals("OPTIONS")){
    response.setStatus(HttpServletResponse.SC_OK);return true;}
  相关解决方案