Я настраиваю конфигурацию Spring Security с помощью JWT, и мне нужно создать собственный поставщик аутентификации и специальную службу сведений о пользователе, но в классе конфигурации безопасности между ними создается циклическая зависимость...
SecurityConfig.class
package io.github.felipeemerson.openmuapi.configuration;
import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.source.ImmutableJWKSet;
import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.proc.SecurityContext;
import io.github.felipeemerson.openmuapi.entities.CustomUserDetails;
import io.github.felipeemerson.openmuapi.services.AccountDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
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.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.JwtEncoder;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusJwtEncoder;
import org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationEntryPoint;
import org.springframework.security.oauth2.server.resource.web.access.BearerTokenAccessDeniedHandler;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Value("${jwt.public.key}")
private RSAPublicKey key;
@Value("${jwt.private.key}")
private RSAPrivateKey priv;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private AuthEntryPointJwt unauthorizedHandler;
@Autowired
private CustomAuthenticationProvider customAuthenticationProvider;
@Bean
public AuthTokenFilter authenticationJwTokenFilter() {
return new AuthTokenFilter();
}
@Bean
public AuthenticationManager authenticationManager() throws Exception {
return customAuthenticationProvider::authenticate;
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(AbstractHttpConfigurer::disable)
.httpBasic(Customizer.withDefaults())
.oauth2ResourceServer((oauth2) -> oauth2
.jwt(Customizer.withDefaults())
)
.exceptionHandling(exception -> exception.authenticationEntryPoint(unauthorizedHandler))
.sessionManagement((session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.exceptionHandling((exceptions) -> exceptions
.authenticationEntryPoint(new BearerTokenAuthenticationEntryPoint())
.accessDeniedHandler(new BearerTokenAccessDeniedHandler())
)
.authorizeHttpRequests(auth ->auth
.requestMatchers("/login").permitAll()
.anyRequest().authenticated()
)
.authenticationProvider(customAuthenticationProvider)
.addFilterBefore(authenticationJwTokenFilter(), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
@Bean
public JwtDecoder jwtDecoder() {
return NimbusJwtDecoder.withPublicKey(this.key).build();
}
@Bean
public JwtEncoder jwtEncoder() {
JWK jwk = new RSAKey.Builder(this.key).privateKey(this.priv).build();
JWKSource jwks = new ImmutableJWKSet(new JWKSet(jwk));
return new NimbusJwtEncoder(jwks);
}
}
UserDetailsService.class
package io.github.felipeemerson.openmuapi.services;
import io.github.felipeemerson.openmuapi.entities.Account;
import io.github.felipeemerson.openmuapi.entities.CustomUserDetails;
import io.github.felipeemerson.openmuapi.exceptions.BadRequestException;
import io.github.felipeemerson.openmuapi.repositories.AccountRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.Optional;
import java.util.Set;
@Service
public class AccountDetailsService implements UserDetailsService {
@Autowired
private AccountRepository accountRepository;
@Override
public UserDetails loadUserByUsername(String username) {
return loadUser(username);
}
private UserDetails loadUser(String username) throws BadRequestException {
Optional userAccountOpt = accountRepository.findByLoginName(username);
if (userAccountOpt.isEmpty()){
return null;
}
Account account = userAccountOpt.get();
return new CustomUserDetails(account.getLoginName(), account.getPasswordHash(), true, Set.of(new SimpleGrantedAuthority("ROLE_USER")));
}
}
CustomAuthenticationProvider.class
package io.github.felipeemerson.openmuapi.configuration;
import io.github.felipeemerson.openmuapi.exceptions.BadRequestException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Autowired
private final UserDetailsService userDetailsService;
private final PasswordEncoder passwordEncoder;
public CustomAuthenticationProvider(UserDetailsService userDetailsService,
PasswordEncoder passwordEncoder) {
this.userDetailsService = userDetailsService;
this.passwordEncoder = passwordEncoder;
}
@Override
public Authentication authenticate(Authentication authentication) throws BadRequestException {
String username = authentication.getName();
String password = authentication.getCredentials().toString();
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
System.out.println(password);
System.out.println(userDetails.getPassword());
if (userDetails == null || !passwordEncoder.matches(password, userDetails.getPassword())) {
throw new BadRequestException("Login or password incorrect.");
}
Authentication authenticated = new UsernamePasswordAuthenticationToken(
userDetails, password, userDetails.getAuthorities());
return authenticated;
}
@Override
public boolean supports(Class authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
Я пытался использовать @Lazy в зависимости UserDetailsService в CustomAuthenticationProvider, но это не удалось. Также пытался использовать @Lazy в зависимостях SecurityConfig...
редактировать:
Извините, я забыл журналы:
Description:
The dependencies of some of the beans in the application context form a cycle:
┌─────┐
| securityConfig (field private io.github.felipeemerson.openmuapi.configuration.CustomAuthenticationProvider io.github.felipeemerson.openmuapi.configuration.SecurityConfig.customAuthenticationProvider)
↑ ↓
| customAuthenticationProvider defined in file [C:\Users\felip\OneDrive\Documentos\Cursos\openmu-api\target\classes\io\github\felipeemerson\openmuapi\configuration\CustomAuthenticationProvider.class]
└─────┘
Подробнее здесь: https://stackoverflow.com/questions/784 ... -in-spring
Как исправить эту циклическую зависимость весной? ⇐ JAVA
Программисты JAVA общаются здесь
-
Anonymous
1715321854
Anonymous
Я настраиваю конфигурацию Spring Security с помощью JWT, и мне нужно создать собственный поставщик аутентификации и специальную службу сведений о пользователе, но в классе конфигурации безопасности между ними создается циклическая зависимость...
SecurityConfig.class
package io.github.felipeemerson.openmuapi.configuration;
import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.RSAKey;
import com.nimbusds.jose.jwk.source.ImmutableJWKSet;
import com.nimbusds.jose.jwk.source.JWKSource;
import com.nimbusds.jose.proc.SecurityContext;
import io.github.felipeemerson.openmuapi.entities.CustomUserDetails;
import io.github.felipeemerson.openmuapi.services.AccountDetailsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
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.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.JwtEncoder;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
import org.springframework.security.oauth2.jwt.NimbusJwtEncoder;
import org.springframework.security.oauth2.server.resource.web.BearerTokenAuthenticationEntryPoint;
import org.springframework.security.oauth2.server.resource.web.access.BearerTokenAccessDeniedHandler;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Value("${jwt.public.key}")
private RSAPublicKey key;
@Value("${jwt.private.key}")
private RSAPrivateKey priv;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private AuthEntryPointJwt unauthorizedHandler;
@Autowired
private CustomAuthenticationProvider customAuthenticationProvider;
@Bean
public AuthTokenFilter authenticationJwTokenFilter() {
return new AuthTokenFilter();
}
@Bean
public AuthenticationManager authenticationManager() throws Exception {
return customAuthenticationProvider::authenticate;
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf(AbstractHttpConfigurer::disable)
.httpBasic(Customizer.withDefaults())
.oauth2ResourceServer((oauth2) -> oauth2
.jwt(Customizer.withDefaults())
)
.exceptionHandling(exception -> exception.authenticationEntryPoint(unauthorizedHandler))
.sessionManagement((session) -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.exceptionHandling((exceptions) -> exceptions
.authenticationEntryPoint(new BearerTokenAuthenticationEntryPoint())
.accessDeniedHandler(new BearerTokenAccessDeniedHandler())
)
.authorizeHttpRequests(auth ->auth
.requestMatchers("/login").permitAll()
.anyRequest().authenticated()
)
.authenticationProvider(customAuthenticationProvider)
.addFilterBefore(authenticationJwTokenFilter(), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
@Bean
public JwtDecoder jwtDecoder() {
return NimbusJwtDecoder.withPublicKey(this.key).build();
}
@Bean
public JwtEncoder jwtEncoder() {
JWK jwk = new RSAKey.Builder(this.key).privateKey(this.priv).build();
JWKSource jwks = new ImmutableJWKSet(new JWKSet(jwk));
return new NimbusJwtEncoder(jwks);
}
}
UserDetailsService.class
package io.github.felipeemerson.openmuapi.services;
import io.github.felipeemerson.openmuapi.entities.Account;
import io.github.felipeemerson.openmuapi.entities.CustomUserDetails;
import io.github.felipeemerson.openmuapi.exceptions.BadRequestException;
import io.github.felipeemerson.openmuapi.repositories.AccountRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import java.util.Optional;
import java.util.Set;
@Service
public class AccountDetailsService implements UserDetailsService {
@Autowired
private AccountRepository accountRepository;
@Override
public UserDetails loadUserByUsername(String username) {
return loadUser(username);
}
private UserDetails loadUser(String username) throws BadRequestException {
Optional userAccountOpt = accountRepository.findByLoginName(username);
if (userAccountOpt.isEmpty()){
return null;
}
Account account = userAccountOpt.get();
return new CustomUserDetails(account.getLoginName(), account.getPasswordHash(), true, Set.of(new SimpleGrantedAuthority("ROLE_USER")));
}
}
CustomAuthenticationProvider.class
package io.github.felipeemerson.openmuapi.configuration;
import io.github.felipeemerson.openmuapi.exceptions.BadRequestException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
@Autowired
private final UserDetailsService userDetailsService;
private final PasswordEncoder passwordEncoder;
public CustomAuthenticationProvider(UserDetailsService userDetailsService,
PasswordEncoder passwordEncoder) {
this.userDetailsService = userDetailsService;
this.passwordEncoder = passwordEncoder;
}
@Override
public Authentication authenticate(Authentication authentication) throws BadRequestException {
String username = authentication.getName();
String password = authentication.getCredentials().toString();
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
System.out.println(password);
System.out.println(userDetails.getPassword());
if (userDetails == null || !passwordEncoder.matches(password, userDetails.getPassword())) {
throw new BadRequestException("Login or password incorrect.");
}
Authentication authenticated = new UsernamePasswordAuthenticationToken(
userDetails, password, userDetails.getAuthorities());
return authenticated;
}
@Override
public boolean supports(Class authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
Я пытался использовать @Lazy в зависимости UserDetailsService в CustomAuthenticationProvider, но это не удалось. Также пытался использовать @Lazy в зависимостях SecurityConfig...
редактировать:
Извините, я забыл журналы:
Description:
The dependencies of some of the beans in the application context form a cycle:
┌─────┐
| securityConfig (field private io.github.felipeemerson.openmuapi.configuration.CustomAuthenticationProvider io.github.felipeemerson.openmuapi.configuration.SecurityConfig.customAuthenticationProvider)
↑ ↓
| customAuthenticationProvider defined in file [C:\Users\felip\OneDrive\Documentos\Cursos\openmu-api\target\classes\io\github\felipeemerson\openmuapi\configuration\CustomAuthenticationProvider.class]
└─────┘
Подробнее здесь: [url]https://stackoverflow.com/questions/78456631/how-to-fix-this-cylic-dependency-in-spring[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия