Spring security redirect to static resources after authentication - spring

Good morning,
I am writing an application using Spring security (latest version) and Spring MVC (latest version).
After securying everything was ok, the form and the controller, together with Spring security configuration worked well and the login was always successful.
Then I added a custom css and some images to display a better graphic, here it came the problem:
everytime I login I am first redirected to the login.css file rather than the homepage, although the login is successful I first see a blank page with the url of the css.
Spring Security configuration
#Override
protected void configure(HttpSecurity http) throws Exception
{
http.authorizeRequests()
//configure security for pages
.antMatchers(new String[]{"/login", "/accessDenied"}).permitAll()
.antMatchers("/**").access("hasAnyRole('admin', 'operatore')")
.anyRequest().authenticated()
//creates login form
.and().formLogin().loginPage("/login").loginProcessingUrl("/login")
.defaultSuccessUrl("/home").failureUrl("/accessDenied")
.usernameParameter("id_utente").passwordParameter("password")
//catches exceptions http 403 response
.and().exceptionHandling().accessDeniedPage("/accessDenied");
http.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
}
Static resources are under the path /static/css and /static/images.
I read this problem comes from the fact that Spring security redirects you to the last requested url after login, as to resolve the issue I tried using
#Override
public void configure(WebSecurity web)
{
web.ignoring().antMatchers("/static/**");
}
but it didn't work.
Are there any way to solve this problem?
EDIT
I already tried using
#Override
protected void configure(HttpSecurity http) throws Exception
{
http.authorizeRequests()
//configure security for pages
.antMatchers("/static/**").permitAll()
.antMatchers(new String[]{"/login", "/accessDenied"}).permitAll()
.antMatchers("/**").access("hasAnyRole('admin', 'operatore')")
.anyRequest().authenticated()
//creates login form
.and().formLogin().loginPage("/login").loginProcessingUrl("/login")
.defaultSuccessUrl("/home").failureUrl("/accessDenied")
.usernameParameter("id_utente").passwordParameter("password")
//catches exceptions http 403 response
.and().exceptionHandling().accessDeniedPage("/accessDenied");
http.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
}
But I am anyhow redirected after a successufl login to a 404 page with url "http://localhost:8080/static/css/login.css". In the login page the static resources are corretcly served as the style is how I expect it to be.
EDIT #2
I Edited as Eleftheria Stein-Kousathana said, but it keeps redirecting to the css (showing the code inside this time) instead of the homepage.
The project structure is:
Resource handler is added this way:
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry)
{
registry.addResourceHandler("/static/**").addResourceLocations("/static/");
}
and updated configuration is:
#Override
protected void configure(HttpSecurity http) throws Exception
{
http.authorizeRequests()
//configure security for pages
.antMatchers("/css/**", "/images/**").permitAll()
.antMatchers(new String[]{"/login", "/accessDenied"}).permitAll()
.antMatchers("/**").access("hasAnyRole('admin', 'operatore')")
.anyRequest().authenticated()
//creates login form
.and().formLogin().loginPage("/login").loginProcessingUrl("/login")
.defaultSuccessUrl("/home").failureUrl("/accessDenied")
.usernameParameter("id_utente").passwordParameter("password")
//catches exceptions http 403 response
.and().exceptionHandling().accessDeniedPage("/accessDenied");
http.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
}
Inside login page the css is linked this way:
<link rel="stylesheet" href="<c:url value="/static/css/login.css" />">
With the new antMatchers the result is not a 404 but the code inside the css. By the way, the linked css is not served anymore as style is not displayed correctly if I use the new configuration and "/static/css/login.css" or "/css/login.css", none of the two link work.

Since static/css and static/images are under the static directory, they will be served at /css and /images respectively.
You can permit all requests to those resources in your HTTP security configuration.
http.authorizeRequests()
.antMatchers("/css/**", "/images/**").permitAll()
// ...

Related

TemplateInputeException while trying to serve frontend on my Spring Boot App

Controller Class:
#Controller
public class FirstRestController {
#GetMapping("/")
public String budget() {
return "budget";
}
Security Config:
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/h2-console/**").permitAll()
.antMatchers("/api/auth/**").permitAll()
.antMatchers("/").permitAll()
.anyRequest().authenticated()
.and()
.httpBasic();
}
package structure image
I try to build a frontend for my web application. I'm using the Controller to serve my html Pages. But they are not rendering proberly. I always get a 404 not found Exception.
Now I tried it with Thymeleaf. But i always catch the TemplateInputeException. Thymeleaf is configured in my Pom.xml. I don't know where to debug this. I can't find a typo. So I think it's a bigger configuration I missed. Do I have to configure my resource folder somewhere? How can I server my html frontend pages in the app?
I tried to reinstall Thymeleaf. I already restarted IntelliJ. It tried to use the RequestMapping annotation. I renamed the static folder to public. I tried different paths.

Spring boot security block non RestController endpoints

I have an app that is exposing a bunch of endpoints that I did not expect. For example localhost:8080/app/ returns a list of URL that among other things exposes information related to the hibernate entities.
I DO NOT want basic auth enabled as I have my own authentication configured.
But if the URL is not one that is represented by a RestController I have written then I want it to an existing forbidden page that I have.
Here is my current config but it does not prevent the unwanted endpoints:
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/api/**").antMatchers("/v2/**").antMatchers("/webjars/**").antMatchers("/swagger-resources/**")
.antMatchers("/swagger-ui.html");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.httpBasic().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.csrf().disable();
http.authenticationProvider(new CustomAuthenticationProvider()).authorizeRequests().anyRequest().authenticated()
.antMatchers("/v2/**").permitAll().antMatchers("/webjars/**").permitAll().antMatchers("/swagger-resources/**").permitAll()
.antMatchers("/swagger-ui.html").permitAll()
.antMatchers("/health").permitAll();
http.rememberMe().rememberMeServices(rememberMeService).useSecureCookie(useSecureCookie);
//Show 403 on denied access
http.exceptionHandling().authenticationEntryPoint(new Forbidden());
}
So in this case localhost:8080/app/api/SearchControler/{var} should work but localhost:8080/app/ should go to my Forbidden entry point. Instead localhost:8080/app/ is going to the spring username and password page.
First off I don't know why these endpoints are even showing up when there is no RestController for them and second why is redirecting to a 403 page so difficult.
I'm not sure what config I am missing.
* EDIT *
I have also tried:
http.formLogin().and().httpBasic().disabled();
as well as:
#EnableAutoConfiguration(exclude = {SecurityAutoConfiguration.class, ManagementWebSecurityAutoConfiguration.class})
and nothing seems to stop spring from taking over and doing whatever it feels like doing.
Try again after removing super.configure(http); in your configure(HttpSecurity http) method.
Documentation
Override this method to configure the {#link HttpSecurity}. Typically
subclasses * should not invoke this method by calling super as it
may override their * configuration. The default configuration is:
http.authorizeRequests().anyRequest().authenticated().and().formLogin().and().httpBasic();
I think there is more configuration which you didn't show to as, but anyway:
#Override
public void configure(WebSecurity web) throws Exception {
//this is only for ignoring static resources in your app, sth that is never changed (you can cash it) and public (available for any user on the internet (ex. /js /css - sth else static img etc)
web.ignoring().antMatchers("/webjars/**").antMatchers("/swagger-resources/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
//super.configure(http); this call the default configuration, if you implement this method you shouldn't call the default one
http.httpBasic().disable();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.csrf().disable();
http.authenticationProvider(new CustomAuthenticationProvider())
.authorizeRequests() // the order is matter here, if antMatchers() will match the request the others after him will not be checked, anyRequest() will match any request, so it should be at the end
//.permitAll().antMatchers("/webjars/**").permitAll().antMatchers("/swagger-resources/**").permitAll() - there is no need to duplicate what is in web.ignoring() - such requests will not reach this point
.antMatchers("/swagger-ui.html").permitAll()
.antMatchers("/health").permitAll()
.anyRequest().authenticated()
http.rememberMe().rememberMeServices(rememberMeService).useSecureCookie(useSecureCookie);
//Show 403 on denied access
http.exceptionHandling().authenticationEntryPoint(new Forbidden());
}
This issue is completely related to transitive dependencies. After removing some dependencies and adding excludes to others the core problem has been solved.

Spring Boot 2 Security downloading font file upon login

I've setup a spring boot 2 application with a login form, however, when you login, instead of redirecting to /admin like it's supposed to, it downloads a font file referenced by the stylesheet via an #import.
Here is my security setup;
#Configuration
#EnableWebSecurity()
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
UserService userService;
#Bean
public PasswordEncoder passwordEncoder() {
return PasswordEncoderFactories.createDelegatingPasswordEncoder();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
// These pages don't require the user to be logged in
http.authorizeRequests()
.antMatchers("/", "/login", "/logout", "/report/**").permitAll()
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.anyRequest().authenticated();
// When the user has logged in as XX.
// But access a page that requires role YY,
// AccessDeniedException will be thrown.
http.authorizeRequests().and().exceptionHandling().accessDeniedPage("/403");
// Config for Login Form
http.authorizeRequests().and().formLogin()//
// Submit URL of login page.
.loginProcessingUrl("/j_spring_security_check") // Submit URL
.loginPage("/login")//
.defaultSuccessUrl("/admin")//
.failureUrl("/login?error=true")//
.usernameParameter("username")//
.passwordParameter("password")
// Config for Logout Page
.and().logout().logoutUrl("/logout").logoutSuccessUrl("/login?logout=true");
}
}
Where am I going wrong? From what I can see, I'm enabling access to Spring resources that are stored in the static folder.
I figured this one out, I read the code that allows access to resources and noticed it said 'atCommonLocations', and guess this adds access to folders such as css, js, img, images etc. I had fonts in a folder labelled webfonts, so I updated my security configuration;
http.authorizeRequests()
.antMatchers("/", "/login", "/logout", "/report/**", "/webfonts/**").permitAll()
.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
.anyRequest().authenticated();

Allowing static resources without spring security authentication

Hi I integrated spring security in my web application. My configure() method is overriden as,
#Override
protected void configure( HttpSecurity http ) throws Exception
{
http.cors().and().csrf().disable().authorizeRequests().antMatchers(HttpMethod.POST, "/rest/auth/**").permitAll()
.antMatchers("/resources/static/**")
.permitAll().antMatchers("/").permitAll().anyRequest().authenticated().and()
.addFilter(new JWTAuthenticationFilter(authenticationManager()))
.addFilter(new JWTAuthorizationFilter(authenticationManager()));
}
my project structure is as in the image. But spring security is not actually allowing the resource without authentication. In WebSecurityConfig.java if I remove .anyRequest().authenticated(), it is allowing css and js for the browser to render. How to solve this?

Spring's WebSecurity 'ignore' still creating sessions

I want to avoid creating a session when a user requests static resources like css files. Howerver, even after telling WebSecurity to ignore this static resource path, I noticed that all of the responses from my SpringBoot application still have the JSESSIONID cookie. Why?
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/css/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
.loginPage("/login")
.loginProcessingUrl("/login")
.and()
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/login", "/error").permitAll()
.anyRequest().authenticated(); //all other pages require users to be authenticated
}
I'm using Spring Security to protect my application.... but for requests to these static resources, I don't want a session created or validated.
I found the issue. It was my fault. I'm using Spring Security and extended RequestHeaderAuthenticationFilter. While web.ignoring()... does avoid all Spring Security authentication/authorization checks, it still does run through the custom filters.
In one of my filters I had the following line:
HttpServletRequest req = ((HttpServletRequest) request);
HttpSession session = req.getSession();
I use it to check if a session already exists and if I need to refresh it (too complicated to explain here). But that method, req.getSession() will create a new session if it doesn't already exist. I didn't realize it had that side effect.
Instead, I should be calling: req.getSession(false). This will return a session if it already exists and return null if it doesn't.

Resources