#spring-security #jhipster #keycloak
#spring-безопасность #jhipster #keycloak
Вопрос:
Я запустил keycloak с помощью docker-compose -f src /main / docker /keycloak.yml up -d, а затем gradlew в моем проекте исключение произошло как
Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'securityConfiguration' defined in file [G:mymobileappbuildclassesjavamaincommycompanymyappconfigSecurityConfiguration.class]:
Unsatisfied dependency expressed through constructor parameter 3; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.zalando.problem.spring.web.advice.security.SecurityProblemSupport': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException:
Error creating bean with name 'org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration': Unsatisfied dependency expressed through method 'setConfigurers' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.OAuth2ClientConfiguration$OAuth2ClientWebMvcSecurityConfiguration': Unsatisfied dependency expressed through method 'setClientRegistrationRepository' parameter 0;
nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'clientRegistrationRepository' defined in class path resource [org/springframework/boot/autoconfigure/security/oauth2/client/servlet/OAuth2ClientRegistrationRepositoryConfiguration.class]: Bean instantiation via factory method failed;
nested exception is org.springframework.beans.BeanInstantiationException:
Failed to instantiate [org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository]:
Factory method 'clientRegistrationRepository' threw exception;
nested exception is java.lang.IllegalArgumentException:
Unable to resolve the OpenID Configuration with the provided Issuer
of "http://localhost:9080/auth/realms/jhipster
SecurityConfiguration.java:
package com.mycompany.myapp.config;
import com.mycompany.myapp.security.*;
import io.github.jhipster.config.JHipsterProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.http.HttpMethod;
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.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import com.mycompany.myapp.security.oauth2.AudienceValidator;
import com.mycompany.myapp.security.SecurityUtils;
import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator;
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
import org.springframework.security.oauth2.jwt.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority;
import java.util.*;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.security.web.csrf.CsrfFilter;
import com.mycompany.myapp.security.oauth2.JwtAuthorityExtractor;
import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter;
import org.springframework.web.filter.CorsFilter;
import org.zalando.problem.spring.web.advice.security.SecurityProblemSupport;
import org.springframework.context.annotation.ComponentScan;
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@ComponentScan({"com.mycompany.myapp.config.*"})
@Import(SecurityProblemSupport.class)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private final CorsFilter corsFilter;
@Value("${spring.security.oauth2.client.provider.oidc.issuer-uri}")
private String issuerUri;
private final JHipsterProperties jHipsterProperties;
private final JwtAuthorityExtractor jwtAuthorityExtractor;
private final SecurityProblemSupport problemSupport;
public SecurityConfiguration(CorsFilter corsFilter, JwtAuthorityExtractor jwtAuthorityExtractor, JHipsterProperties jHipsterProperties, SecurityProblemSupport problemSupport) {
this.corsFilter = corsFilter;
this.problemSupport = problemSupport;
this.jwtAuthorityExtractor = jwtAuthorityExtractor;
this.jHipsterProperties = jHipsterProperties;
}
@Override
public void configure(WebSecurity web) {
web.ignoring()
.antMatchers(HttpMethod.OPTIONS, "/**")
.antMatchers("/app/**/*.{js,html}")
.antMatchers("/i18n/**")
.antMatchers("/content/**")
.antMatchers("/h2-console/**")
.antMatchers("/swagger-ui/index.html")
.antMatchers("/test/**");
}
@Override
public void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
.and()
.addFilterBefore(corsFilter, CsrfFilter.class)
.exceptionHandling()
.accessDeniedHandler(problemSupport)
.and()
.headers()
.contentSecurityPolicy("default-src 'self'; frame-src 'self' data:; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://storage.googleapis.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:")
.and()
.referrerPolicy(ReferrerPolicyHeaderWriter.ReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN)
.and()
.featurePolicy("geolocation 'none'; midi 'none'; sync-xhr 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope 'none'; speaker 'none'; fullscreen 'self'; payment 'none'")
.and()
.frameOptions()
.deny()
.and()
.authorizeRequests()
.antMatchers("/api/auth-info").permitAll()
.antMatchers("/api/**").authenticated()
.antMatchers("/management/health").permitAll()
.antMatchers("/management/info").permitAll()
.antMatchers("/management/prometheus").permitAll()
.antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN)
.and()
.oauth2Login()
.and()
.oauth2ResourceServer()
.jwt()
.jwtAuthenticationConverter(jwtAuthorityExtractor)
.and()
.and()
.oauth2Client();
// @formatter:on
}
/**
* Map authorities from "groups" or "roles" claim in ID Token.
*
* @return a {@link GrantedAuthoritiesMapper} that maps groups from
* the IdP to Spring Security Authorities.
*/
@Bean
public GrantedAuthoritiesMapper userAuthoritiesMapper() {
return (authorities) -> {
Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
authorities.forEach(authority -> {
OidcUserAuthority oidcUserAuthority = (OidcUserAuthority) authority;
mappedAuthorities.addAll(SecurityUtils.extractAuthorityFromClaims(oidcUserAuthority.getUserInfo().getClaims()));
});
return mappedAuthorities;
};
}
@Bean
JwtDecoder jwtDecoder() {
NimbusJwtDecoderJwkSupport jwtDecoder = (NimbusJwtDecoderJwkSupport)
JwtDecoders.fromOidcIssuerLocation(issuerUri);
OAuth2TokenValidator<Jwt> audienceValidator = new AudienceValidator(jHipsterProperties.getSecurity().getOauth2().getAudience());
OAuth2TokenValidator<Jwt> withIssuer = JwtValidators.createDefaultWithIssuer(issuerUri);
OAuth2TokenValidator<Jwt> withAudience = new DelegatingOAuth2TokenValidator<>(withIssuer, audienceValidator);
jwtDecoder.setJwtValidator(withAudience);
return jwtDecoder;
}
}
Комментарии:
1. Я отформатировал ваш вопрос, потому что он был нечитаемым, пожалуйста, посмотрите, что я сделал, чтобы узнать, как это сделать. Я также исправил теги и установил более описательный заголовок. Надеюсь, вы получите дополнительную помощь с этим.
2. Что произойдет, если вы попытаетесь получить доступ к localhost:8080/auth/realms/jhipster/.well-known / … ?
3. большое вам спасибо за formatting.it не показывает, что сервер запущен с 8080. приложение успешно построено, вызывая указанное выше исключение.
4. Извините, URL-адрес должен быть на порту 9080, например: localhost:9080/auth/realms/jhipster/.well-known / … . Если эта конечная точка не возвращает json, ваша проблема на сервере keycloak, а не в вашем приложении.
Ответ №1:
Из вашего сообщения об исключении я предполагаю, что вы настроили в application.properties
spring.security.oauth2.client.provider.keycloak.issuer-uri=http://localhost: 9080/auth/realms/jhipster
Ошибка возникает — как указано в комментариях — когда OpenID-configuration не может быть загружена путем вызова [issuer-uri]/.well-known/OpenID-configuration.
Когда вы вызываете http://localhost:9080/realms/jhipster/.well-known/openid-configuration (без /auth/) вы должны получить json, и для этого приложение должно запускаться при соответствующей настройке uri эмитента:
spring.security.oauth2.client.provider.keycloak.issuer-uri=http://localhost: 9080/realms/jhipster
(без /auth/)
Ответ №2:
Публикация в качестве ответа может помочь кому-то другому.
В моем случае конфигурация не была создана должным образом, и проблема заключалась в keycloak
после исправления файла конфигурации служба работает должным образом.
Поэтому убедитесь, что keycloak возвращает правильный JSON, в моем случае это было null
http://localhost:9080/auth/realms/jhipster