There was an unexpected error type none status 999

After successful login spring redirects to /error page with the following content { "timestamp" : 1586002411175, "status" : 999, "error" : "None", "message" : "No message available" } I'm...

After successful login spring redirects to /error page with the following content

{
  "timestamp" : 1586002411175,
  "status" : 999,
  "error" : "None",
  "message" : "No message available"
}

I’m using spring-boot 2.2.4

My config:

spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp
spring.mvc.servlet.load-on-startup=1
spring.mvc.throw-exception-if-no-handler-found=true
spring.resources.add-mappings=false

@Configuration
public class DispatcherContextConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
    }
}

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AppSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(WebSecurity web) {
        web.ignoring().antMatchers("/favicon.ico", "/resources/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .authorizeRequests()
                .antMatchers("/api/**").permitAll()
                .antMatchers("/registration/**").anonymous()
                .anyRequest().authenticated()
                .and()
                    .headers()
                        .defaultsDisabled()
                        .cacheControl()
                    .and()
                .and()
                    .exceptionHandling()
                        .accessDeniedPage("/errors/403")
                .and()
                    .formLogin()
                    .loginPage("/login")
                    .loginProcessingUrl("/login")
                    .failureUrl("/login?error")
                    .defaultSuccessUrl("/log") // I don't want to use force redirect here
                    .permitAll()
                .and()
                    .logout()
                    .logoutUrl("/logout")
                    .deleteCookies("JSESSIONID")
                    .invalidateHttpSession(true)
                    .logoutSuccessUrl("/login?logout")
                    .permitAll()
                .and()
                    .rememberMe()
                    .rememberMeParameter("remember-me")
                    .key("myKey");

    }

    // ...
}

Note:

Turns out that error is caused by failed request to one of my static resources. Login page has <script src="/resources/my-js-file.js"></script> that is missing in the project.
I can fix this by removing missing resource import, but the problem can reappear in future so it’s not a fix.

How can I prevent this from happening?

I know I can force redirect to starting page with .defaultSuccessUrl("/log", true) but I don’t want this.
Also I want redirect to work properly despite of any not found resources.

to configure

server:
  port: 8000
  servlet:
    context-path: "/api"
  compression:
    enabled: false

Just contacted with SpringBoot, HelloWolrd has been implemented. The normal 404 was also handled successfully. But 127.0.0.1:8000/api/error has always been «Whitelabel Error Page». Tried a lot of methods, still can’t solve.
I need to add status 999 to ErrorPageConifg, but I don’t know how to add it. In theory, we can expand HttpStatus, but this is read-only.

This application has no explicit mapping for /error, so you are seeing this as a fallback.

Tue Jan 14 16:29:43 CST 2020
There was an unexpected error (type=None, status=999).
No message available

ErrorPageConifg.java

package cn.vlice.aox.AoxServer.config;

import org.springframework.boot.web.server.ConfigurableWebServerFactory;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;

@Configuration
public class ErrorPageConifg {
    @Bean
    public WebServerFactoryCustomizer<ConfigurableWebServerFactory> webServerFactoryCustomizer(){
        return new WebServerFactoryCustomizer<ConfigurableWebServerFactory>() {
            @Override
            public void customize(ConfigurableWebServerFactory factory) {
                ErrorPage page404 = new ErrorPage(HttpStatus.NOT_FOUND, "/error/404");
                ErrorPage page500 = new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500");
                factory.addErrorPages(page404, page500);
            }
        };
    }
}

ErrorPageController.java

package cn.vlice.aox.AoxServer.controller;

import cn.vlice.aox.AoxServer.data.Request;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/error")
public class ErrorPageController {
    @RequestMapping("/999")
    public Request toPage999() {
        HttpStatus status = HttpStatus.valueOf(404);
        return Request.error(status.getReasonPhrase(), status.value());
    }

    @RequestMapping("/404")
    public Request toPage404() {
        HttpStatus status = HttpStatus.valueOf(404);
        return Request.error(status.getReasonPhrase(), status.value());
    }

    @RequestMapping("/500")
    public Request toPage500() {
        HttpStatus status = HttpStatus.valueOf(500);
        return Request.error(status.getReasonPhrase(), status.value());
    }
}

Violet ice, a UP who is busy with work and has no time to record video

Postscript 1.3 months ago

Problem solved

public class ErrorPageController implements ErrorController {
...

    @Override
    public String getErrorPath() {
        return "/error/404";
    }
}

Finally note: the theory of light is not enough. By the way, I’d like to present you a set of 2020 latest JAVA architecture project practical course and interview question bank of Dachang, which can be found under the transformation of seven bar umbrella bar and Zero clothing umbrella (Digital homophony). There are many new JAVA architecture projects in it, as well as communication with old drivers
The text and pictures of this article come from the Internet and my own ideas. They are only for learning and communication. They have no commercial use. The copyright belongs to the original author. If you have any questions, please contact us in time for handling

#spring-boot #spring-security #spring-security-oauth2

Вопрос:

Я хочу использовать новое Spring Security Authorization Server для реализации OAuth2 для моего веб-сервиса.

В https://www.baeldung.com/spring-security-oauth-auth-server приведен пример, разделение

  • Авторизовать Сервер
  • Сервер ресурсов
  • Клиент

Код можно найти по адресу https://github.com/Baeldung/spring-security-oauth/tree/master/oauth-authorization-server

Эти три проекта Maven функционируют в данной версии, когда клиент в веб-браузере получает доступ http://localhost:8080/articles вывод выполнен правильно

 ["Article 1","Article 2","Article 3"]
 

Я попытался обновить Authorization Server проект до 0.1.1 , но, хотя он компилируется и запускается, когда клиент получает доступ http://localhost:8080/articles Я получаю

 Whitelabel Error Page

This application has no explicit mapping for /error, so you are seeing this as a fallback.
Sat Aug 07 15:57:26 CEST 2021
There was an unexpected error (type=None, status=999).
 

Я подумал, что это потому , что мне нужно обновить также другие версии во всех трех проектах, до Spring Boot 2.5.3 и также OpenJDK 16 , но та же ошибка.

Я обновил 0.1.2 и изменил уровень журнала на DEBUG , это отображается при запуске проекта сервера авторизации:

     ...
2021-08-09 17:54:45.876 DEBUG 16256 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration$EmbeddedTomcat'
    2021-08-09 17:54:46.015 DEBUG 16256 --- [           main] o.a.catalina.core.AprLifecycleListener   : The Apache Tomcat Native library could not be found using names [tcnative-1, libtcnative-1] on the java.library.path [/usr/java/packages/lib:/usr/lib64:/lib64:/lib:/usr/lib]. The errors reported were [Can't load library: /home/myself/PROJECTs/SPRING/spring-authorization-server/bin/libtcnative-1.so, Can't load library: /home/myself/PROJECTs/SPRING/spring-authorization-server/bin/liblibtcnative-1.so, no tcnative-1 in java.library.path: /usr/java/packages/lib:/usr/lib64:/lib64:/lib:/usr/lib, no libtcnative-1 in java.library.path: /usr/java/packages/lib:/usr/lib64:/lib64:/lib:/usr/lib]
    
    org.apache.tomcat.jni.LibraryNotFoundError: Can't load library: /home/myself/PROJECTs/SPRING/spring-authorization-server/bin/libtcnative-1.so, Can't load library: /home/myself/PROJECTs/SPRING/spring-authorization-server/bin/liblibtcnative-1.so, no tcnative-1 in java.library.path: /usr/java/packages/lib:/usr/lib64:/lib64:/lib:/usr/lib, no libtcnative-1 in java.library.path: /usr/java/packages/lib:/usr/lib64:/lib64:/lib:/usr/lib
        at org.apache.tomcat.jni.Library.<init>(Library.java:101) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
        at org.apache.tomcat.jni.Library.initialize(Library.java:211) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
        at org.apache.catalina.core.AprLifecycleListener.init(AprLifecycleListener.java:192) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
        at org.apache.catalina.core.AprLifecycleListener.isAprAvailable(AprLifecycleListener.java:101) ~[tomcat-embed-core-9.0.50.jar:9.0.50]
        at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getDefaultLifecycleListeners(TomcatServletWebServerFactory.java:173) ~[spring-boot-2.5.3.jar:2.5.3]
        at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.<init>(TomcatServletWebServerFactory.java:120) ~[spring-boot-2.5.3.jar:2.5.3]
        at org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration$EmbeddedTomcat.tomcatServletWebServerFactory(ServletWebServerFactoryConfiguration.java:76) ~[spring-boot-autoconfigure-2.5.3.jar:2.5.3]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78) ~[na:na]
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
        at java.base/java.lang.reflect.Method.invoke(Method.java:567) ~[na:na]
        at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154) ~[spring-beans-5.3.9.jar:5.3.9]
        at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653) ~[spring-beans-5.3.9.jar:5.3.9]
        at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:638) ~[spring-beans-5.3.9.jar:5.3.9]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1334) ~[spring-beans-5.3.9.jar:5.3.9]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177) ~[spring-beans-5.3.9.jar:5.3.9]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564) ~[spring-beans-5.3.9.jar:5.3.9]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[spring-beans-5.3.9.jar:5.3.9]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.9.jar:5.3.9]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.9.jar:5.3.9]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.9.jar:5.3.9]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:213) ~[spring-beans-5.3.9.jar:5.3.9]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.getWebServerFactory(ServletWebServerApplicationContext.java:217) ~[spring-boot-2.5.3.jar:2.5.3]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:180) ~[spring-boot-2.5.3.jar:2.5.3]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:160) ~[spring-boot-2.5.3.jar:2.5.3]
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:577) ~[spring-context-5.3.9.jar:5.3.9]
        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:145) ~[spring-boot-2.5.3.jar:2.5.3]
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) ~[spring-boot-2.5.3.jar:2.5.3]
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:434) ~[spring-boot-2.5.3.jar:2.5.3]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:338) ~[spring-boot-2.5.3.jar:2.5.3]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343) ~[spring-boot-2.5.3.jar:2.5.3]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1332) ~[spring-boot-2.5.3.jar:2.5.3]
        at com.baeldung.OAuth2AuthorizationServerApplication.main(OAuth2AuthorizationServerApplication.java:10) ~[classes/:na]
...
 

Похоже, то же самое происходит и с 0.1.1

Мой pom.xml

 <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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.baeldung</groupId>
    <artifactId>spring-authorization-server</artifactId>
    <version>0.1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.3</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security.experimental</groupId>
            <artifactId>spring-security-oauth2-authorization-server</artifactId>
            <version>0.1.2</version>
        </dependency>
    </dependencies>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>16</java.version>
    </properties>
</project>
 

Изменение только версии сервера авторизации в pom.xml, 0.1.0 или 0.1.1 или 0.1.2 предоставляют все одно и то же исключение.

Пример проекта из Baeldung запускается только (доставляет статьи с локального хоста:8080/статьи) с 0.1.0, но с 0.1.1 и 0.1.2 я получаю описанную страницу с белой ошибкой.

Комментарии:

1. 0.1.2 доступен, но та же ошибка.

Ответ №1:

Во-первых, я бы рекомендовал вам ознакомиться с образцами в самом проекте spring-authorization-server (см., например, Эту строку), что позволит вам быть в курсе быстрых изменений, происходящих в проекте, поскольку эти учебные пособия в Интернете будут быстро устаревать.

Во-вторых, я считаю, что 2-я ошибка в отладке не связана с этой проблемой, так что это похоже на проблему локальной установки, но я не уверен на 100%.

В-третьих, первая ошибка происходит в более новых версиях SAS из-за #243. Изменение включало включение рекомендаций OAuth 2.1, раздел 9.7.1, в котором говорится:

При перенаправлении URI с помощью localhost (т. е. «http://localhost:{порт}/{путь}») функция аналогично перенаправлениям IP-адресов с обратной связью, описанным в разделе 10.3.3, использование «локального хоста» НЕ РЕКОМЕНДУЕТСЯ. Указание URI перенаправления с помощью литерала IP-адреса обратной связи, а не «localhost», позволяет избежать непреднамеренного прослушивания сетевых интерфейсов, отличных от интерфейса обратной связи. Он также менее восприимчив к брандмауэрам на стороне клиента и неправильному разрешению имен хостов на устройстве пользователя.

Эта ошибка появляется только при перенаправлении обратно в клиентское приложение, когда URI перенаправления содержит множество localhost . Если вы включите ведение журнала трассировки на сервере авторизации (например logging.level.org.springframework.security=trace ), вы увидите успешную аутентификацию, за которой последует перенаправление на страницу с ошибкой, что-то вроде:

 ...
2021-08-10 11:10:41.596 DEBUG 90071 --- [io-9000-exec-10] w.a.UsernamePasswordAuthenticationFilter : Set SecurityContextHolder to UsernamePasswordAuthenticationToken [Principal=org.springframework.security.core.userdetails.User [Username=user, Password=[PROTECTED], Enabled=true, AccountNonExpired=true, credentialsNonExpired=true, AccountNonLocked=true, Granted Authorities=[ROLE_PILOT]], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=127.0.0.1, SessionId=3786957448CCBB82DAE6AB29DBCA5D2C], Granted Authorities=[ROLE_USER]]
2021-08-10 11:10:41.596 DEBUG 90071 --- [io-9000-exec-10] o.s.s.web.DefaultRedirectStrategy        : Redirecting to http://auth-server:9000/error?response_type=codeamp;client_id=messaging-clientamp;scope=openidamp;state=Vg-fUjLSdOjAG_4Y9LcjcxxYTGhd33Trbaclp92XoDQ=amp;redirect_uri=http://localhost:8080/login/oauth2/code/messaging-clientamp;nonce=s8hJD_zDopreLImNeRwQ3fslL4yFNySjbt6MiYK1mPw
...
 

Это говорит мне о том, что что-то произошло раньше в потоке, и мы только сейчас испытываем симптом. Если вы посмотрите выше в журналах, перед входом в систему, вы увидите что-то вроде этого:

 ...
2021-08-10 11:10:37.444 TRACE 90071 --- [nio-9000-exec-8] o.s.security.web.FilterChainProxy        : Invoking OAuth2AuthorizationEndpointFilter (6/24)
2021-08-10 11:10:37.444 TRACE 90071 --- [nio-9000-exec-8] o.s.s.authentication.ProviderManager     : Authenticating request with OAuth2AuthorizationCodeRequestAuthenticationProvider (1/10)
2021-08-10 11:10:37.445 TRACE 90071 --- [nio-9000-exec-8] o.s.s.w.header.writers.HstsHeaderWriter  : Not injecting HSTS header since it did not match request to [Is Secure]
2021-08-10 11:10:37.445 DEBUG 90071 --- [nio-9000-exec-8] w.c.HttpSessionSecurityContextRepository : Did not store empty SecurityContext
2021-08-10 11:10:37.445 DEBUG 90071 --- [nio-9000-exec-8] w.c.HttpSessionSecurityContextRepository : Did not store empty SecurityContext
2021-08-10 11:10:37.445 DEBUG 90071 --- [nio-9000-exec-8] s.s.w.c.SecurityContextPersistenceFilter : Cleared SecurityContextHolder to complete request
2021-08-10 11:10:37.447 TRACE 90071 --- [nio-9000-exec-8] o.s.security.web.FilterChainProxy        : Trying to match request against DefaultSecurityFilterChain [RequestMatcher=org.springframework.security.config.annotation.web.configurers.oauth2.server.authorization.OAuth2AuthorizationServerConfigurer$Lambda$603/0x000000080041a040@4dd90166, Filters=[org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@52227eb2, org.springframework.security.web.context.SecurityContextPersistenceFilter@21263314, org.springframework.security.web.header.HeaderWriterFilter@4d84049a, org.springframework.security.web.csrf.CsrfFilter@1d8b0500, org.springframework.security.web.authentication.logout.LogoutFilter@6413d7e7, org.springframework.security.oauth2.server.authorization.web.OAuth2AuthorizationEndpointFilter@32d5279, org.springframework.security.oauth2.server.authorization.oidc.web.OidcProviderConfigurationEndpointFilter@fe87ddd, org.springframework.security.oauth2.server.authorization.web.OAuth2AuthorizationServerMetadataEndpointFilter@448b808a, org.springframework.security.oauth2.server.authorization.web.NimbusJwkSetEndpointFilter@ebda593, org.springframework.security.oauth2.server.authorization.web.OAuth2ClientAuthenticationFilter@22d322f5, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@4337afd, org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@d16be4f, org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter@5ad1904f, org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationFilter@60e06f7d, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@4a92c6a9, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@64c781a9, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@a146b11, org.springframework.security.web.session.SessionManagementFilter@642857e0, org.springframework.security.web.access.ExceptionTranslationFilter@30c3ae63, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@550e9be6, org.springframework.security.oauth2.server.authorization.web.OAuth2TokenEndpointFilter@32ec9c90, org.springframework.security.oauth2.server.authorization.web.OAuth2TokenIntrospectionEndpointFilter@456bcb74, org.springframework.security.oauth2.server.authorization.web.OAuth2TokenRevocationEndpointFilter@3b332962, org.springframework.security.oauth2.server.authorization.oidc.web.OidcClientRegistrationEndpointFilter@58a2d9f9]] (1/2)
2021-08-10 11:10:37.447 TRACE 90071 --- [nio-9000-exec-8] o.s.security.web.FilterChainProxy        : Trying to match request against DefaultSecurityFilterChain [RequestMatcher=any request, Filters=[org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@1b01a0d, org.springframework.security.web.context.SecurityContextPersistenceFilter@91f565d, org.springframework.security.web.header.HeaderWriterFilter@67b355c8, org.springframework.security.web.csrf.CsrfFilter@79f90a3a, org.springframework.security.web.authentication.logout.LogoutFilter@414f87a9, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@6e31d989, org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@1ddc6db2, org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter@2ed71727, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@46e3559f, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@3b83459e, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@5261ec9, org.springframework.security.web.session.SessionManagementFilter@388623ad, org.springframework.security.web.access.ExceptionTranslationFilter@22bdb1d0, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@416d56f2]] (2/2)
2021-08-10 11:10:37.447 DEBUG 90071 --- [nio-9000-exec-8] o.s.security.web.FilterChainProxy        : Securing GET /error?response_type=codeamp;client_id=messaging-clientamp;scope=openidamp;state=Vg-fUjLSdOjAG_4Y9LcjcxxYTGhd33Trbaclp92XoDQ=amp;redirect_uri=http://localhost:8080/login/oauth2/code/messaging-clientamp;nonce=s8hJD_zDopreLImNeRwQ3fslL4yFNySjbt6MiYK1mPw
...
 

Таким образом, ошибка действительно происходит , OAuth2AuthorizationEndpointFilter и перенаправление ошибки сохраняется в качестве целевого URL-адреса после аутентификации , затем мы перенаправляемся на /login , а после аутентификации перенаправляемся обратно /error , что создает страницу с ошибкой с белой меткой.

Краткосрочное исправление состояло бы в том, чтобы убедиться , что вы используете 127.0.0.1 для своего клиентского приложения, вместо localhost того, чтобы, в том числе, изменять URI перенаправления на сервере авторизации (см. Пример). Но если вы забудете и запустите свой браузер по адресу http://localhost:8080 , вы все равно получите эту ошибку. Пока вы можете обойти это с помощью фильтра в своем клиентском приложении, подобного этому:

 /**
 * This filter ensures that the loopback IP <code>127.0.0.1</code> is used to access the
 * application so that the sample works correctly, due to the fact that redirect URIs with
 * "localhost" are rejected by the Spring Authorization Server, because the OAuth 2.1
 * draft specification states:
 *
 * <pre>
 *     While redirect URIs using localhost (i.e.,
 *     "http://localhost:{port}/{path}") function similarly to loopback IP
 *     redirects described in Section 10.3.3, the use of "localhost" is NOT
 *     RECOMMENDED.
 * </pre>
 *
 * @see <a href=
 * "https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-01#section-9.7.1">Loopback Redirect
 * Considerations in Native Apps</a>
 */
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class LoopbackIpRedirectFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        if (request.getServerName().equals("localhost")) {
            UriComponents uri = UriComponentsBuilder.fromHttpRequest(new ServletServerHttpRequest(request))
                    .host("127.0.0.1").build();
            response.sendRedirect(uri.toUriString());
            return;
        }
        filterChain.doFilter(request, response);
    }

}
 

Я бы посоветовал вам открыть проблему, чтобы запросить улучшение способа обработки этой ошибки. И если вам интересно, мы хотели бы обсудить это с вами и привлечь вас к участию в проекте, чтобы помочь решить эту проблему.

Комментарии:

1. Стив, спасибо за усилия. Я не понял всего, что вы сказали, но я заменил «localhost» на «127.0.0.1» везде в 3 проектах Baeldung, и это повело себя еще хуже. Я больше не получал страницу входа в систему.

2. Я надеюсь, что команда Белдунга проверит и обновит свои образцы. Тем временем я пробую официальные образцы.

3. Примите этот ответ, если вы почувствовали, что он вам помог

4. @Toerktumlare разве ты не читал мой комментарий? Это не помогло. И я не буду продолжать попытки с проектами Баельдунга, пока они сами не проверят, что не так.

5. Я не могу отдать должное ответу, который в моем случае не решил проблему. Как принять ответ, который я не мог одобрить? Я последовал его рекомендации попробовать официальные образцы.

Ответ №2:

Я тоже столкнулся с той же проблемой. после четырех-пяти дней борьбы я нашел решение. Во всех примерах uri эмитента является http://auth-server:9000

я только что добавил в файл etc/hosts следующую запись

127.0.0.1 аутентификационный сервер

это решило проблему

Комментарии:

1. Я хочу использовать IP-адрес, а не что-то вроде «auth-сервера», так что я не хочу изменять файл хоста. Я не могу следить за этим прямо сейчас, так как мне пришлось принять решение о рабочем промежуточном решении с Keycloak, но позже я могу вернуться к использованию сервера аутентификации Spring Security.

Views: 25,870

The Authorization Server in OAuth has the task of issuing an access token that allows the Client Application to use this access token to request the resource it needs to use. The Resource Server will validate this access token with the Authorization Server every time the Client Application requests to resource to decide whether to allow the Client Application access to this resource. You can use many other open sources such as Keycloak, Spring Security OAuth (deprecated), or a new Spring project called Spring Authorization Server to implement this Authorization Server. In this tutorial, I will show you how to use Spring Authorization Server to implement OAuth Authorization Server!

First, I will create a new Spring Boot project with Web Starter, and Security Starter:

and Spring Authorization Server:

<dependency>

    <groupId>org.springframework.security</groupId>

    <artifactId>spring-security-oauth2-authorization-server</artifactId>

    <version>0.3.0</version>

</dependency>

to make an example.

Result:

Implement OAuth Authorization Server using Spring Authorization Server

Authorization Server configuration

First, I will create a new AuthorizationServerConfiguration class to configure the Authorization Server.

By default, Spring Authorization Server supports the OAuth2AuthorizationServerConfiguration class with default configurations for an Authorization Server. If you take a look at the code of this class, you will see that it defines an applyDefaultSecurity() method that initializes the OAuth2AuthorizationServerConfigurer object, with the purpose of applying the default configurations that this OAuth2AuthorizationServerConfigurer class defines:

public static void applyDefaultSecurity(HttpSecurity http) throws Exception {

  OAuth2AuthorizationServerConfigurer<HttpSecurity> authorizationServerConfigurer =

      new OAuth2AuthorizationServerConfigurer<>();

  RequestMatcher endpointsMatcher = authorizationServerConfigurer.getEndpointsMatcher();

  http.requestMatcher(endpointsMatcher)

      .authorizeRequests(authorizeRequests > authorizeRequests.anyRequest().authenticated())

      .csrf(csrf > csrf.ignoringRequestMatchers(endpointsMatcher))

      .apply(authorizationServerConfigurer);

}

As you can see, the applyDefaultSecurity() method also defines security for the default endpoints of an Authorization Server.

Class OAuth2AuthorizationServerConfiguration also defines a bean for the SecurityFilterChain class that calls the applyDefaultSecurity() method to register these default configurations. with Spring Security of Authorization Server.

You can import this OAuth2AuthorizationServerConfiguration class using Spring’s @Import annotation to use these default configurations:

package com.huongdanjava.springauthorizationserver;

import org.springframework.context.annotation.Configuration;

import org.springframework.context.annotation.Import;

import org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;

@Configuration

@Import(OAuth2AuthorizationServerConfiguration.class)

public class AuthorizationServerConfiguration {

}

or if you want to add something custom code, then let declare a bean for the SecurityFilterChain class and call the applyDefaultSecurity() method as follows:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

package com.huongdanjava.springauthorizationserver;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.core.Ordered;

import org.springframework.core.annotation.Order;

import org.springframework.security.config.Customizer;

import org.springframework.security.config.annotation.web.builders.HttpSecurity;

import org.springframework.security.config.annotation.web.configuration.OAuth2AuthorizationServerConfiguration;

import org.springframework.security.web.SecurityFilterChain;

@Configuration

public class AuthorizationServerConfiguration {

  @Bean

  @Order(Ordered.HIGHEST_PRECEDENCE)

  public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity http)

      throws Exception {

    OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);

    return http.formLogin(Customizer.withDefaults()).build();

  }

}

Here, I add more code so that if the user does not have permission to request the default endpoints of an Authorization Server, the Authorization Server will redirect to the login page.

With an Authorization Server, an important thing that we need to do is define the JSON Web Key to verify the information in the access token that the user requested to the Resource Server, issued by the Authorization Server. A JwtDecoder bean with an object of the JWKSource class is required to complete the configuration of this Authorization Server. We can define beans for these objects as follows:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

@Bean

public JwtDecoder jwtDecoder(JWKSource<SecurityContext> jwkSource) {

  return OAuth2AuthorizationServerConfiguration.jwtDecoder(jwkSource);

}

@Bean

public JWKSource<SecurityContext> jwkSource() throws NoSuchAlgorithmException {

  RSAKey rsaKey = generateRsa();

  JWKSet jwkSet = new JWKSet(rsaKey);

  return (jwkSelector, securityContext) > jwkSelector.select(jwkSet);

}

private static RSAKey generateRsa() throws NoSuchAlgorithmException {

  KeyPair keyPair = generateRsaKey();

  RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();

  RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();

  return new RSAKey.Builder(publicKey)

      .privateKey(privateKey)

      .keyID(UUID.randomUUID().toString())

      .build();

}

private static KeyPair generateRsaKey() throws NoSuchAlgorithmException {

  KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(«RSA»);

  keyPairGenerator.initialize(2048);

  return keyPairGenerator.generateKeyPair();

}

You also need to declare additional issuer information. When building the access token, the Spring Authorization Server will use the issuer information configured in the ProviderSettings class to assign the information to the “iss” claim. We can configure the bean for the ProviderSettings class as follows:

@Bean

public ProviderSettings providerSettings() {

  // @formatter:off

  return ProviderSettings.builder()

      .issuer(«http://localhost:8080»)

      .build();

  // @formatter:on

}

Spring Security configuration

When the Authorization Server redirects to the login page because the user is not authenticated, we need to define another SecurityFilterChain to handle this request and all other requests of the Authorization Server. Because the OAuth2AuthorizationServerConfiguration class only defines security for the default endpoints of the Authorization Server.

We can define this SecurityFilterChain as follows:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

package com.huongdanjava.springauthorizationserver;

import org.springframework.context.annotation.Bean;

import org.springframework.security.config.Customizer;

import org.springframework.security.config.annotation.web.builders.HttpSecurity;

import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;

import org.springframework.security.web.SecurityFilterChain;

@EnableWebSecurity

public class SpringSecurityConfiguration {

  @Bean

  SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {

    // @formatter:off

    http

        .authorizeRequests(authorizeRequests >

            authorizeRequests.anyRequest().authenticated()

        )

        .formLogin(Customizer.withDefaults());

    // @formatter:on

    return http.build();

  }

}

At this point, the login page will display if the user is not logged in.

Register client with Authorization Server

Spring Authorization Server uses the RegisteredClient class to declare the information of a client registered with the Authorization Server and uses the implementation of the RegisteredClientRepository interface to store the information of all these clients.

We can declare client information using memory or a certain database:

Implement OAuth Authorization Server using Spring Authorization Server

For simplicity, I will use memory as follows:

@Bean

public RegisteredClientRepository registeredClientRepository() {

  // @formatter:off

  RegisteredClient registeredClient = RegisteredClient.withId(UUID.randomUUID().toString())

    .clientId(«huongdanjava»)

    .clientSecret(«{noop}123456»)

    .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_POST)

    .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)

    .redirectUri(«https://oidcdebugger.com/debug»)

    .scope(OidcScopes.OPENID)

    .build();

  // @formatter:on

  return new InMemoryRegisteredClientRepository(registeredClient);

}

There are several important properties that a client must have: client Id and authorization grant type enabled for this client Id.

Client Id, I don’t need to explain, right? For authorization grant type, Spring Authorization Server supports all grant types of OAuth 2.

Client secret depends on the client type we want to define, if our client is confidential, see also Client types in OAuth 2.0, Client secret is mandatory. Here, you need to declare how to encrypt the client secret with PasswordEncoder, if you don’t want to encrypt it for testing purposes, we can use NoOpPasswordEncoder by declaring “{noop}” at the beginning of the client secret as I did above. Remember this is for testing purposes only!

The Client Authentication method is also required if our client is confidential, declaring to define how we can get the access token.

Depending on the grant type of the client you are defining, some other required information that we need to declare. For example, in my case, I am defining a client with grant type authorization_code, so I have to define a redirect_uri. Here, I will use the tool https://oidcdebugger.com/ to get the authorization code, so I define the redirect_uri with the value https://oidcdebugger.com/debug as you can see.

Depending on your needs, let’s define client information accordingly.

Register user with Authorization Server

User information logged into the Authorization Server, I use memory with the following declaration:

@Bean

public UserDetailsService users() {

  UserDetails user = User.withDefaultPasswordEncoder()

      .username(«admin»)

      .password(«password»)

      .roles(«ADMIN»)

      .build();

  return new InMemoryUserDetailsManager(user);

}

OK, at this point, we have completed the basic configuration for the Authorization Server.

To check the results, I will use the tool https://oidcdebugger.com/ as I mentioned above, with the following declaration:

Implement OAuth Authorization Server using Spring Authorization Server

Click Send Request on this page, you will see the Authorization Server login page displayed as follows:

Implement OAuth Authorization Server using Spring Authorization Server

Log in with the information we have declared above, you will see the following results:

Implement OAuth Authorization Server using Spring Authorization Server

Using this authorization code along with the client secret that we have declared, you can get the access token for this client as follows:

Implement OAuth Authorization Server using Spring Authorization Server

Понравилась статья? Поделить с друзьями:
  • There was an unexpected error type forbidden status 403 forbidden
  • There was an unexpected error type bad request status 400
  • There was an unexpected error running sql scripts setup will now terminate
  • There was an unexpected error removing this product from your account
  • There was an error processing your order перевод