我的rest服务中没有Spring Security实施,并且尝试调用rest资源时遇到了CORS 401未经授权的问题。
我对此表示红色:
https://www.baeldung.com/spring-security-cors-preflight
https://docs.spring.io/spring-security/site/docs/5.0.7.RELEASE/reference/html5/#cors
我有2个休息的电话:
1)登录
2)其他
登录功能基于Shiro,例如,当我从Postman执行登录,然后尝试调用其他资源时,该功能就起作用了。
当我开始使用react实现客户端应用程序时,我的问题就开始了,而我正试图通过fetch javascript方法调用其余的应用程序。我在第一次调用登录名时遇到了CORS问题,并通过在控制器上添加@CorsOrigin批注解决了该问题,但是登录成功后,第二次调用在cors 401上仍然失败。
如果我正确理解,可以通过添加过滤器t oWebSecurityConfig来解决CORS,但是如果我的应用程序在Postman上运行,则无需在服务器端应用程序中进行此类更改,我想从客户端解决它。
那让我可以选择在请求中传递JSESSIONID,对吗? 我仍然不知道该怎么做...我应该从哪里获取JSESSIONID?我尝试读取浏览器的Cookie,但在该处找不到它...我尝试从第一次调用Login的Response标头中获取它,但Response为空!
试图用Spring在服务器端解决它,但是没有运气:
WebSecurityConfig:
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// http
// .cors();
// .headers().disable();
// http
// .authorizeRequests()
// .requestMatchers(CorsUtils::isCorsRequest).permitAll()
// .anyRequest().authenticated()
// .and().httpBasic()
// .and().addFilterBefore(new WebSecurityCorsFilter(), ChannelProcessingFilter.class);
http.addFilterBefore(new CorsFilter(), ChannelProcessingFilter.class);
}
}
WebSecurityCorsFilter:
public class WebSecurityCorsFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
res.setHeader("Access-Control-Max-Age", "3600");
res.setHeader("Access-Control-Allow-Headers", "Authorization, Content-Type, Accept, x-requested-with, Cache-Control");
chain.doFilter(request, res);
}
@Override
public void destroy() {
}
}
或者,CorsFilter(在其中使用):
@Component
//@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsFilter implements Filter{
public CorsFilter () {
super();
}
@Override
public final void doFilter(final ServletRequest req, final ServletResponse res, final FilterChain chain) throws IOException, ServletException {
final HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "http://localhost:3000");
// without this header jquery.ajax calls returns 401 even after successful login and SSESSIONID being succesfully stored.
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "X-Requested-With, Authorization, Origin, Content-Type, Version");
response.setHeader("Access-Control-Expose-Headers", "X-Requested-With, Authorization, Origin, Content-Type");
final HttpServletRequest request = (HttpServletRequest) req;
if (!request.getMethod().equals("OPTIONS")) {
chain.doFilter(req, res);
} else {
// do not continue with filter chain for options requests
}
}
@Override
public void destroy() {
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
}
答案 0 :(得分:0)
感谢类似的提取问题:https://github.com/github/fetch/issues/386
我终于做到了。因此,总结一下:
1)除了将注释添加到控制器外(无需将其添加到基本控制器中,所有注释都可以继承),无需更改Spring Security Config
@CrossOrigin(origins =“ *”,allowedHeaders =“ *”)
2)从客户端来看,在使用访存时,我必须同时使用两个请求(登录和第二个请求):
凭据:'include',//'same-origin'
(请注意,在使用cors时,请勿使用凭据的“ same-origin”值)
无需手动设置任何cookie,浏览器即可处理它(如果您需要编写Java客户端,则需要...可以搜索CookiesManagement java类,您将找到这种实现)