【发布时间】:2020-01-05 12:36:10
【问题描述】:
我已经设置了一个向 Spring 服务器发送请求的 Angular 客户端。我刚刚克服了 CORS 阻塞,所有请求都顺利通过。直到我在 spring 端添加了一个 @webFilter,现在我得到了 CORS 错误,允许 GET 请求,但不允许其他请求。
如果我将 webFilter 放在评论中,代码可以正常工作(但不检查登录)。
我在服务器端添加了一个 restConfig 类,它允许来自我的客户端地址 (localhost:4200) 的所有方法。
即使我将@CrossOrigin 放在每个控制器上(甚至在过滤器文件上),它也不会改变效果。
我在 Angular 端(每个请求)和服务器端(在 restConfig 类和 @CrossOrigin 注释中)都添加了 withCredentials。
我在 pom.xml 中添加了会话依赖项。
我在 Angular 端也有一个拦截器,但这是在我添加拦截器之前发生的。
例如,当我尝试删除时,控制台会写入错误: 选项http://localhost:8080/CouponSystem/sec/admin/removecompany/3 出现 401 错误(即使我已登录)并详细说明: 从源“http://localhost:4200”访问“http://localhost:8080/CouponSystem/sec/admin/removecompany/3”处的 XMLHttpRequest 已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:它没有 HTTP ok 状态。
如前所述,获取请求(返回 200)通过正常。
在检查发送的请求时,这些是删除中显示的标头: 请求网址:http://localhost:8080/CouponSystem/sec/admin/removecompany/3 请求方法:选项 状态码:401 远程地址:[::1]:8080 推荐人政策:降级时无推荐人 访问控制允许凭据:true 访问控制允许方法:删除 访问控制允许来源:http://localhost:4200 访问控制最大年龄:1800 允许:GET、HEAD、POST、PUT、DELETE、TRACE、OPTIONS、PATCH 内容长度:0 日期:2019 年 9 月 2 日星期一 13:00:00 GMT 变化:来源、访问控制请求方法、访问控制请求标头 显示临时标题 访问控制请求方法:删除 来源:http://localhost:4200 推荐人:http://localhost:4200/admin/removecompany Sec-Fetch-Mode: no-cors
如果它与更改标题有关,我需要具体说明如何添加标题。
这是网络过滤器:
//Overcoming CORS while allowing cookies
@CrossOrigin(origins = "*", allowedHeaders = "*", allowCredentials = "true",
methods= {RequestMethod.DELETE, RequestMethod.GET, RequestMethod.HEAD, RequestMethod.OPTIONS, RequestMethod.PATCH, RequestMethod.POST, RequestMethod.PUT, RequestMethod.TRACE})
@WebFilter("/sec/*")
public class LoginFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
HttpSession session = httpRequest.getSession(false);
if (session == null) {
httpResponse.sendError(401, "You are not logged in.");
} else {
chain.doFilter(httpRequest, httpResponse);
}
}
}
这是我的一个restControllers的相关代码:
@RestController
@RequestMapping("sec/admin")
//For overcoming CORS while allowing cookies
@CrossOrigin(origins = "http://localhost:4200", allowedHeaders = "*", allowCredentials = "true")
public class AdminWebService {
@Autowired
AdminService adminService;
@Autowired
HttpSession session;
//GET method - works fine
@RequestMapping(path = "companies")
public List<Company> findAllCompanies() {
return adminService.getAllCompanies();
}
@PostMapping(path = "newcompany")//CORS ERROR
public Company createCompany(@RequestBody Company company) throws IncompatibleInputException {
return adminService.createCompany(company);
}
@PutMapping(path = "updatecompany/{id}") //CORS ERROR
public void updateCompany(@PathVariable long id, @RequestBody Company company)
throws IncompatibleInputException, ObjectNotFoundException {
adminService.updateCompany(company, id);
}
@DeleteMapping(path = "removecompany/{id}")//CORS ERROR
public boolean deleteCompany(@PathVariable long id) throws ObjectNotFoundException {
adminService.removeCompany(id);
return true;
}
这是允许整个网络应用程序通过 CORS 的 restConfig 类(因此,据我了解,@CrossOrigin 并不是真正必要的。):
@SuppressWarnings("deprecation")
@Configuration
public class RestConfig{
@Bean
public WebMvcConfigurer corsConfigurer(){
return new WebMvcConfigurerAdapter() {
public void addCorsMappings(CorsRegistry registry) {
registry
.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "OPTIONS", "PUT", "DELETE", "TRACE")
.allowCredentials(true);
}
};
}
}
这是 Angular 方面 - 正在发送请求:
public updateCompany(companyToUpdate: Company) {
this.httpClient.put<Company>(`${this.baseUrl}updatecompany/${companyToUpdate.id}`, companyToUpdate, { withCredentials: true })
.subscribe(() => alert(`Company ${companyToUpdate.id} has been successfully updated.`), err => alert("We could not update this company. " + err.error.messages));
}
deleteCompany(id: number) {
if (confirm('Are you sure you want to delete company of id ' + id + '?')) { //user must confirm his intention to delete
this.httpClient.delete(`${this.baseUrl}removecompany/${id}`, { withCredentials: true })
.subscribe(res => {
alert(`Company ${id} deleted successfully.`);
this.getAllCompanies();//update table
}, err => {
alert("Unable to delete. " + err.error.messages);
this.getAllCompanies(); //Update dropdown with existing companies.
}
);
} else {
// Do nothing. Giving user a chance to regret it.
}
}
这是 Angular 端的拦截器——尽管我认为这不是问题,因为请求在发送到服务器之前就被 CORS 阻止了。
@Injectable()
export class HttpConfigInterceptor implements HttpInterceptor {
constructor(private router: Router) { }
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(request).pipe(catchError(error => {
// Checking if it is an Authentication Error (401)
if (error.status === 401) {
this.router.navigate([`/login`]);
alert('You are not logged in. Log in first.');
return throwError(error);
}
// If it is not an authentication error, just throw it
return throwError(error);
}));
}
}
我希望所有请求都能顺利通过,而不仅仅是 GET。 (如果用户没有登录,它应该过滤他并发送 401,然后 Angular 拦截器才会阻止他。)并在发送请求时停止给我 CORS 错误。
【问题讨论】:
-
浏览器控制台出现什么错误??
-
@gnanajeyam95 这是控制台中的文本:(提供示例浏览器文本我尝试使用删除请求删除公司) removecompany:1 Access to XMLHttpRequest at 'localhost:8080/CouponSystem/sec/admin/removecompany/5' from源“localhost:4200”已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:它没有 HTTP ok 状态。
标签: angular spring-boot session filter cors