Spring Security - JWT и Basic Auth для разных моделейJAVA

Программисты JAVA общаются здесь
Anonymous
Spring Security - JWT и Basic Auth для разных моделей

Сообщение Anonymous »

Я борюсь за добавление базовой аудитории рядом с JWT, обеспечивающим отдельные конечные точки. Я пробовал несколько способов, а также из предыдущих сообщений настраивают несколько типов аутентификации с Spring Security для базовой Auth & jwt. Это мой SecurityConfiguration < /p>

Код: Выделить всё

@SuppressWarnings(value = "unused")
@Profile(value = "!test")
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor(onConstructor_ = @__(@Autowired))
public class SecurityConfiguration {

// Final Constructors
private final BasicAuthEntryPoint basicAuthEntryPoint;
private final JwtAuthEntryPoint jwtAuthEntryPoint;
private final JwtFilter jwtFilter;

// Retrieving username & password from environment variables
@Value("${EMP_CONFIG_USERNAME}")
private String envUsername;

@Value("${EMP_CONFIG_PASSWORD}")
private String envPassword;

@Value("${EMP_ENCRYPT_KEY}")
private String envEncryptKey;

// PasswordEncoder
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}

// RequestInterceptor (Authentication with external Microservices - OpenFeign)
@Bean
public RequestInterceptor basicAuthRequestInterceptor() {
return requestTemplate -> {
String authHeader = "Basic " + Base64.getEncoder()
.encodeToString((envUsername + ":" + envEncryptKey).getBytes());
requestTemplate.header("Authorization", authHeader);
};
}

// Setting SecurityFilterChain - Basic Auth
@Bean
@Order(1)
public SecurityFilterChain securityFilterChainBasicAuth(HttpSecurity http) throws Exception {
return http
.securityMatcher("/actuator/**")
.authorizeHttpRequests(req -> req
.anyRequest().hasRole("ADMIN"))
.httpBasic(withDefaults())
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.exceptionHandling(ex -> ex.authenticationEntryPoint(basicAuthEntryPoint))
.csrf(AbstractHttpConfigurer::disable)
.build();
}

// Setting SecurityFilterChain - JWT Auth
@Bean
@Order(2)
public SecurityFilterChain securityFilterChainJwt(HttpSecurity http) throws Exception {
return http
.csrf(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(request -> request
.requestMatchers(HttpMethod.POST, "/v1/auth/**").permitAll()
.anyRequest().authenticated())
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
//.exceptionHandling(ex -> ex.authenticationEntryPoint(jwtAuthEntryPoint))
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)
.build();
}

// AuthenticationManager (JWT)
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration configuration) throws Exception {
return configuration.getAuthenticationManager();
}

// InMemory User - Admins Only (Basic Auth)
@Bean
public UserDetailsService adminUser() {

// Admin
return new InMemoryUserDetailsManager(
User.withUsername(envUsername)
.password(envPassword)
.roles("ADMIN")
.build()
);
}
}
Здесь my jwtfilter.java:

Код: Выделить всё

@Component
@RequiredArgsConstructor(onConstructor_ = @__(@Autowired))
public class JwtFilter extends OncePerRequestFilter {

// Final Constructors
private final JwtUtils jwtUtils;
private final AuthServiceProxy authServiceProxy;
private final Logger logger = LoggerFactory.getLogger(JwtFilter.class);

@Override
protected void doFilterInternal(
@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response,
@NonNull FilterChain filterChain
) throws ServletException, IOException {

// Extracting 'Authorization' from request Headers
String authHeader = getAuthHeader(request);
String requestPath = request.getRequestURI();

// 1.  Skipping JWT if Authorization Header is 'Basic'
if (authHeader != null && authHeader.startsWith("Basic ")) {
logger.debug("Skipping JWT filter for Basic Auth request [{}]", requestPath);
filterChain.doFilter(request, response);
return;
}

// 2. Validating
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
logger.debug("No Bearer token found in request [{}], skipping JWT filter", requestPath);
filterChain.doFilter(request, response);
return;
}

String token = authHeader.substring(7);
String username = jwtUtils.getUsername(token);
logger.debug("JWT token parsed.  Username extracted: [{}]", username);

if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
CredentialDTO credentialDTOByUsername = authServiceProxy.getCredentialByUsername(
username,
"GET",
"/v1/creds/ids?user=" + username
);

if (jwtUtils.isTokenValid(token, credentialDTOByUsername)) {
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
credentialDTOByUsername,
null,
credentialDTOByUsername.getAuthorities()
);
authToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authToken);
logger.info("JWT authentication successful for user [{}] on [{}]", username, requestPath);
}
}
filterChain.doFilter(request, response);
}

// Extracting 'Authorization' from request Headers
private String getAuthHeader(HttpServletRequest request) {
return request.getHeader(HttpHeaders.AUTHORIZATION);
}
}
jwtauthentrypoint:

Код: Выделить всё

@Component
@RequiredArgsConstructor(onConstructor_ = @__(@Autowired))
public class JwtAuthEntryPoint implements AuthenticationEntryPoint {

// Final Constructor
private final HandlerExceptionResolver handlerExceptionResolver;
private final Logger logger = LoggerFactory.getLogger(JwtAuthEntryPoint.class);

@Override
public void commence(
@NonNull HttpServletRequest request,
@NonNull HttpServletResponse response,
@NonNull AuthenticationException authException
) {
logger.error("Error occurred during JWT Auth: {}", authException.getMessage());
handlerExceptionResolver.resolveException(
request,
response,
null,
new UnauthorizedAccessAttempt(authException.getMessage())
);
}
}
Последнее, но не менее важное, my credentialAuthenticationprovider.java:

Код: Выделить всё

@Component
@RequiredArgsConstructor(onConstructor_ = @__(@Autowired))
public class CredentialAuthenticationProvider implements AuthenticationProvider {

// Final Constructors
private final AuthServiceProxy authServiceProxy;
private final PasswordEncoder passwordEncoder;
private final Logger logger = LoggerFactory.getLogger(CredentialAuthenticationProvider.class);

@Value("${EMP_CONFIG_USERNAME}")
private String adminUsername;

@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {

// Username & Password (Plaintext)
String username = authentication.getName();

// Skip in-memory admin
if (username.equals(adminUsername)) {
logger.debug("Skipping CredentialAuthenticationProvider for in-memory user [{}]", username);
return null;
}

String password = authentication.getCredentials().toString();

CredentialDTO credentialDTOByUsername = authServiceProxy.getCredentialByUsername(
username,
"GET",
"/v1/cred/ids?user=" + username
);
if(credentialDTOByUsername == null || !passwordEncoder.matches(password, credentialDTOByUsername.password())){
logger.error("Username or Password aren't valid - Please check again for JWT generation");
throw new InvalidCredentialException(username);
}
logger.info("Username & Password valid!");
return new UsernamePasswordAuthenticationToken(credentialDTOByUsername, null, credentialDTOByUsername.getAuthorities());
}

@Override
public boolean supports(Class authentication) {
return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
}
}
Заранее спасибо за любую помощь.


Подробнее здесь: https://stackoverflow.com/questions/795 ... t-patterns

Вернуться в «JAVA»