Consolidate data access control backoffice updates
This commit is contained in:
@@ -1,16 +1,18 @@
|
||||
package com.cloudhandson.vpdbackoffice.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.http.HttpMethod;
|
||||
|
||||
@Configuration
|
||||
public class SecurityConfig {
|
||||
@@ -19,23 +21,48 @@ public class SecurityConfig {
|
||||
SecurityFilterChain securityFilterChain(
|
||||
HttpSecurity http,
|
||||
BackofficeProperties properties,
|
||||
McpAccessTokenFilter mcpAccessTokenFilter
|
||||
UserDetailsService userDetailsService
|
||||
) throws Exception {
|
||||
if (properties.security().requireHttps()) {
|
||||
http.requiresChannel(channel -> channel.anyRequest().requiresSecure());
|
||||
}
|
||||
|
||||
var security = properties.security();
|
||||
if (security.rememberMeConfigured()) {
|
||||
http.rememberMe(rememberMe -> rememberMe
|
||||
.key(security.rememberMeKey())
|
||||
.userDetailsService(userDetailsService)
|
||||
.rememberMeParameter("remember-me")
|
||||
.rememberMeCookieName("VPD_REMEMBER_ME")
|
||||
.tokenValiditySeconds(security.rememberMeValiditySeconds())
|
||||
.useSecureCookie(true)
|
||||
.alwaysRemember(false));
|
||||
}
|
||||
|
||||
return http
|
||||
.addFilterBefore(mcpAccessTokenFilter, BasicAuthenticationFilter.class)
|
||||
.csrf(csrf -> csrf.ignoringRequestMatchers(
|
||||
"/mcp", "/mcp/messages", "/mcp/*/messages", "/dds/mcp/messages"))
|
||||
"/mcp", "/mcp/messages", "/mcp/*/messages"))
|
||||
.headers(headers -> headers.httpStrictTransportSecurity(hsts -> hsts
|
||||
.includeSubDomains(true)
|
||||
.maxAgeInSeconds(31_536_000)))
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
.requestMatchers("/css/**", "/js/**", "/webjars/**", "/dds/mcp/sse", "/dds/mcp/messages")
|
||||
.requestMatchers(
|
||||
"/css/**", "/js/**", "/webjars/**",
|
||||
"/mcp", "/mcp/sse", "/mcp/*/sse", "/mcp/messages", "/mcp/*/messages")
|
||||
.permitAll()
|
||||
.requestMatchers(HttpMethod.POST, "/mcp").hasAnyRole("ADMIN", "MCP")
|
||||
.requestMatchers(HttpMethod.POST, "/login", "/logout").permitAll()
|
||||
.requestMatchers(HttpMethod.POST,
|
||||
"/probe",
|
||||
"/vector-knowledge/search",
|
||||
"/security-sql-scripts/explanation",
|
||||
"/mcp-chatbot",
|
||||
"/mcp-client-demo",
|
||||
"/mcp-reasoning")
|
||||
.authenticated()
|
||||
.requestMatchers(HttpMethod.PUT, "/**").hasRole("ADMIN")
|
||||
.requestMatchers(HttpMethod.PATCH, "/**").hasRole("ADMIN")
|
||||
.requestMatchers(HttpMethod.POST, "/**").hasRole("ADMIN")
|
||||
.requestMatchers(HttpMethod.DELETE, "/**").hasRole("ADMIN")
|
||||
.anyRequest().authenticated())
|
||||
.httpBasic(basic -> {
|
||||
})
|
||||
@@ -52,11 +79,26 @@ public class SecurityConfig {
|
||||
PasswordEncoder passwordEncoder
|
||||
) {
|
||||
var security = properties.security();
|
||||
var user = User.withUsername(security.adminUser())
|
||||
.password(passwordEncoder.encode(security.adminPassword()))
|
||||
String encodedPassword = security.adminPasswordHash() == null || security.adminPasswordHash().isBlank()
|
||||
? passwordEncoder.encode(security.adminPassword())
|
||||
: security.adminPasswordHash();
|
||||
List<UserDetails> users = new ArrayList<>();
|
||||
users.add(User.withUsername(security.adminUser())
|
||||
// BCrypt encoding includes a random salt. Re-encoding the configured
|
||||
// password on every startup would invalidate remember-me signatures.
|
||||
.password(encodedPassword)
|
||||
.roles("ADMIN")
|
||||
.build();
|
||||
return new InMemoryUserDetailsManager(user);
|
||||
.build());
|
||||
if (security.guestConfigured()) {
|
||||
String encodedGuestPassword = security.guestPasswordHash() == null || security.guestPasswordHash().isBlank()
|
||||
? passwordEncoder.encode(security.guestPassword())
|
||||
: security.guestPasswordHash();
|
||||
users.add(User.withUsername(security.guestUser())
|
||||
.password(encodedGuestPassword)
|
||||
.roles("VIEWER")
|
||||
.build());
|
||||
}
|
||||
return new InMemoryUserDetailsManager(users);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
Reference in New Issue
Block a user