Reputation: 87
I got stuck with a cross origin cors issue with my project. I have to send a get request from my Angular2 app running on localhost:4200 to my Spring Boot backend running on localhost:8080 with some header attributes. the request i want to send looks like this:
test() {
let jwt = localStorage.getItem('token');
let headers = new Headers({
'Content-Type': 'application/json; charset=utf-8',
'Authorization': 'Bearer ' + jwt
});
let options = new RequestOptions({ headers: headers });
this.http.get('http://localhost:8080/service/events/byTeamId/1', options)
.map((response: Response) => response.json())
.subscribe(
data => console.log('Response: '+data),
err => console.log('error: '+err),
() => console.log('Secret Quote Complete')
);
}
But this request doesn't arrive on the server side how i'd like to have it. With Postman to test the api it works.
My Spring Boot Backend looks like this:
WebSecurityConfig.java:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
@Autowired
private SimpleCorsFilter simpleCorsFilter;
@Resource
private UserDetailsServiceImpl userDetailsService;
@Resource
private JwtAuthenticationProvider jwtAuthenticationProvider;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home", "/login", "/register").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(simpleCorsFilter, ChannelProcessingFilter.class)
.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.logout()
.permitAll()
.and().csrf().disable();
}...
My SimpleCorsFilter looks like this:
@Component
public class SimpleCorsFilter implements Filter {
private final Logger log = LoggerFactory.getLogger(SimpleCorsFilter.class);
public SimpleCorsFilter() {
log.info("SimpleCORSFilter init");
}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "http://localhost:4200");
//response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
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", "Content-Type, Accept, X-Requested-With, remember-me, Authorization");
chain.doFilter(req, res);
}
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void destroy() {
}
}
Wit Postman it works properly:
But when I test it on my chrome browser I get:
So to me it looks like i don't receive the header properties like "Authorization" at my backend. I also see this by debugging the request in the spring boot backend. I just see "null" as header of this request.
Does anyone have an idea why i don't get my request headers correct at the api endpoint?
I already had a look here:
restlet.com/blog/2016/09/27/how-to-fix-cors-problems/
and looked into several similar issues posted on stackoverflow.
Upvotes: 1
Views: 4764
Reputation: 2581
I have had this same issue and i am using spring boot for my api and Angular 2.3.1. Im not sure if you are using Npm and Angular Cli. If you are using npm for development then the following can be done to fix this issue. You can proxy the api calls to your backend.
Step 1: create a file called proxy.conf.json in the same directory as package.json with the following content
{
"/api": {
"target": "http://localhost:8080",
"secure": false,
"pathRewrite": {"^/api" : ""}
}
}
so instead of using http://localhost:8080/service/events/byTeamId/1
for your api requests you will use /api/service/events/byTeamId/1
Notice the added "/api" and the removal of "http://localhost:8080". This means that any request being made that starts with /api will be proxied. This is what you want because you don't just want any url being proxied. The line
"pathRewrite": {"^/api" : ""}
ensures that "/api" is removed so that in the end your actual url is being requested.
Step 2: Update package.json
Update the line
"start": "ng serve",
and change it to
"start": "ng serve --proxy-config proxy.conf.json",
this will ensure that the proxy is configured and used
Step 3: Use npm start
While using angular cli and making sure you are in the project directory you can now start your application where your requests are proxied using
npm start
Upvotes: 0
Reputation: 87
To me it works with this solution: add this to spring security config:
.antMatchers(org.springframework.http.HttpMethod.OPTIONS, "/service/**").permitAll()
http
.authorizeRequests()
.antMatchers("/", "/home", "/login", "/register").permitAll()
.antMatchers(org.springframework.http.HttpMethod.OPTIONS, "/service/**").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(simpleCorsFilter, ChannelProcessingFilter.class)
.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.logout()
.permitAll()
.and().csrf().disable();
(jwt token is still required, how i want to have it)
from:
CORS Origin Spring Boot Jhipster - pre-flight fails
Upvotes: 2