Spring Security Thymleaf static resources don't load - spring

I'm using SpringMVC with Thymleaf and Spring-Security.
I want to load a page using Thymleaf template and I can load my static resources.
I want to load for example a picture located in : static/img/theme/logo.png from template.html
Here is what I have : result
template.html :
<body>
<div layout:fragment="content">
img src="../static/img/theme/logo.png" alt="Logo">
<h1>Hello</h1>
</div>
</body>
MvcConfig.java
#Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/home").setViewName("home");
registry.addViewController("/index").setViewName("index");
registry.addViewController("/template").setViewName("template");
registry.addViewController("/layout").setViewName("layout");
registry.addViewController("/login").setViewName("login");
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
WebSecurityConfig :
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
//List of all free pages
private static final String[] pagesFree = {
"/home",
"/template",
"/layout",
//Thymleaf directory
"/css/**",
"/js/**",
"/img/**",
"/fonts/**",
"/ico/**",
"/twitter/**",
"/"
};
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers(pagesFree).permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("u").password("u").roles("USER");
}
}
Source Code tree

In your security configuration you would declare something like this:
/** Public URLs. */
private static final String[] PUBLIC_MATCHERS = {
"/webjars/**",
"/css/**",
"/js/**",
"/images/**",
"/"
};
Then something like this:
#Override
protected void configure(HttpSecurity http) throws Exception {
List<String> activeProfiles = Arrays.asList(env.getActiveProfiles());
if (activeProfiles.contains("dev")) {
http.csrf().disable();
http.headers().frameOptions().disable();
}
http
.authorizeRequests()
.antMatchers(PUBLIC_MATCHERS).permitAll()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").defaultSuccessUrl("/payload")
.failureUrl("/login?error").permitAll()
.and()
.logout().permitAll();
}
And in your Thymeleaf template you'd declare something like this:
<img class="featurette-image pull-left" th:src="#{/images/browser-icon-firefox.png}" />
A working copy of your project can be found here.

Related

Resource handler for caching cause issue

I use spring boot 2.6.7, spring security and thymeleaf
In a class who extends WebSecurityConfigurerAdapter
#Override
public void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeRequests()
.antMatchers(HttpMethod.POST, "/printdownload**").permitAll()
.antMatchers(
"/",
"/css/**",
"/js/**",
"/img/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").permitAll()
.successHandler(customAuthenticationSuccessHandler)
.and()
.logout();
}
#Override
public void configure(WebSecurity web) {
web.ignoring().antMatchers("/css/**", "/js/**", "/img/**");
}
Since I added this code (want to cache static content),
I tried
#Configuration
public class MvcConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/css/**", "/resources/js/**", "/resources/img/**")
.addResourceLocations("/resources/static/css/", "/resources/static/js/", "/resources/img/")
.setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS));
}
}
tried also
#Override
public void addResourceHandlers (ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/js/**")
.addResourceLocations("/static/js/")
.setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS));
registry.addResourceHandler("/static/img/**")
.addResourceLocations("/static/img/")
.setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS));
registry.addResourceHandler("/static/css/**")
.addResourceLocations("/static/css/")
.setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS));
}
When i check in firefox, nothing go cached

multiple entry points in spring security

I have a spring boot application that should allow form based authentication against database and SSO CAS based authentication.
I have followed the example from here (https://www.baeldung.com/spring-security-multiple-entry-points) and seems to me that Order is not working as expected. it is always using the one that is annotated as Order(1) as entry point.
here is my code,
#Configuration
#EnableWebSecurity
public class SecurityConfig {
#Configuration
#Order(2)
public static class WebSecurityCASConfig extends WebSecurityConfigurerAdapter {
public WebSecurityCASConfig() {
super();
}
#Autowired
private AuthenticationEntryPoint authenticationEntryPoint;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers(
"/js/**",
"/css/**",
"/images/**").permitAll()
.regexMatchers("/login1")
.authenticated()
.and()
.authorizeRequests()
.and()
.httpBasic()
.authenticationEntryPoint(authenticationEntryPoint);
}
}
//second
#Configuration
#Order(1)
public static class WebSecurityDatabaseConfig extends WebSecurityConfigurerAdapter {
public WebSecurityDatabaseConfig() {
super();
}
#Autowired
UserDetailServiceImpl userDetailsService;
#Autowired
BCryptPasswordEncoder passwordEncoder;
#Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers(
"/js/**",
"/css/**",
"/images/**").permitAll()
//.antMatchers("/catalog").access("hasAnyRole('ROLE_USER', 'ROLE_ADMIN')")
////.antMatchers("/login1").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/catalog", true)
.permitAll()
.usernameParameter("username")
.passwordParameter("password")
.and()
.logout()
.permitAll()
.logoutUrl("/logout").logoutSuccessUrl("/logout")
.and().exceptionHandling().accessDeniedPage("/403");
}
}
}
I want both configurations work based on url pattern. Any solutions/help/suggestions would be highly appreciated. Thanks.
I found a solution for this. I just simply followed what the spring document says in 5.9 (https://docs.spring.io/spring-security/site/docs/5.0.0.RELEASE/reference/htmlsingle/) and also another question on stackoverflow, Spring Security : Multiple HTTP Config not working

404 error for login page in spring boot security... I am working in intellj idea community version

I am trying to implement spring boot security.And it is not able to find login page
This is my folder structure.
resources
static
home.html
login.html
templates
index.html
This is security Config file
enter code here
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter{
#Autowired
public void configureAuth(AuthenticationManagerBuilder auth) throws
Exception{
auth
.inMemoryAuthentication()
.withUser("dan")
.password("password")
.roles("ADMIN")
.and()
.withUser("joe")
.password("password")
.roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/login?logout")
.permitAll();
http.csrf().disable();
}
}
this is my webconfig file
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
super.addViewControllers(registry);
registry.addViewController("/home").setViewName("home.html");
registry.addViewController("/login").setViewName("login.html");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
}
}
Please help. How to solve this error
It is working fine while specifying html file instead of just writing name of file.
Modifying above code.
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login.html")
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/login?logout")
.permitAll();
http.csrf().disable();
}
Also remove .html from setviewname
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addViewControllers(ViewControllerRegistry registry) {
super.addViewControllers(registry);
registry.addViewController("/home").setViewName("home");
registry.addViewController("/login").setViewName("login");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
}
}

Authorization roles Spring-boot Oauth2 ~ Restful API

i'm needing help with this problem...
i can't secure my controllers in my security configuration files. but i can do it in my controller using
#PreAuthorize("hasAuthority('ROLE_ADMIN')")
but this is really annoying, i want to do it from my security conf. files
this is my WebSecurityconfigurerAdapter:
#Configuration
//#EnableWebMvcSecurity
#EnableGlobalMethodSecurity(prePostEnabled = false)
//#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
//#EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
CustomAuthenticationProvider customAuthenticationProvider;
#Autowired
CustomUserDetailsService cuds;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(cuds)
.passwordEncoder(passwordEncoder())
.and()
.authenticationProvider(customAuthenticationProvider);
}
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
#Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/**").authenticated()
.antMatchers("/test").authenticated()
.antMatchers("/usuarios/**").hasRole("ADMIN");
}
}
and this is my Oauth2Configuration:
#Configuration
public class Oauth2Configuration {
private static final String RESOURCE_ID = "restservice";
#Configuration
#EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
#Autowired
private CustomLogoutSuccessHandler customLogoutSuccessHandler;
#Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources
.resourceId(RESOURCE_ID);
}
#Override
public void configure(HttpSecurity http) throws Exception {
http
// Logout
.logout()
.logoutUrl("/oauth/logout")
.logoutSuccessHandler(customLogoutSuccessHandler)
.and()
//Session management
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
//URI's to verify
.authorizeRequests()
.antMatchers("/oauth/logout").permitAll()
.antMatchers("/**").authenticated()
.antMatchers("/usuarios/**").hasRole("ADMIN");
}
}
i've tried to use authority and roles, but nothings works. some idea what i'm doing wrong?
Well thanks to Yannic Klem i got the answer, was a problem with the order
First on my WebSecurityConfigurerAdapter i set my authentication on "usuarios"
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/usuarios").authenticated();
}
after that in my Oauth2Configuration set my authorizarion with my rol.
#Override
public void configure(HttpSecurity http) throws Exception {
http
// Logout
.logout()
.logoutUrl("/oauth/logout")
.logoutSuccessHandler(customLogoutSuccessHandler)
.and()
//Session management
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
//URI's to verify
.authorizeRequests()
.antMatchers("/oauth/logout").permitAll()
.antMatchers("/usuarios/**").hasRole("ADMIN");
}
and now all works pretty fine. thank you all!

how to define the secured URLs within an application dynamically

I am using Spring framework version: 3.2.3.RELEASE and
Spring security version: 3.2.3.RELEASE
I want to define the secured URLs within an application dynamically,and I have tried for several ways . I just can't make it,please help me!
According to http://docs.spring.io/spring-security/site/docs/3.2.x/reference/htmlsingle/faq.html#faq-dynamic-url-metadata ,
I learn that dynamically defining access control to URLs needs using an explicitly declared security filter chain in order to customize the FilterSecurityInterceptor bean.
My question is
how to explicitly declared security filter chain?are there any example?
according to the book Spring security 3.1
which said"We can use a custom BeanPostProcessor to replace the standard FilterInvocationServiceSecurityMetadataSource with our custom implementation."
I followed this way and it dosen't work, I wondering if I have done something wrong?
the Java config class looks like this:
public class MessageSecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
}
#Configuration
#EnableWebSecurity
public class MultiHttpSecurityConfig {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER").and()
.withUser("admin").password("password").roles("USER", "ADMIN");
}
#Configuration
#Order(1)
public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/api/**")
.authorizeRequests()
.anyRequest().hasRole("ADMIN")
.and()
.httpBasic();
}
}
#Configuration
public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin();
}
}
}
#Component
public class KpiFilterInvocationSecurityMetadataSourceBeanPostProcessor implements BeanPostProcessor {
#Autowired
private KpiFilterInvocationSecurityMetadataSource metadataSource;
#Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if(bean instanceof FilterInvocationSecurityMetadataSource) {
return metadataSource;
}
if(bean instanceof FilterChainProxy.FilterChainValidator) {
return new FilterChainProxy.FilterChainValidator() {
#Override
public void validate(FilterChainProxy filterChainProxy) {
}
};
}
return bean;
}
#Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
I found a method withObjectPostProcessor,and try to do the following,it still doesn't worked. so what is best way to leverage this method?
#Configuration
public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Autowired
private KpiFilterInvocationSecurityMetadataSource metadataSource;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf()
.disable()
.authorizeRequests()
.antMatchers("/signup/**", "/about", "/login/**", "/index")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.permitAll()
.loginPage("/login/form")
.loginProcessingUrl("/login")
.usernameParameter("policeNo")
.passwordParameter("password")
.failureUrl("/login/form?error")
.defaultSuccessUrl("/default")
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/login/form?logout")
.and()
.authorizeRequests()
.anyRequest()
.authenticated()
.withObjectPostProcessor(
new ObjectPostProcessor<FilterSecurityInterceptor>() {
public <O extends FilterSecurityInterceptor> O postProcess(
O fsi) {
fsi.setSecurityMetadataSource(metadataSource);
return fsi;
}
});
}
#Override
public void configure(WebSecurity webSecurity) throws Exception {
webSecurity.ignoring().antMatchers("/resources/**");
}
}

Resources