You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
133 lines
4.2 KiB
133 lines
4.2 KiB
package com.mousetech.gourmetj;
|
|
|
|
import java.io.File;
|
|
import java.io.FileReader;
|
|
import java.io.LineNumberReader;
|
|
import java.util.Arrays;
|
|
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
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.config.Customizer;
|
|
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
|
import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
|
|
import org.springframework.security.config.annotation.authentication.configurers.provisioning.UserDetailsManagerConfigurer;
|
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
|
|
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
|
|
import org.springframework.security.web.SecurityFilterChain;
|
|
|
|
import jakarta.servlet.DispatcherType;
|
|
|
|
@Configuration
|
|
@EnableWebSecurity
|
|
public class SpringSecurityConfig {
|
|
//extends WebSecurityConfigurerAdapter {
|
|
|
|
/* Logger */
|
|
|
|
private static final Logger log =
|
|
LoggerFactory.getLogger(SpringSecurityConfig.class);
|
|
|
|
|
|
@Value("${gourmet.password.file}")
|
|
private String passwordFile;
|
|
|
|
/**
|
|
* Load in config file with in-memory credentials.
|
|
* For practical use, this should probably be
|
|
* replace with JdbcUserDetailsManager and credentials in
|
|
* the recipe database.
|
|
*
|
|
* @param auth Builder for the authenticator
|
|
* @throws Exception
|
|
*/
|
|
@Autowired
|
|
public void configureGlobal(
|
|
AuthenticationManagerBuilder auth) throws Exception {
|
|
|
|
File pwFile = new File(passwordFile);
|
|
if (!pwFile.canRead()) {
|
|
String msg =
|
|
"Password file '" + pwFile.getAbsolutePath()
|
|
+ "' could not be found or read.";
|
|
log.error(msg);
|
|
throw new RuntimeException(msg);
|
|
}
|
|
|
|
LineNumberReader rdr =
|
|
new LineNumberReader(new FileReader(pwFile));
|
|
String pwLine;
|
|
InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder>
|
|
authenticator =
|
|
auth.inMemoryAuthentication();
|
|
while ((pwLine = rdr.readLine()) != null) {
|
|
pwLine = pwLine.trim();
|
|
if ((pwLine.length() == 0)
|
|
|| (pwLine.charAt(0) == '#')) {
|
|
continue;
|
|
}
|
|
String[] creds = parseCreds(pwLine);
|
|
UserDetailsManagerConfigurer<AuthenticationManagerBuilder,
|
|
InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder>>
|
|
.UserDetailsBuilder bar =
|
|
authenticator.withUser(creds[0])
|
|
.password("{noop}" + creds[1]);
|
|
int credlen = creds.length;
|
|
for (int i = 2; i < credlen; i++) {
|
|
bar.roles(creds[i]);
|
|
}
|
|
}
|
|
rdr.close();
|
|
}
|
|
|
|
/**
|
|
* Parse CSV credential/roles line. Element 1 is userid,
|
|
* element 2 is password, following element(s) are role(s)
|
|
*
|
|
* @param pwLine
|
|
* @return Credentials array following CSV values, trimmed
|
|
*/
|
|
private String[] parseCreds(String pwLine) {
|
|
String[] creds = pwLine.split(",");
|
|
String[] ocreds = Arrays.stream(creds).map(e -> e.trim())
|
|
.toArray(String[]::new);
|
|
return ocreds;
|
|
}
|
|
|
|
@Bean
|
|
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
|
|
|
http
|
|
.csrf(AbstractHttpConfigurer::disable)
|
|
.cors(AbstractHttpConfigurer::disable)
|
|
.formLogin(Customizer.withDefaults())
|
|
.authorizeHttpRequests((authorize)-> authorize
|
|
.dispatcherTypeMatchers(DispatcherType.FORWARD, DispatcherType.ERROR).permitAll()
|
|
.anyRequest().authenticated()
|
|
);
|
|
|
|
return http.build();
|
|
}
|
|
|
|
/**
|
|
* Replaces old antMatchers for determining secured URLs.
|
|
* @return customizer
|
|
*/
|
|
@Bean
|
|
public WebSecurityCustomizer webSecurityCustomizer() {
|
|
return (web) -> web.ignoring().requestMatchers(
|
|
"/javax.faces.resource/**",
|
|
"/",
|
|
"/index.jsf",
|
|
"/index.xhtml",
|
|
"/main.jsf",
|
|
"/img/**",
|
|
"/recipeDetails.jsf",
|
|
"/recipePrint.jsf");
|
|
}
|
|
}
|
|
|