前端在浏览器总报错,且获取请求头中token的值为null

发布于:2024-07-27 ⋅ 阅读:(20) ⋅ 点赞:(0)

在这里插入图片描述
前端请求总是失败说受跨域请求影响,但前后端配置已经没有问题了,如下:

package com.example.shop_manage_sys.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.example.shop_manage_sys.Interceptor.TokenInterceptor;

@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Autowired
    private TokenInterceptor jwtInterceptor;
//cors配置
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")  // Applies CORS to all paths
                .allowedOrigins("http://127.0.0.1:8081", "http://localhost:8081")  // List specific allowed origins
                .allowedMethods("GET", "POST", "PUT", "DELETE","OPTIONS")
                .allowedHeaders("accept", "content-type", "origin", "custom-header","token")
                .allowCredentials(true)
                .maxAge(3600); 
    }
//拦截器配置
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(jwtInterceptor)
                .addPathPatterns("/**")
                .excludePathPatterns("/sms/*"); // 排除不需要拦截的路径
    }
}

后端获取前端请求头中自定义的token字段时获取到null,这是因为浏览器端会在请求前总发出一次预检请求,后端的拦截器将这种options请求直接放行即可。
示例拦截器代码:

package com.example.shop_manage_sys.Interceptor;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
// import org.springframework.web.servlet.ModelAndView;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import java.nio.charset.StandardCharsets;
import java.security.Key;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.server.ServletServerHttpResponse;


// import java.util.Base64;

@Component
public class TokenInterceptor implements HandlerInterceptor {
    @Value("${jwt.secret}")
    private String SECRET_KEY;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            // 直接放行预检请求
            return true;
        }
        
        String token = request.getHeader("token");
        if (token != null && !token.isEmpty()) {
            try {
                // 验证并解析token
                Key key = Keys.hmacShaKeyFor(SECRET_KEY.getBytes(StandardCharsets.UTF_8));
                Jws<Claims> claimsJws = Jwts.parserBuilder()
                                            .setSigningKey(key)
                                            .build()
                                            .parseClaimsJws(token);
                Claims claims = claimsJws.getBody();
                request.setAttribute("claims", claims);
                return true;
            } catch (Exception e) {
                handleJwtError(response, "Invalid or expired token.");
                return false;
            }
        } else {
            handleJwtError(response, "Token is missing.");
            return false;
        }
    }

    private void handleJwtError(HttpServletResponse response, String errorMessage) {
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
        response.setCharacterEncoding(StandardCharsets.UTF_8.name());
    
        try {
            // Wrap the ServletOutputStream in a ServletServerHttpResponse
            ServletServerHttpResponse outputMessage = new ServletServerHttpResponse(response);
            // Convert the JSON string to an Object
            Object jsonContent = "{\"error\": \"" + errorMessage + "\"}";
            
            // Write the JSON content to the output stream
            new MappingJackson2HttpMessageConverter().write(jsonContent, MediaType.APPLICATION_JSON, outputMessage);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    // 你可以选择性实现以下方法,但在这个场景下它们可能不是必须的
    // @Override
    // public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) {
    //     // ...
    // }
    //
    // @Override
    // public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
    //     // ...
    // }
}

网站公告

今日签到

点亮在社区的每一天
去签到