I have configured spring security to enable cors.
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
#Autowired
private CustomLogoutHandler logoutHandler;
#Autowired
private HttpLogoutSuccessHandler logoutSuccessHandler;
#Override
protected void configure( HttpSecurity http ) throws Exception
{
http.cors().and().csrf().disable()
.authorizeRequests()
.antMatchers("/rest/noauth/**").permitAll()
.antMatchers("/rest/login").permitAll()
.antMatchers("/rest/logout").permitAll()
.antMatchers("/static/**").permitAll()
.antMatchers("/ws/**").permitAll()
.antMatchers("/rest/razorpay/hook").permitAll()
.antMatchers("/rest/user/cc").permitAll()
.antMatchers("/v2/api-docs/**", "/configuration/ui/**", "/swagger-resources/**",
"/configuration/security/**", "/swagger-ui.html/**", "/webjars/**")
.permitAll()
.anyRequest().authenticated()
.and()
.logout().addLogoutHandler(logoutHandler).logoutSuccessHandler(logoutSuccessHandler)
.logoutUrl("/rest/logout")
.and()
.addFilterBefore(
new JWTAuthenticationFilter("/rest/login", tokenService(), refreshTokenService,
authTokenModelRepository, userService, userActivitiesRepository,
handlerExceptionResolver, bCryptPasswordEncoder, redisTemplate),
UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new JWTAuthorizationFilter(authenticationManager(), authTokenModelRepository,
userSubscriptionRepository, handlerExceptionResolver, redisTemplate),
UsernamePasswordAuthenticationFilter.class);
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
#Override
public void configure( AuthenticationManagerBuilder auth ) throws Exception
{
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
}
}
and I have a rest controller,
#RestController
#RequestMapping( RestEndPoints.NO_AUTH_CONTROLLER )
#CrossOrigin(origins = "http://0.0.0.0:3000")
public class OtpController extends AbstractController {
#Autowired
private AuthService authService;
#ApiOperation( value = "Generate OTP to login using registered email address", response = UIResponse.class, notes = "Please do validate and send only the organisation email address" )
#ApiResponses( value = { #ApiResponse( code = 200, message = "Otp generated for <email_address>" ),
#ApiResponse( code = 400, message = "Email address not registered as CC", response = UIErrorMessage.class ),
#ApiResponse( code = 500, message = "Something went wrong", response = UIErrorMessage.class ) } )
#PostMapping( "/otp/{email_address:.+}" )
public ResponseEntity generateOtpToLogin( #PathVariable( "email_address" ) String emailAddress )
{
try
{
return buildResponse(authService.generateOtpForTheEmailAddress(emailAddress));
}
catch( DataException e )
{
return buildError(e);
}
}
}
But, when an API request is made from a frontend application to the POST method, the browser is making an OPTIONS call and that response headers as Access-Control-Allowed-Origin:* even though I am setting it to 0.0.0.0:3000 and the browser is getting the error,
Access to XMLHttpRequest at
'http://192.168.1.3:8090/rest/noauth/otp/sandesha#test.com' from
origin 'http://0.0.0.0:3000' has been blocked by CORS policy: The
value of the 'Access-Control-Allow-Origin' header in the response must
not be the wildcard '*' when the request's credentials mode is
'include'. The credentials mode of requests initiated by the
XMLHttpRequest is controlled by the withCredentials attribute.
How to resolve this issue?
I faced same issue earlier, I suppose it expect some other parameter also.
So that i place following code and it's working file for me.
package com.ecommerce.auth_service.service.jwt;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
#Component
#Order(Ordered.HIGHEST_PRECEDENCE)
public class SimpleCORSFilter implements Filter {
private final Logger log = LoggerFactory.getLogger(SimpleCORSFilter.class);
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
String check = "xsrf-token,X-Total-Results,Authorization";
response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me, Authorization");
response.setHeader("Access-Control-Expose-Headers",check);
if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
log.debug("Request get method call status SC_OK.");
response.setStatus(HttpServletResponse.SC_OK);
} else {
log.debug("Request get method not work chain start.");
chain.doFilter(req, res);
}
}
#Override
public void init(FilterConfig filterConfig) {
}
#Override
public void destroy() {
}
}
Related
I'm trying to request data from my backend through my frontend, but I'm getting the error:
Access to XMLHttpRequest at 'http://localhost:8081/api/transactions/' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I am able to get the data with postman, but not my frontend. I'm using angular and spring boot.
My application.java:
#EnableJpaRepositories
#EntityScan
#SpringBootApplication
public class KoalaTreeAccountingApplication {
public static void main(String[] args) {
SpringApplication.run(KoalaTreeAccountingApplication.class, args);
}
}
My security config:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest()
.permitAll()
.and().csrf().disable();
}
}
My service to make the http call in angular:
#Injectable({
providedIn: 'root'
})
export class TransactionService {
baseUrl = 'http://localhost:8081/api/';
transactionUrl = this.baseUrl + 'transactions/';
constructor(private http: HttpClient, private logger : Logger){ }
getAllTransactions() : Observable<Transaction[]> {
this.logger.log("Request all transactions");
return this.http.get<Transaction[]>(this.transactionUrl);
}
getTransactionById(id : number) : Observable<Transaction> {
this.logger.log("Request transaction " + id);
return this.http.get<Transaction>(this.transactionUrl + id);
}
}
Edit: I've tried
https://spring.io/guides/gs/rest-service-cors/
Spring Security CORS filter not working
Security configuration with Spring-boot
https://stackoverflow.com/a/31748398/12025088
Protip: clean install before re-running the application after a change. I'm an idiot.
Fixed by using this instead of SecurityConfig.java:
#Component
public class SimpleCORSFilter implements Filter {
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) res;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
response.setHeader("Access-Control-Max-Age", "36000");
response.setHeader("Access-Control-Allow-Headers", "origin, content-type, accept");
chain.doFilter(req, res);
}
public void init(FilterConfig filterConfig) {
}
public void destroy() {
}
}
You need to configure CORS on the methods of your RestController that you want to allow it. CORS is a server response.
#CrossOrigin(origins = "http://localhost:4200")
#GetMapping("/")
public List<Transaction> findAllTransactions() {
return transactionService.findAllTransactions(); }
}
I have created one app using angular and springboot for basic authentication with spring security but i am getting 401 error ..i am novice in springboot
#Configuration
#EnableWebSecurity
public class SpringSecurityConfigurationBasicAuth extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS,"/**").permitAll()
.anyRequest().authenticated()
.and()
//.formLogin().and()
.httpBasic();
}
}
"Access to XMLHttpRequest at 'http://localhost:8080/hello-world/path-variable/MSD' from origin 'http://localhost:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status."
I also had the same issue with angulat7 and spring boot I resolved by adding the following configuration
#Configuration
public class SpringDataRestConfiguration extends RepositoryRestConfigurerAdapter {
#Override
public void configureRepositoryRestConfiguration(RepositoryRestConfiguration config) {
config.getCorsRegistry().addMapping("/**").allowedOrigins("*").allowedHeaders("*").allowedMethods("GET", "POST", "PATCH", "PUT", "DELETE");
}
}
You could try the following
At the top of the controller, you can add #CrossOrigin(origins = "*", allowedHeaders = "*") or customise if required
...
#CrossOrigin(origins = "*", allowedHeaders = "*")
#RestController
public class UserController {
// Methods
}
...
Please try above solution and let me know if this doesnt work
EDIT 1:
You could also try to create a filter with CORS options:
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
#Component
#Order(1)
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", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With, remember-me");
chain.doFilter(req, res);
}
#Override
public void init(FilterConfig filterConfig) {
}
#Override
public void destroy() {
}
}
Please try with the filters method and let me know if it doesn't work
I always encounter this in Frontend says Access to XMLHttpRequest at 'api/abc/xyz' from origin 'localhost://2800/api/abc/xyz' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
I tried this to add in Backend
`
http.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS).permitAll()
.anyRequest().authenticated();
`
and my frontend AJAX CALL API:
`
$.ajax({
'type': 'GET',
'url': '/api/vessel/?vesselId=' + $('#vessel_id').val() + '&page=1&size=100',
'headers': {
"Content-Type": "application/json",
"Accept": "application/json",
"Authorization": `Bearer ${session}`
},
success: function(response) {console.log(response)}
});
`
But after that I still encounter that error.
`
#Override
protected void configure(HttpSecurity http) throws Exception {
// Disable CSRF (cross site request forgery)
http.csrf().disable();
// No session will be created or used by spring security
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// Entry points
http.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS).permitAll()
// Disallow everything else..
.anyRequest().authenticated();
// If a user try to access a resource without having enough permissions
//http.exceptionHandling().accessDeniedPage("/login");
// Apply JWT
http.apply(new JwtTokenFilterConfigurer(jwtTokenProvider));
// Optional, if you want to test the API from a browser
// http.httpBasic();
}
`
You have to config the CORS Configurations. Add the following class in your Project. You can change this as per your requirements.
WebConfig.java
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
#Configuration
#EnableWebMvc
public class WebConfig implements Filter {
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
HttpServletResponse response = (HttpServletResponse) res;
HttpServletRequest request = (HttpServletRequest) req;
System.out.println("WebConfig; "+request.getRequestURI());
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, PUT, GET, OPTIONS, DELETE");
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With,observe");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Expose-Headers", "Authorization");
response.addHeader("Access-Control-Expose-Headers", "responseType");
response.addHeader("Access-Control-Expose-Headers", "observe");
System.out.println("Request Method: "+request.getMethod());
if (!(request.getMethod().equalsIgnoreCase("OPTIONS"))) {
try {
chain.doFilter(req, res);
} catch(Exception e) {
e.printStackTrace();
}
} else {
System.out.println("Pre-flight");
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST,GET,DELETE,PUT");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Access-Control-Expose-Headers"+"Authorization, content-type,"+
"access-control-request-headers,access-control-request-method,accept,origin,authorization,x-requested-with,responseType,observe");
response.setStatus(HttpServletResponse.SC_OK);
}
}
}
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers(HttpMethod.OPTIONS,"/**");
//URL you want to ignore
}
#Override
protected void configure(HttpSecurity http) throws Exception {
// Disable CSRF (cross site request forgery)
http.csrf().disable();
// No session will be created or used by spring security
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
// Entry points
http.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS,"/**").permitAll()
// Disallow everything else..
.anyRequest().authenticated();
// If a user try to access a resource without having enough permissions
//http.exceptionHandling().accessDeniedPage("/login");
// Apply JWT
http.apply(new JwtTokenFilterConfigurer(jwtTokenProvider));
// Optional, if you want to test the API from a browser
// http.httpBasic();
}
I'm trying to write an application with separated Backend (written using Spring Boot, and Spring Security for login) and Frontend (ReactJS). Right now I'm struggling with accessing a secured endpoint after a successful login.
What I want to achieve: Make a GET to secured endpoint e.g. '/books/all'. If user not logged in, return 401. If 401 received on front-end, make a POST to '/login'. Then I want to have a successful login and to be able to make a successful GET to '/books/all'.
What doesn't work: The last part. I'm making a POST to '/login' and receive 200 GET. Then I make a second call to '/books/all' and receive GET 401. Also I no longer receive JSESSIONID cookie which worries me.
My question: how to fix this behavior? I believe it's connected to JSESSIONID (server doesn't send information about user being successfully logged in?).
On front-end I'm using axios.
axios.get('http://localhost:8080/rest/book/anna/all')
.then(response => {
console.log('response rebuild');
console.log(response);
if (response.status === 401 && response.request.responseURL === 'http://localhost:8080/login') {
axios.post('http://localhost:8080/login', 'username=c&password=d')
.then(response => {
console.log('response 2');
console.log(response);
})
.catch(error => {
console.log('error');
console.log(error);
})
}
})
.catch(error => {
console.log('error 2');
console.log(error);
axios.post('http://localhost:8080/login', 'username=c&password=d')
.then(response => {
console.log('response 2');
console.log(response);
axios.get('http://localhost:8080/rest/book/anna/all')
.then(response => {
console.log('response 3');
console.log(response);
})
.catch(error => {
console.log('error 3');
console.log(error);
})
})
.catch(error => {
console.log('error');
console.log(error);
})
});
Please mind that I'm aware that this code it's low quality; it's just temporary to check if redirection after login is working.
SecurityConfig.java
package com.shareabook.security;
import com.shareabook.repository.UsersRepository;
import com.shareabook.service.CustomUserDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
#EnableGlobalMethodSecurity(prePostEnabled = true)
#EnableWebSecurity
#EnableJpaRepositories(basePackageClasses = UsersRepository.class)
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private CustomUserDetailsService userDetailsService;
#Autowired
private RESTAuthenticationEntryPoint restAuthenticationEntryPoint;
#Autowired
private RESTAuthenticationSuccessHandler restAuthenticationSuccessHandler;
#Autowired
private RESTAuthenticationFailureHandler restAuthenticationFailureHandler;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(getPasswordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors()
.and()
.csrf().disable()
.authorizeRequests()
.antMatchers("**/anna/**").authenticated()
.anyRequest().permitAll();
http.exceptionHandling().authenticationEntryPoint(restAuthenticationEntryPoint);
http.formLogin().successHandler(restAuthenticationSuccessHandler);
http.formLogin().failureHandler(restAuthenticationFailureHandler);
// .and()
// .formLogin().permitAll();
http
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/rest/author/all");
}
private PasswordEncoder getPasswordEncoder() {
return new PasswordEncoder() {
#Override
public String encode(CharSequence charSequence) {
return charSequence.toString();
}
#Override
public boolean matches(CharSequence charSequence, String s) {
return true;
}
};
}
}
RESTAuthenticationEntryPoint.java
#Component
public class RESTAuthenticationEntryPoint implements AuthenticationEntryPoint {
#Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException)
throws IOException, ServletException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
}
RESTAuthenticationFailureHandler.java
#Component
public class RESTAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
#Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException,
ServletException {
super.onAuthenticationFailure(request, response, exception);
}
}
RESTAuthenticationSuccessfulHandler.java
#Component
public class RESTAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
#Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
// clearAuthenticationAttributes(request);
HttpSession session = request.getSession();
session.setAttribute("username", "c");
response.setStatus(HttpServletResponse.SC_OK);
}
}
BooksController.java
#RestController
#RequestMapping("/rest/book")
public class BookController {
#CrossOrigin(origins = "http://localhost:8888")
#PreAuthorize("hasAnyRole('ROLE_ADMIN')")
#RequestMapping(value = "/anna/all", method = RequestMethod.GET)
public List<String> securedHello() {
List<String> word = new ArrayList<>();
word.add("all");
System.out.print(word);
return word;
}
}
You have enabled forms authentication on your application. At the moment you send the post to login page Spring authenticates your request and by default caches the authnetication on user session.
Later you can send requests to server bound to the same session without additional authentication information. But you need to provide session information on your request. Usually this is done by supplying the JSESSIONID cookie on your next requests. Browser does this for you automatically but only after page reload. If you stay of the same page only cookies loaded for that page initially will be sent back to server.
For SPA applications I would suggest using token-based authentication instead of forms. You will have first to login and receive a token in response. Next you will have to supply Authorization header with each your request providing token as authentication information (usually in form Bearer <token>)
Late answer, but may help someone.
Try to add header "Access-Control-Allow-Credentials" with value "true" to your server responses. And in request config of axios calls set option withCredentials to true as well.
I have probem with Spring Boot and Cors
After some searches I was able to find solutions (Spring Data Rest and Cors and How to configure CORS in a Spring Boot + Spring Security application?) which I tried but which does not solve my problem.
My code for the Authentication with JWT
public class AuthenticationFilter extends AbstractAuthenticationProcessingFilter
{
private final Logger log = LoggerFactory.getLogger(AuthenticationFilter.class);
private final String tokenHeader = "Authorization";
private final TokenUtils tokenUtils = new TokenUtils();
public AuthenticationFilter()
{
super("/api/v1/**");
tokenUtils.expiration = 86400;
tokenUtils.secret = "papipapo123popo";
}
#Override
public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws AuthenticationException, IOException, ServletException
{
String header = httpServletRequest.getHeader(tokenHeader);
if(header == null || !header.startsWith("Bearer "))
{
log.error("Not found JWT token in request headers","Not found header Authorization");
throw new JwtTokenMissingException("No JWT token found in request headers");
}
String token = header.substring(7);
JwtAuthentication jwtAuthentication = new JwtAuthentication(token);
boolean isValid = tokenUtils.validateToken(token);
if(!isValid)
{
log.error("JWT token is expired",token);
throw new JwtTokenExpired("JWT token is expired");
}
return this.getAuthenticationManager().authenticate(jwtAuthentication);
}
#Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException
{
super.successfulAuthentication(request, response, chain, authResult);
String token = ((JwtAuthentication)authResult).getToken();
log.info("Token is authenticated : ",token);
chain.doFilter(request, response);
}
#Override
protected AuthenticationManager getAuthenticationManager()
{
return authentication -> (JwtAuthentication) authentication;
}
}
My code for Configuration security
#Configuration
#EnableWebSecurity
#EnableAutoConfiguration
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter
{
#Inject
private EntryPointUnauthorizedHandler entryPointUnauthorizedHandler;
#Inject
private JwtAuthenticationProvider jwtAuthenticationProvider;
#Bean
#Override
public AuthenticationManager authenticationManager() throws Exception
{
return new ProviderManager(Arrays.asList(jwtAuthenticationProvider));
}
#Bean
public AuthenticationFilter authenticationFilter() throws Exception
{
AuthenticationFilter authenticationFilter = new AuthenticationFilter();
authenticationFilter.setAuthenticationManager(authenticationManager());
authenticationFilter.setAuthenticationSuccessHandler(new EntryPointSuccessHandler());
return authenticationFilter;
}
#Bean
public FilterRegistrationBean corsFilter()
{
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.addAllowedOrigin("*");
source.registerCorsConfiguration("/**",config);
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(new CorsFilter(source));
filterRegistrationBean.setOrder(0);
return filterRegistrationBean;
}
#Override
protected void configure(HttpSecurity http) throws Exception
{
http
.csrf()
.disable()
.exceptionHandling()
.authenticationEntryPoint(entryPointUnauthorizedHandler)
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
.antMatchers(HttpMethod.POST,"/api/auth").permitAll()
.anyRequest().authenticated();
http.addFilterBefore(authenticationFilter(),UsernamePasswordAuthenticationFilter.class);
http.headers().cacheControl();
}
}
I always receive an error 401 refused accesse.
I am a beginner in Spring-Boot.
You can help me.
I solved my problem by adding a Class which implements Filter.
#Component
public class CorsConfig implements Filter
{
#Override
public void init(FilterConfig filterConfig) throws ServletException
{}
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException
{
HttpServletRequest request = (HttpServletRequest) servletRequest;
String method = request.getMethod();
if(method.equals("OPTIONS") || method.equals("options"))
{
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
response.setStatus(200);
filterChain.doFilter(servletRequest, servletResponse);
}
else
{
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization");
filterChain.doFilter(servletRequest, servletResponse);
}
}
#Override
public void destroy()
{}
}
First class:
#Configuration
public class MyConfiguration {
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
};
}
}
Second class:
#EnableWebSecurity
#Configuration
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**").authorizeRequests().requestMatchers(CorsUtils::isPreFlightRequest).permitAll()
.anyRequest().fullyAuthenticated().and().httpBasic().and().csrf().disable();
}
}
And be happy my friend
1: Create a class WebMvcConfig extends WebMvcConfiguration and override addCorsMappings method.
2: Don't forget to make it #Configuration annotation
#Configuration
public class WebMvcCofig implements WebMvcConfigurer{
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/*")
.allowedOrigins("*")
.allowedMethods("*")
.allowedHeaders("*")
.allowCredentials(true);
}
}