#java #spring #spring-boot #spring-security #java-15
#java #spring #spring-boot #spring-безопасность #java-15
Вопрос:
В настоящее время выполняется обновление с версии Spring Boot v2.3.5 до версии v2.4.0. Однако я сталкиваюсь с проблемой, связанной с установкой SecurityContextHolder, когда пользователь аутентифицируется и фактически проходит через цепочку фильтров.
Проблемный код является частью класса, который расширяет BasicAuthenticationFilter и выглядит следующим образом:
/**
* Perform the filter for authentication
*
* @param request The HttpServletRequest
* @param response The HttpServletResponse
* @param chain The FilterChain
* @throws IOException When the filter could not be performed
* @throws ServletException When the filter could not be performed
*/
@Override
protected void doFilterInternal(final HttpServletRequest request,
final HttpServletResponse response,
final FilterChain chain) throws IOException, ServletException {
final String header = request.getHeader(jwtConfiguration.getHeader());
if (header == null || !header.startsWith(jwtConfiguration.getTokenPrefix())) {
chain.doFilter(request, response);
return;
}
final UsernamePasswordAuthenticationToken authentication = getAuthentication(request);
if (authentication == null) {
response.setStatus(HttpStatus.UNAUTHORIZED.value());
} else {
final SecurityContext context = SecurityContextHolder.createEmptyContext();
context.setAuthentication(authentication);
SecurityContextHolder.setContext(context);
chain.doFilter(request, response); // The exception is thrown here, but only when setting the SecurityContextHolder
}
}
...
/**
* Get the UsernamePasswordAuthenticationToken from the HttpServletRequest
*
* @param request The HttpServletRequest
* @return The UsernamePasswordAuthenticationToken that was filtered from the HttpServletRequest
*/
private UsernamePasswordAuthenticationToken getAuthentication(final HttpServletRequest request) {
final String token = request.getHeader(jwtConfiguration.getHeader());
if (token != null amp;amp; !token.isEmpty()) {
final UserDto user = authorizationService.getCurrentUser(token);
if (user != null) {
final Set<GrantedAuthority> grantedAuthorities = new HashSet<>();
if (user.getRoles() != null) {
for (final RoleDto role : user.getRoles()) {
if (role.getPermissions() != null) {
for (final PermissionDto permission : role.getPermissions()) {
grantedAuthorities.add(new SimpleGrantedAuthority(permission.getName()));
}
}
}
}
return new UsernamePasswordAuthenticationToken(user, null, grantedAuthorities);
}
return null;
}
return null;
}
Без установки SecurityContextHolder код работает просто отлично, но, к сожалению, аутентификация не будет установлена, что не является результатом, который мне нужен, поскольку я хотел бы защитить определенные конечные точки.
Класс, который расширяет WebSecurityConfigurerAdapter, настроен следующим образом:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, jsr250Enabled = true, prePostEnabled = true)
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
private final JwtConfiguration jwtConfiguration;
private final IAuthorizationService userService;
/**
* Initialize a new WebSecurityConfiguration
*
* @param jwtConfiguration The JwtConfiguration object
* @param userService The IAuthorizationService implementation
*/
public WebSecurityConfiguration(@Autowired final JwtConfiguration jwtConfiguration,
@Autowired final IAuthorizationService userService) {
if (jwtConfiguration == null)
throw new NullPointerException("JwtConfig cannot be null!");
if (userService == null)
throw new NullPointerException("IAuthorizationService cannot be null!");
this.jwtConfiguration = jwtConfiguration;
this.userService = userService;
}
/**
* Configure the HttpSecurity
*
* @param http The HttpSecurity object
* @throws Exception When the configuration failed
*/
@Override
protected void configure(final HttpSecurity http) throws Exception {
final AuthenticationManager authenticationManager = authenticationManager();
http
.csrf().disable().cors().and()
.authorizeRequests()
.antMatchers("/authentication/**",
"/v2/api-docs",
"/configuration/ui",
"/swagger-resources/**",
"/configuration/security",
"/swagger-ui.html",
"/webjars/**")
.permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(new JwtAuthorizationFilter(authenticationManager, jwtConfiguration, userService), JwtAuthorizationFilter.class)
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
Само исключение, возникающее при установке SecurityContextHolder, при передаче по цепочке выглядит следующим образом:
java.lang.Исключение IllegalStateException: для интерфейса org.springframework.security.core не найден основной или единственный общедоступный конструктор.Аутентификация — и конструктор по умолчанию также не найден
Комментарии:
1. Можете ли вы показать нам, что внутри
getAuthentication(...)
?2. @Aman Да, но только частично.
3. Та часть, где вы создаете экземпляр
Authentication
объекта?4. Конечно, добавил это к вопросу @Aman
5. Вы когда-нибудь решали эту проблему? Я испытываю точно такую же трассировку стека.