Spring security 403 ошибка

I’m trying to secure my website using Spring Security following the guides on the web.

So on my server side I have the following classes.

My WebSecurityConfigurerAdapter:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter implements ApplicationContextAware {

    @Override
    protected void registerAuthentication(AuthenticationManagerBuilde rauthManagerBuilder) throws Exception {
        authManagerBuilder.inMemoryAuthentication().withUser("user").password("password").roles("ADMIN");
    }
}

My controller:

@Controller
//@RequestMapping("/course")
public class CourseController implements ApplicationContextAware {

    @RequestMapping(value="/course", method = RequestMethod.GET, produces="application/json")
    public @ResponseBody List<Course> get(  // The criterion used to find.
        @RequestParam(value = "what", required = true) String what,
        @RequestParam(value = "value", required = true) String value) {
        //.....
    }

    @RequestMapping(value = "/course", method = RequestMethod.POST, produces = "application/json")
    public List<Course> upload(@RequestBody Course[] cs) {
        
    }
}

What confused me very much is the server does not respond to the POST/DELETE method, while the GET method works fine. BTW, I’m using RestTemplate on the client side.

Exceptions are:

Exception in thread "main" org.springframework.web.client.HttpClientErrorException: 403 Forbidden
    at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91)
    at org.springframework.web.client.RestTemplate.handleResponseError(RestTemplate.java:574)
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:530)
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:487)
    at org.springframework.web.client.RestTemplate.delete(RestTemplate.java:385)
    at hello.Application.createRestTemplate(Application.java:149)
    at hello.Application.main(Application.java:99)

I’ve searched the internet for days. Still don’t have a clue. Please help. Thanks so much

Table of Contents

1. Overview

In this article, we’ll have a look at how to handle Spring Security exceptions produced by our Spring Security Resource Server . To do so, we’ll also use a practical example where all the necessary configurations will be explained. First of all, let’s make a short introduction to Spring Security.

Spring Security is a library that’s part of the Spring project. It tries to group all the functionalities of user access control on Spring projects . Access control allows limiting the options that can be executed by a given set of users or roles on the application. In this direction, Spring Security controls invocations to business logic or limits the access of HTTP requests to certain URLs . With this in mind, we must configure the application by telling Spring Security how the security layer should behave.

In our case, we’ll focus on the configuration of exception handlers. Spring Security offers three different interfaces to accomplish this purpose and to control the events produced:

  • Authentication Success Handler
  • Authentication Failure Handler
  • Access Denied Handler

Firstly, let’s take a closer look at the configuration.

3. Security Configuration

First of all, we’ve our configuration class that has to extend the WebSecurityConfigurerAdapter class. This will be in charge of managing all the security configurations of the application. So, it’s here where we have to introduce our handlers.

On the one hand, we’ll define the required configuration:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Override
protected void configure(HttpSecurity http) throws Exception {
    http.csrf()
      .disable()
      .httpBasic().disable()
      .authorizeRequests()
      .antMatchers("/login").permitAll()
      .antMatchers("/customError").permitAll()
      .antMatchers("/access-denied").permitAll()
      .antMatchers("/secured").hasRole("ADMIN")
      .anyRequest().authenticated()
      .and()
      .formLogin()
      .failureHandler(authenticationFailureHandler())
      .successHandler(authenticationSuccessHandler())
      .and()
      .exceptionHandling()
      .accessDeniedHandler(accessDeniedHandler())
      .and()
      .logout();
    }
}

It’s interesting to note that redirection URLs, such as "/login" , "/customError", and "/access-denied" don’t have to have any type of restriction to access them. So, we annotate them as permitAll().

On the other hand, we’ve to define the Beans that define the types of exceptions that we can handle:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
@Bean
public AuthenticationFailureHandler authenticationFailureHandler() {
    return new CustomAuthenticationFailureHandler();
} 

@Bean
public AuthenticationSuccessHandler authenticationSuccessHandler() {
   return new CustomAuthenticationSuccessHandler();
}

@Bean
public AccessDeniedHandler accessDeniedHandler() {
   return new CustomAccessDeniedHandler();
}

Since the AuthenticationSuccessHandler handles the happy path, we’ll define the two remaining beans for the exception cases. These two handlers are the ones we now have to adapt and implement to our needs . So, let’s proceed with the implementation of each of them.

4. Authentication Failure Handler

On the one hand, we’ve got the AuthenticationFailureHandler interface. That’s in charge of managing the exceptions produced when the user fails to log in . This interface provides us with the onAuthenticationFailure() method to customize the handler logic. It will be invoked by Spring Security upon a failed login attempt . With this in mind, let’s define our exception handler to redirect us to the error page when a failed login occurs:

1
2
3
4
5
6
7
8
public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler {

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) 
      throws IOException {
        response.sendRedirect("/customError");
    }
}

5. Access Denied Handler

On the other hand, when an unauthorized user tries to access the secure or protected page, Spring Security will throw an access denied exception . There’s a default 403 access denied page available with Spring Security which we can customize. This is managed by the AccessDeniedHandler interface. In addition, it provides the handle() method for custom the logic before redirecting the user to the 403 page :

1
2
3
4
5
6
7
public class CustomAccessDeniedHandler implements AccessDeniedHandler {

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException exc) throws IOException {
        response.sendRedirect("/access-denied");
    }
}

6. Conclusion

In this quick article, we’ve learned how to handle Spring Security exceptions and how to control them by creating and customizing our classes . In addition, we’ve created a fully functional example that helps us with understanding the concepts explained.

The complete source code of the article is available over on GitHub.

Reference https://www.baeldung.com/spring-security-exceptions

In this article of spring security tutorial, we will see how to create a Spring Security custom 403 access denied page. we will take a look at the steps for spring security custom 403 page.

In Spring security, when an unauthorized user will try to access the secure/ protected page, spring security will throw an access denied exception. There is a default 403 access denied page available with spring security, or if we are using spring boot, it will show the infamous whitelabel error page. Spring security flexible architecture provides the option to customize the 403 access denied page.

1. Application Setup

Before we create spring security custom 403 access denied page, let’s look at our pom.xml file containing the required dependencies.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>2.3.1.RELEASE</version>
      <relativePath />
      <!-- lookup parent from repository -->
   </parent>
   <groupId>com.javadevjournal</groupId>
   <artifactId>spring-security-series</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <name>Spring Security Tutorial Series</name>
   <description>Series to explain the core Spring security concepts.</description>
   <properties>
      <java.version>1.8</java.version>
   </properties>
   <dependencies>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-security</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-thymeleaf</artifactId>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-data-jpa</artifactId>
      </dependency>
      <dependency>
         <groupId>org.thymeleaf.extras</groupId>
         <artifactId>thymeleaf-extras-springsecurity5</artifactId>
         <version>3.0.4.RELEASE</version>
      </dependency>
      <dependency>
         <groupId>org.springframework.boot</groupId>
         <artifactId>spring-boot-starter-test</artifactId>
         <scope>test</scope>
         <exclusions>
            <exclusion>
               <groupId>org.junit.vintage</groupId>
               <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
         </exclusions>
      </dependency>
   </dependencies>
   <build>
      <plugins>
         <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
         </plugin>
      </plugins>
   </build>
</project>

Our pom.xml file contains only required dependencies, and you may need more based on your use case. Also, if you are not using spring boot, the above file is not relevant to you but will give you the idea for the required dependencies.

2. Custom Access Denied Page

To replace the Spring Security custom access denied page, we need to create a custom HTML page for our application. I am using Thymeleaf to build the HTML page, but you can use any other templating engine of your choice. Here is our custom access denied page.

Below HTML is just a sample HTML. You may need different HTML for your production app.

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <link href="https://fonts.googleapis.com/css?family=Raleway:500,800" rel="stylesheet" />
        <title>Access Denied</title>
    </head>
    <body>
        <use>
            <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve" class="whistle">
                <metadata></metadata>
                <g>
                    <g transform="translate(0.000000,511.000000) scale(0.100000,-0.100000)">
                        <path
                            d="M4295.8,3963.2c-113-57.4-122.5-107.2-116.8-622.3l5.7-461.4l63.2-55.5c72.8-65.1,178.1-74.7,250.8-24.9c86.2,61.3,97.6,128.3,97.6,584c0,474.8-11.5,526.5-124.5,580.1C4393.4,4001.5,4372.4,4001.5,4295.8,3963.2z"
                        />
                        <path
                            d="M3053.1,3134.2c-68.9-42.1-111-143.6-93.8-216.4c7.7-26.8,216.4-250.8,476.8-509.3c417.4-417.4,469.1-463.4,526.5-463.4c128.3,0,212.5,88.1,212.5,224c0,67-26.8,97.6-434.6,509.3c-241.2,241.2-459.5,449.9-488.2,465.3C3181.4,3180.1,3124,3178.2,3053.1,3134.2z"
                        />
                        <path
                            d="M2653,1529.7C1644,1445.4,765.1,850,345.8-32.7C62.4-628.2,22.2-1317.4,234.8-1960.8C451.1-2621.3,947-3186.2,1584.6-3500.2c1018.6-501.6,2228.7-296.8,3040.5,515.1c317.8,317.8,561,723.7,670.1,1120.1c101.5,369.5,158.9,455.7,360,553.3c114.9,57.4,170.4,65.1,1487.7,229.8c752.5,93.8,1392,181.9,1420.7,193.4C8628.7-857.9,9900,1250.1,9900,1328.6c0,84.3-67,172.3-147.4,195.3c-51.7,15.3-790.8,19.1-2558,15.3l-2487.2-5.7l-55.5-63.2l-55.5-61.3v-344.6V719.8h-411.7h-411.7v325.5c0,509.3,11.5,499.7-616.5,494C2921,1537.3,2695.1,1533.5,2653,1529.7z"
                        />
                    </g>
                </g>
            </svg>
        </use>
        <h1>403</h1>
        <h2>Not this time, access forbidden!</h2>
    </body>
</html>

3. Spring Security Configuration

We have the custom HTML in place. The next step is to configure the Spring Security custom 403 access denied page. To customize this page, Spring security provides the following options while configuring the HttpSecurity element.

  1. Configure access denied page using the accessDeniedPage().
  2. Use accessDeniedHandler() method.

The accessDeniedHandler() method provides more flexibility and control while customizing the access denied page in spring security, and we will use this option for this article.

3.1 Access Denied Handler

Spring security access denied handler provides us the flexibility and power to run the custom logic before redirecting user to the 403 page.To create a custom access denied handler with spring security, create a class by extending the <a aria-label="AccessDeniedHandler (opens in a new tab)" href="https://docs.spring.io/spring-security/site/docs/current/api/org/springframework/security/web/access/AccessDeniedHandler.html" target="_blank" rel="noreferrer noopener" class="rank-math-link">AccessDeniedHandler</a> interface.

package com.javadevjournal.core.security.handlers;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.access.AccessDeniedHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class CustomAccessDeniedHandler implements AccessDeniedHandler {

    private static final Logger LOG = LoggerFactory.getLogger(CustomAccessDeniedHandler.class);

    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {

        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null) {

            LOG.info("User '" + authentication.getName() +
                "' attempted to access the URL: " +
                request.getRequestURI());
        }
        response.sendRedirect(request.getContextPath() + "/access-denied");
    }
}

The custom handler is only logging the information and redirecting user to the “access-denied” controller. If you look closely, at this point we have access to the request, response, exception and the authentication object. We can build any custom logic based on this information.

3.2. Access Denied Controller.

Next is to create a custom controller to handle the redirect and send use to the access denied page. This is a simple Spring MVC controller, but we have the flexibility to perform any additional logic before showing the page to the customer.

package com.javadevjournal.web.controller.error;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class AccessDeniedController {

    @GetMapping("/access-denied")
    public String getAccessDenied() {
        return "/error/accessDenied";
    }
}

3.3. Configuring the Custom Access Denied Handler.

We have created the following components for our custom access denied page:

  1. Custom HTML page.
  2. Custom access denied handler.
  3. Spring MVC controller.

The last part of the setup is to let Spring security know about our custom handler. It will do this as part of configuring spring security through the HttpSecurity component. Here is a simplified version of our Spring security configuration (You can check complete configuration on our GitHub Repository)

@EnableWebSecurity
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
            .antMatchers("/login", "/register", "/home")
            .permitAll()
            .antMatchers("/account/**").hasAuthority("ADMIN")
            .and()
            .exceptionHandling().accessDeniedHandler(accessDeniedHandler())
            .and()
            ...
    }

    @Bean
    public AccessDeniedHandler accessDeniedHandler() {
        return new CustomAccessDeniedHandler();
    }
    
}

There are few important things in the above configuration.

  1. We are only allowing ADMIN authority to access the /account/**. This means any other user with different authority will get the 403 access denied exception.
  2. Since this is an exception handling, we are using the Spring security .excepTionHandling() method and telling that we like to handle the access denied use case by passing custom access denied handler to the accessDeniedHandler() method (.exceptionHandling().accessDeniedHandler(accessDeniedHandler()).
  3. Last part defines our custom handler as a spring managed bean.

4. Testing Application

Our setup is complete, let’s start our application and try to access the page. In the first screen shot (without custom access denied configuration), our application will show the default page.

Spring Security custom 403 access denied page

Once we active the configurations for spring security custom 403 access denied page. Let’s try to access the unauthorized section again by simply login to the system, this time, we will be greeted by our custom access denied page.

Spring Security custom 403 access denied page

Summary

In this article, we saw how to create a Spring Security custom 403 access denied page. We took a deep dive in to the different components to required to customize the access denied page for spring security application. As always, the source code for our Spring Security Course is available on the GitHub.

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and
privacy statement. We’ll occasionally send you account related emails.

Already on GitHub?
Sign in
to your account

Assignees

@jzheaux

Comments

@bleepbleepbleep

Summary

When I try to POST to a resource requiring authentication, I am redirected to a login page (as expected). Upon entering the username and password, I get a 403 access denied error. This works fine if I do a GET to the exact same resource. It’s only for a POST.

Actual Behavior

Receive 403 after successful authentication if authentication trigger is a POST to a protected resource.

Expected Behavior

Resource call should execute same as a GET.

Configuration

@OverRide
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers(«//action/«).access(«isFullyAuthenticated()»)
.and().formLogin()
.and().csrf().disable();

Version

Tried 5.0.4 and 4.2.4

Sample

@jzheaux

@bleepbleepbleep, the behavior you specify is already supported:

@SpringBootApplication
public class DemoApplication {

	@Controller
	public static class ActionController {
		@GetMapping("/action")
		@ResponseBody
		String getOk() {
			return "<form action='/action' method='post'><button type='submit'>Go</button></form>";
		}

		@PostMapping("/action")
		@ResponseBody
		String postOk() {
			return "ok";
		}
	}

	@EnableWebSecurity
	public static class SecurityConfig extends WebSecurityConfigurerAdapter {
		@Override
		protected void configure(HttpSecurity http) throws Exception {
			http.authorizeRequests()
				.antMatchers("/action/**")
					.access("isFullyAuthenticated()")
					.and()
				.formLogin()
					.and()
				.csrf().disable();
		}

		@Bean
		@Override
		public UserDetailsService userDetailsService() {
			UserDetails user = User.withDefaultPasswordEncoder()
								.username("user")
								.password("password")
								.roles("USER")
								.build()

			return new InMemoryUserDetailsManager(user);
		}
	}

	public static void main(String[] args) {
		SpringApplication.run(DemoApplication.class, args);
	}
}

In the above code, both GET /action and POST /action return a 200 OK once the user is authenticated.

Note the ant syntax for /action, which is where I think I could be misunderstanding your use case. Would you mind clarifying if you feel I’ve misunderstood? Otherwise, I’ll close this issue and recommend that you make a post to StackOverflow for further troubleshooting support.

@chandu-atina

@bleepbleepbleep From your statement GET works well and POST throws 403 error, I suspect that CSRF protect is enabled and the post request doesn’t include a valid csrf token.

But your sample code states that csrf is disabled, can you confirm the same from your application configuration to make sure that csrf is disabled?

@charlie39

this is something I am facing right now with spring security 5.1.5

@jzheaux

@charlie39 would you be able to provide a sample project that reproduces the issue you are experiencing?

@spring-projects-issues

If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.

@spring-projects-issues

Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.

@solutionaddicts

Has anyone fixed this error?
I’m facing this issue when I trigger a POST request with couple of fields.
{
«timestamp»: «2020-02-06T19:58:23.636+0000»,
«status»: 403,
«error»: «Forbidden»,
«message»: «Access Denied»,
«path»: «/csor/security/greet»
}

I have CSRF disabled in security config as below:
@OverRide
public void configure(HttpSecurity http) throws Exception {
http
.headers().frameOptions().disable()
.and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
// .antMatchers(«csor/security/authenticate/»).permitAll()
.antMatchers(«/v2/api-docs»,
«/swagger-resources/«,
«/swagger-ui.html»,
«/webjars/
«
).permitAll()
// .anyRequest().authenticated()
.and()
.csrf().disable();
//.and()
//.addFilter(new JwtAuthenticationFilter(authenticationManager()))
//.addFilter(new JwtAuthorizationFilter(authenticationManager()));
}

@VhiktorBrown

I’ve been experiencing this issue for the past 1 week now. I disabled csrf but I still get the same error. Any little help would be appreciated.

@danielptm

Im having the same issue.

@sarita-hirekhan

even i am facing this issue, how to resolve 403 error for POST api

По умолчанию в Spring Security определенExceptionTranslationFilter, который обрабатывает исключения типаAuthenticationException иAccessDeniedException. Последнее осуществляется с помощью свойстваaccessDeniedHandler,, которое использует классAccessDeniedHandlerImpl.

Чтобы настроить это поведение для использования нашей собственной страницы, которую мы создали выше, нам нужно переопределить свойства классаExceptionTranslationFilter. Это можно сделать с помощью конфигурации Java или конфигурации XML.

3.1. Доступ запрещен к странице

Используя Java,we can customize the 403 error handling process by using the accessDeniedPage() or accessDeniedHandler() methods при настройке элементаHttpSecurity.

Давайте создадим конфигурацию аутентификации, которая ограничивает URL-адреса“/admin/** рольюADMIN и устанавливает страницу отказа в доступе на нашу пользовательскую страницуaccessDenied.jsp:

@Override
protected void configure(final HttpSecurity http) throws Exception {
    http
      // ...
      .and()
      .exceptionHandling().accessDeniedPage("/accessDenied.jsp");
}

Давайте посмотрим на эквивалентную конфигурацию XML для страницы с отказом в доступе:

3.2. Обработчик отказа в доступе

Использование обработчика отказа в доступе вместо страницы имеет то преимущество, что мы можем определить пользовательскую логику, которая будет выполняться перед перенаправлением на страницу 403. Для этогоwe need to create a class that implements the AccessDeniedHandler interface и отменяет методhandle().

Давайте создадим собственный классAccessDeniedHandler, который будет регистрировать предупреждающее сообщение для каждой попытки отказа в доступе с указанием пользователя, который сделал попытку, и защищенного URL, к которому он пытался получить доступ:

public class CustomAccessDeniedHandler implements AccessDeniedHandler {

    public static final Logger LOG
      = Logger.getLogger(CustomAccessDeniedHandler.class);

    @Override
    public void handle(
      HttpServletRequest request,
      HttpServletResponse response,
      AccessDeniedException exc) throws IOException, ServletException {

        Authentication auth
          = SecurityContextHolder.getContext().getAuthentication();
        if (auth != null) {
            LOG.warn("User: " + auth.getName()
              + " attempted to access the protected URL: "
              + request.getRequestURI());
        }

        response.sendRedirect(request.getContextPath() + "/accessDenied");
    }
}

В конфигурации безопасностиwe’ll define the bean and set the custom AccessDeniedHandler:

@Bean
public AccessDeniedHandler accessDeniedHandler(){
    return new CustomAccessDeniedHandler();
}

//...
.exceptionHandling().accessDeniedHandler(accessDeniedHandler());

Если мы хотим настроить классCustomAccessDeniedHandler, определенный выше, с использованием XML, конфигурация будет выглядеть немного иначе:

Понравилась статья? Поделить с друзьями:
  • Spowha 412 ошибка e4
  • Spovl ошибка yaskawa a1000
  • Spotify прокси ошибка
  • Spotify ошибка при оплате
  • Spotify ошибка 408