I don't have a Spring Security implementation in my rest service, and I'm facing CORS 401 Unauthorized issue when trying to call resources in rest.
I red about it:
https://www.baeldung.com/spring-security-cors-preflight
https://docs.spring.io/spring-security/site/docs/5.0.7.RELEASE/reference/html5/#cors
I have 2 calls to rest:
1) Login
2) Others
The login functionality is based on Shiro, and when I perform login from Postman for example and then try to call other resource it works.
My problem starts when I started implementing a client side app with react and I'm trying to call the rest from fetch javascript method. I faced CORS issue when calling the login first and I solved it by adding @CorsOrigin annotation to my controller, but after login is succeeding the second call is still failing on cors 401.
If I correctly understand, CORS can be solved by adding filter t oWebSecurityConfig but if my app is working from Postman then there is no need to perform such a change in my server side app and I want to solve it from client side.
That leaves me with the option of passing the JSESSIONID in my requests, right?! I still didn't figure out how to do it... where should I take the JSESSIONID from? I tried reading the cookies of the browser but didn't find it there... I tried taking it from Response headers of the first call to Login but the Response is coming empty!
Tried to solve it with Spring in server side but with no luck:
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() {
}
}
Or, CorsFilter (using on of them):
@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 {
}
}

JSESSIONIDin you request header? - hrdkisback