【发布时间】:2021-10-31 19:36:16
【问题描述】:
我正在构建一个应用程序,该应用程序在 Java Spring boot 中具有后端,在 React 中具有前端。为了将令牌从客户端传递到服务器,我使用了一个如下所示的过滤器类:
@Component
@Order(1)
public class ApplicationFilter implements Filter {
@Autowired
private UserDetails userDetails;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String token = httpRequest.getHeader("Authorization").substring(7);
Jws<Claims> jwsParsed = null;
try {
jwsParsed = Jwts.parserBuilder()
.setSigningKey("Yn2kjibddFAWtnPJ2AFlL8WXmohJMCvigQggaEypa5E=".getBytes())
.build()
.parseClaimsJws(token);
} catch (Exception e) {
throw new AuthenticationException("The token is not correct.");
}
Long id = jwsParsed.getBody().get("id", Long.class);
String name = jwsParsed.getBody().get("name", String.class);
userDetails.setUserId(id);
userDetails.setUserName(name);
chain.doFilter(httpRequest, response);
}
除此之外,我正在配置网络配置:
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer{
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedMethods("PUT", "DELETE","POST","GET")
.allowedOrigins("*")
.exposedHeaders("*");
}
}
让请求通过 CORS 策略。而且我还配置了上下文侦听器以在应用程序中使用请求上下文:
@Configuration
public class RequestContextListenerConfig {
@Bean
@Order(0)
public RequestContextListener requestContextListener() {
return new RequestContextListener();
}
}
块引用
在客户端,我定义了一个身份验证服务:
class AuthApiService {
api = null;
constructor() {
this.api = axios.create();
this.api
.interceptors
.request
.use(config => {
config.baseURL = "http://localhost:8080/";
config.headers = {
Authorization: `Bearer ${loginService.getUserToken()}`
};
return config;
});
}
getApi = () => this.api;
}
const authApiService = new AuthApiService();
export const authApi = authApiService.getApi();
export default authApiService;
并像这样在我的请求中使用它:
addItem(item) {
authApi.post("image", item)
.then((response) => {
item.id = response.data.id;
this.galleryItems.push(item);
this.dataWasChanged.next("ADD");
}).catch((err) => {
console.error(err.response);
});
}
问题是当我运行这个添加函数时,它在控制台中给我一个错误:
Access to XMLHttpRequest at 'http://localhost:8080/' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
在java中也是如此:
ERROR 46280 --- [nio-8080-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception
Cannot invoke "String.substring(int)" because the return value of "javax.servlet.http.HttpServletRequest.getHeader(String)" is null
我更确定令牌已发送,因为在出现错误之前我看到它打印在控制台中。此外,当我通过 Postman 访问应用程序时,一切都使用令牌。
我从 Postman 打印了标题,它们是:
Header 'authorization' = Bearer eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbGdhIiwic3ViIjoiZ2FsbGVyeUFwcCIsImlkIjoyLCJuYW1lIjoiTWF4IiwiaWF0IjoxNjM1MTkwMDA5LCJleHAiOjE2Mzc4NzIwMDl9.KV7PNXDIITMQcmzsLOF0WMF34-t4PP47URMoiGJYvvs
Header 'content-type' = application/json
Header 'user-agent' = PostmanRuntime/7.28.4
Header 'accept' = */*
Header 'postman-token' = 21eee286-c554-442f-a169-ab82926165f7
Header 'host' = localhost:8080
Header 'accept-encoding' = gzip, deflate, br
Header 'connection' = keep-alive
Header 'content-length' = 85
但是从浏览器请求中我看到了这些标头:
host: localhost:8080
connection: keep-alive
accept: */*
access-control-request-method: POST
access-control-request-headers: authorization,content-type
origin: http://localhost:3000
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36
sec-fetch-mode: cors
sec-fetch-site: same-site
sec-fetch-dest: empty
referer: http://localhost:3000/
accept-encoding: gzip, deflate, br
accept-language: ru-RU,ru;q=0.9,en;q=0.8,he;q=0.7
根本没有授权标头。
所以问题是为什么授权令牌没有来自 react 客户端的 java 代码?我做错了什么,哪里可能是错误?或者有没有其他方法可以从我发送到服务器的标头中接收令牌?
【问题讨论】:
标签: reactjs spring-boot authorization token client-server