Одна предназначена для вызовов /api с OAuth2, а другая — для вызовов /net со специальным значение заголовка с именем X-Authorization. В этом значении находится секретный ключ, который используется для авторизации.
Вот интересные части кода.
Код: Выделить всё
@Configuration
@EnableWebSecurity
public class SecurityConfiguration {
private final XAuthorizationFilter xAuthorizationFilter;
public SecurityConfiguration(XAuthorizationFilter xAuthorizationFilter) {
this.xAuthorizationFilter= xAuthorizationFilter;
}
@Bean
@Order(1)
public SecurityFilterChain xAuthorizationSecurityFilterChain(HttpSecurity http) throws Exception {
http
.securityMatcher(
"/net/**"
)
.addFilterAt(this.xAuthorizationFilter, AuthorizationFilter.class)
.authorizeHttpRequests(auth -> auth //
.requestMatchers("/net/url1").hasRole(NET)
.requestMatchers("/net/url2").hasRole(NET)
);
return http.build();
}
@Bean
@Order(2)
public SecurityFilterChain oAuth2SecurityFilterChain(HttpSecurity http) throws Exception {
http
.securityMatcher(
"/api/**",
"/health"
)
.authorizeHttpRequests(auth -> auth //
.requestMatchers("/api/admin/**").hasRole(ADMIN)
.requestMatchers("/api/**").hasRole(EMPLOYEE)
.requestMatchers("/health").permitAll() //
.anyRequest().denyAll() //
)
.oauth2ResourceServer(oauth2 -> oauth2 //
.jwt(jwt -> jwt //
.jwtAuthenticationConverter(new KeycloakJwtConverter()) //
) //
) //
.logout(logout -> logout //
.logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler()) //
);
return http.build();
}
}
Код: Выделить всё
@Component
public class XAuthorizationFilter implements Filter {
@Value("${net.authorization}")
private String netAuthorization;
@Value("${net.endpoints}")
private String[] netEndpoints;
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
if (this.isNetEndpoint(request)) {
String header = request.getHeader("X-Authorization");
if (header == null) {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.getWriter().write("Missing X-Authorization header.");
return;
}
if (!this.netAuthorization.equals(header)) {
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
response.getWriter().write("Invalid X-Authorization header.");
return;
}
SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_NET");
Authentication authentication = new UsernamePasswordAuthenticationToken("xUser", null, Collections.singleton(authority));
SecurityContextHolder.getContext().setAuthentication(authentication);
}
filterChain.doFilter(request, response);
}
private boolean isNetEndpoint(HttpServletRequest request) {
return Arrays.stream(this.netEndpoints).anyMatch(endpoint -> endpoint.equals(request.getRequestURI()));
}
@Override
public void init(FilterConfig filterConfig) {
// no implementation needed
}
@Override
public void destroy() {
// no implementation needed
}
}
Как я могу это исправить?
Я уже пытался найти решения в stackoverflow и там где есть несколько хороших записей об отсутствии средства сопоставления безопасности.
Я сверяюсь с документами весной, но безуспешно.
Подробнее здесь: https://stackoverflow.com/questions/787 ... g-security