Blocking going to other webpages throught url bar in spring boot application - java

I have a fundamental problem with spring boot application. The start webpage is http://127.0.0.1:8080/login and after log in user is redirect to http://127.0.0.1:8080/MainMenu. Unfortunatelly it is also possible to write in url bar http://127.0.0.1:8080/MainMenu and going there without authentication.
What is the main idea to block that action?
#edit
This is my configuration:
package local.vlex.security;
import org.springframework.context.annotation.Configuration;
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.WebSecurityConfigurerAdapter;
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "src/main/resources/static/assets/css/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
}
and Controller:
#GetMapping("/MainMenu")
public ModelAndView correctCredentials(){
ModelAndView mav = new ModelAndView();
mav.setViewName("MainMenu");
return mav;
}
Sum up:
I would like to block going to other sites without authentication - if someone is not logged in then it should go 404 on everything other than /login

if someone is not logged in then it should go 404 on everything other
than /login
This is a bit pecular requirement. What is usually done is that people get redirected to login page on all other urls than login, or get 401 Unauthorized or 403 Forbidden. However, it's not hard to do this one either.
You mentioned you need your static resources (css, js, images) in the assets directory as well, so given that, this should work:
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
#Configuration
#EnableWebSecurity
public class YourSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login", "/assets/**").permitAll()
.anyRequest().authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.NOT_FOUND))
;
}
}
Using
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
</parent>
and
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
in Maven pom.xml
Note that there is also accessDeniedHandler() in exceptionHandling(), but that seems to only fire when user is already authenticated but denied access, so you'd need authenticationentrypoint for your use case.
Addition:
Sometimes having a custom authentication entrypoint messes the existing entry point handler. That is the case at least if you use default spring-generated form login. One way to go around that is to specify your entrypoint to only match urls that are not matching your authentication handler url, like this:
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.NegatedRequestMatcher;
// snip...
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login", "/assets/**").permitAll()
.anyRequest().authenticated()
.and()
.exceptionHandling()
.defaultAuthenticationEntryPointFor(new HttpStatusEntryPoint(HttpStatus.NOT_FOUND),
new NegatedRequestMatcher(new AntPathRequestMatcher("/login")) )
.and()
.formLogin()
;
}

Add the following code, It will block all the request except "/" & "/login"
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers(
"/css/**",
"/js/**",
"/lib/**",
"/video/**",
"/images/**"
);
}
}
And add WebConfig
#Configuration
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter{
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/**")
.addResourceLocations("classpath:/static/")
.setCachePeriod(31556926)
.resourceChain(true);
}
}
Don't forget to add the security dependency in your pom.xml file.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

Provided that you have spring-security dependencies on classpath, this is a working example from my code.
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/", "/login**")
.permitAll()
.anyRequest()
.authenticated();
This blocks me from any other requests than '/' or 'login' or 'loginPage' etc. with Authorization.
Follow that with ignoring the static ones, css, js etc.,
If this still doesn't work, for now try working on blocking the page alone:
http.authorizeRequests()
.antMatchers("/MainMenu")
.authenticated();
The above would give idea what's happening. Dependency issue or something like that.

Related

I think that there is something wrong with my security config

So i have created a Security Config where i defined the patterns that i want to be granted access to without logging in. And it is not working. In my mind either the file its self is not getting scanned(even though i set it so it would be using #ComponentScan tag in the main Spring application) or the code is faulty.
Here is the code :
package com.projects.AProj.security;
import com.projects.AProj.service.AccountUserDetailsService;
import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.password.PasswordEncoder;
import static com.projects.AProj.security.Permission.DATA_READ;
import static com.projects.AProj.security.Permission.DATA_WRITE;
#Configuration
#EnableWebSecurity
#AllArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final PasswordEncoder passwordEncoder;
private final AccountUserDetailsService accountUserDetailsService;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.authorizeRequests()
.antMatchers("/","/**","/api/**")
.permitAll()
.antMatchers("/my-tree", "/my-tree/*")
.hasAnyAuthority(DATA_READ.getPermission_info(), DATA_WRITE.getPermission_info())
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login").permitAll()
.defaultSuccessUrl("/",true)
.and()
.logout()
.logoutSuccessUrl("/");
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(getDaoAuthenticationProvider());
}
#Bean
public DaoAuthenticationProvider getDaoAuthenticationProvider(){
DaoAuthenticationProvider daoAuthenticationProvider =
new DaoAuthenticationProvider();
daoAuthenticationProvider.setPasswordEncoder(passwordEncoder);
daoAuthenticationProvider.setUserDetailsService(accountUserDetailsService);
return daoAuthenticationProvider;
}
}
btw i would think that it would be helpful to note that the project it self has been acting a tad bit strange. I would get errors that the Repositories are not getting recognized, stuff like can't create bean with name "baseController", unsatisfied dependencies and those kinds of stuff.
Thanks.

Spring Security : Always bad Credentials

I'm trying to use authenticate using in-memory users but i always keep getting "bad credentials" even when they are right .
WebSecurityConfig.java:
package com.skillshare.project.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.WebSecurityConfigurerAdapter;
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers( "/home").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.permitAll()
.and()
.logout()
.permitAll();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("test").password("{noop}test").roles("USER");
}
}

How to wire authentication with Spring Boot

I am following the documentation from Spring.io to setup user authentication using Spring Boot.
Here are the files in question:
MvcConfig.java
package com.*********.*******;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
#Configuration
public class MvcConfig implements WebMvcConfigurer {
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/home").setViewName("home");
registry.addViewController("/").setViewName("home");
registry.addViewController("/hello").setViewName("hello");
registry.addViewController("/login").setViewName("login");
}
}
WebSecurityConfig.java
package com.*********.*******;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.WebSecurityConfigurerAdapter;
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.provisioning.InMemoryUserDetailsManager;
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
#Bean
#Override
public UserDetailsService userDetailsService() {
UserDetails user =
User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build();
return new InMemoryUserDetailsManager(user);
}
}
How can I eliminate the home.html file and wire it so that localhost:808 takes the user directly to the login which, if successful, brings them to the hello.html file?
If I change the default controller to the following code, then it just enters a loop of the login page because the login takes you to the previous page you were trying to access. How can I instead have it send the user to hello.html?
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/home").setViewName("home");
registry.addViewController("/").setViewName("login");
registry.addViewController("/hello").setViewName("hello");
registry.addViewController("/login").setViewName("login");
}
I apologize if this post is worded poorly. If there is anything I can add for clarity, please don't hesitate to ask and I will make any corrections.
Remove the line .antMatchers("/", "/home").permitAll() so all urls are protected and redirected to login.
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}

Spring security: how to turn off /logout for non-logged users?

I am building a spring security app. Login and logout are working fine, but I would like to make it impossible for non-logged users to logout which is possible by default (strange...).
I tried to add a custom Controller for /logout (checking if user is authenticated) but nothing seems to be working. Is there a way to do it in spring configuration instead? Below is my code. The controller is not working. The default spring-security /logout view is visible even if user is not authenticated.
package com.example.demo.config;
import com.example.demo.security.CustomAccessDeniedHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
#Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Bean
public AccessDeniedHandler accessDeniedHandler() {
return new CustomAccessDeniedHandler();
}
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/**").permitAll() // This will be your home screen URL
.antMatchers("/css/**").permitAll()
.antMatchers("/assets/css/js/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().permitAll()
.and()
.exceptionHandling()
.accessDeniedHandler(new CustomAccessDeniedHandler())
;
}
}
-----------------
#RequestMapping("/logout")
public String logout() {
if (!(SecurityContextHolder
.getContext()
.getAuthentication()
.getPrincipal() instanceof MyUserPrincipal)) {
// System.out.println("Non logged user is trying to logout");
return "redirect:/";
} else {
// System.out.println("Logged user is trying to logout");
return "redirect:/logout";
}
}
Finally found the solution. It appears that the "Are You sure..." page that is showed after a user goes to /logout is generated by CSRF module. After turning of CSRF the page did not show again. That was not the solution though because csrf needs to be enabled for security. One line was missing:
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
. Now user is logged out after going to /logout with no questions asked. It is not my desired solution but it does the trick for now ;). Thank You all for your responses.
package com.example.demo.config;
import com.example.demo.security.CustomAccessDeniedHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
#Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Bean
public AccessDeniedHandler accessDeniedHandler() {
return new CustomAccessDeniedHandler();
}
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/**").permitAll() // This will be your home screen URL
.antMatchers("/css/**").permitAll()
.antMatchers("/assets/css/js/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().permitAll()
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login")
.deleteCookies("JSESSIONID")
.invalidateHttpSession(true)
.and()
.exceptionHandling()
.accessDeniedHandler(new CustomAccessDeniedHandler())
;
}
}
You need to handle the permissions for the logout URL via the WebSecurityConfig class in the configure method which you are already doing for some URLs so change to something like:
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/**").permitAll() // This will be your home screen URL
.antMatchers("/css/**").permitAll()
.antMatchers("/assets/css/js/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().permitAll()
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/logoutSuccessful")
.permitAll()
.deleteCookies("JSESSIONID")
.invalidateHttpSession(true)
.and()
.exceptionHandling()
.accessDeniedHandler(new CustomAccessDeniedHandler())
;
}
notice the addition of
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/logoutSuccessful")
.permitAll()
.deleteCookies("JSESSIONID")
.invalidateHttpSession(true)
This is our logout handling code, so if users hit /logout they will be logged out and forwarded to the /logoutSuccessful (I would usually redirect to login page here).
You can also add a selection of other methods here for configuring your logout as well. The logout is just as configurable as the login, so you can add logout handlers as you see fit.

How to assign auth success handler to multiple spring security realms

I have the following Spring security configuration class for two separate security realms, the admin area and the frontend area:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled=true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private CustomUserDetailsServiceImpl userDetailsService;
#Configuration
#Order(1)
public static class AdminAreaConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private AuthSuccessAdmin authSuccessAdmin;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatcher(new AntPathRequestMatcher("/admin/**"))
.csrf().disable()
.authorizeRequests()
.antMatchers("/admin/login/login.html").permitAll()
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/admin/login.html")
.permitAll()
.successHandler(authSuccessAdmin)
.and()
.logout()
.permitAll();
}
}
#Configuration
#Order(2)
public static class UserAreaConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private AuthSuccessFrontend authSuccessFrontend;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.requestMatcher(new AntPathRequestMatcher("/**"))
.csrf().disable()
.authorizeRequests()
.antMatchers("/about", "/register").permitAll()
.antMatchers("/**").hasRole("USER")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.successHandler(authSuccessFrontend)
.and()
.logout()
.permitAll();
}
}
}
When the app is started, the authentication success handler of the admin area is overwritten by the authentication handler of the frontend area, which is loaded after the first. This results in a wrong redirect when logging into the admin area (redirects to url defined in the frontend auth success handler). How can I assign disctinct handlers to the separate configurations?
The issue seems to be in RequestMatcher pattern.
Your USER app has the RequestMatcher pattern '/**'(means anything after / which will include path /admin as well) which will override your ADMIN RequestMatcher pattern /admin/**
Change the user RequestMatcher to /user/**

Categories

Resources