I'm trying to add a landing page to a Spring Application that I created so that when the application initially loads the landing page is the first page that is seen. The issue is, I created the landing page after I created the application and so the application loads a login/register page first and I cannot route the landing page to open first. I'm trying to research online where I could possibly complete this task yet I'm lost and would really appreciate some help.
I've included the WebSecurityConfig file below.
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/resources/**", "/registration").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
//Disable csrf token as it is not needed for now and is preventing the applciation from running properly
http.csrf().disable();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
}
Related
I'm writing a basic Web App using Java Spring Boot and am currently having issues with the roles of my users in my database and access to different parts of the app. The users can either have the role "ADMIN" or "USER". The only difference between what's allowed for these 2 roles is that the ADMIN is able to visit the "/register" page, whereas the other people in the role USER cannot. I have posted the code for my http configure method below, and am not sure where I am going wrong. I want all users to be able to access the login page and only the ADMIN to access the "/register" page. The issue I'm experiencing is that as of now, for some reason, the "/home" page to my app is to able be seen without even logging in. Logging in with what I have below is not being enforced.
package bcoreHW.security;
import org.springframework.beans.factory.annotation.Autowired;
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;
import org.springframework.security.crypto.password.PasswordEncoder;
import bcoreHW.service.UserService;
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
UserService userService;
#Autowired
private PasswordEncoder passwordEncoder;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers( // allow users access to any files in js, css, and img directories
"/login",
"/js/**",
"/css/**",
"/img/**")
.permitAll()
.antMatchers("/register")
.hasRole("ADMIN")
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/home")
.permitAll()
.and()
.logout()
.permitAll();
}
// #Autowired
// public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// auth
// .inMemoryAuthentication()
// .withUser("test")
// .password("hello")
// .roles("USER");
// }
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(passwordEncoder);
}
}
If I change the configure() method to what I have below, however, at least the user is forced to login, and the permissions from there are correct on an "on-click" basis, but I am still able to go to the address bar and search for "/register" under a USER role, which is why I attempted to implement the first piece of code I posted. Neither have worked yet, and was hoping for some help.
package bcoreHW.security;
import org.springframework.beans.factory.annotation.Autowired;
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;
import org.springframework.security.crypto.password.PasswordEncoder;
import bcoreHW.service.UserService;
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
UserService userService;
#Autowired
private PasswordEncoder passwordEncoder;
#Override
protected void configure(HttpSecurity http) throws Exception {
//#formatter:off
http
.authorizeRequests()
.antMatchers( // allow users access to any files in js, css, and img directories
"/login",
"/js/**",
"/css/**",
"/img/**")
.permitAll()
.anyRequest().
authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/home")
.permitAll()
.and()
.logout()
.permitAll();
}
// #Autowired
// public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// auth
// .inMemoryAuthentication()
// .withUser("test")
// .password("hello")
// .roles("USER");
// }
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService).passwordEncoder(passwordEncoder);
}
}
Make sure you are storing the users with roles as ROLE_ADMIN and ROLE_USER in the database
#Override
public void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers( "/login", "/js/**", "/css/**", "/img/**").permitAll() // allow users access to any files in js, css, and img directories
.antMatchers("/register").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login")
.defaultSuccessUrl("/home").permitAll()
.and()
.logout().permitAll();
}
I have an application providing several REST endpoints and web pages as well.
/products -- REST endpoint
/cutomers -- REST endpoint
/ui/catalog -- Web
/ui/admin -- Web
I want to set up the security so all web starting with /ui/** are redirected to a login page and all the others (REST) are challenged with 401 and WWW-Authenticate.
With the following settings the login page is not permitted and 401 with the header is sent:
#Configuration
#Order(20)
#RequiredArgsConstructor
class RestConfigurationAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.requestMatcher(AnyRequestMatcher.INSTANCE)
.authorizeRequests().anyRequest().fullyAuthenticated();
httpSecurity.
requiresChannel().
requestMatchers(AnyRequestMatcher.INSTANCE).
requiresSecure();
}
}
#Configuration
#Order(10)
#RequiredArgsConstructor
class WebUIConfigurationAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.antMatcher("/ui/**")
.authorizeRequests().anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").permitAll()
.and()
.logout().permitAll();
}
}
Why this doesn't work? I would expect to be redirected to the login page (it works) and the login page to be 200 (it doesn't work).
Editing the WebUIConfigurationAdapter as follows solves the problem:
httpSecurity.requestMatchers()
.antMatchers("/ui/**", "/login", "/logout")
.authorizeRequests().anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").permitAll()
.and()
.logout().permitAll();
The URL /login is set by WebUIConfigurationAdapter so it is then excluded by RestConfigurationAdapter.
Thanks #PraveenKumarLalasangi for his comment.
I have a Spring Boot project using Spring Security and OAuth2.0 libraries.
I confirmed when I accessed http://localhost:8080/login, the default login view is displayed and I could log in.
But if I implement Config class shown below:
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers( "/login**" ).permitAll()
.anyRequest()
.authenticated();
}
}
The browser returns "404 not found error".
I thought I could be authenticated directly accessing to a Github's API, so implemented this, but it Wouldn't work:
#RequestMapping(value = "/login", method = RequestMethod.GET)
public String login(){
return "redirect:/oauth2/authorization/github";
}
How should I cope with that? I know I probably have some misunderstandings because of a lack of my knowledge,
but I only want to know how to allow access to only a login page when a user is not authenticated.
Thanks.
finally solved!
I need to append following parts to the end of the methods flow.
.and()
.oauth2Login()
.loginPage("/login");
so the final code is:
SecurityConfig.java
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
#Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/login**")
.permitAll()
.anyRequest()
.authenticated()
//appended
.and()
.oauth2Login()
.loginPage("/login");
}
}
Controller.java
#GetMapping(value = "/login")
public String getit(Model model){
return "login";
}
login.html
<body>
<a th:href="#{/oauth2/authorization/github}">Login</a>
</body>
It worked!
Referenced URL:https://www.codeflow.site/ja/article/spring-security-5-oauth2-login
I'm trying to get spring security to allow the serving of static files like .css .js etc. without need to login first.
I've tried creating MVC config with resource handler and changing rules in spring security config, but nothing seems to be working.
MvcConfig.java:
#Configuration
#EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/assets/**")
.addResourceLocations("/assets/");
}
}
SecurityConfig.java:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/", "/assets/**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
#Override
public void configure(WebSecurity web) {
web.ignoring().antMatchers("/assets/**");
}
}
When I go to http://localhost:8080/assets/js/particles.min.js I'm expecting it to return the file contents but every time I try links like localhost:8080/assets/* it returns the content of login.html
My assets files
My project files
Supposing that your static files are under src/main/resources:
There are two main pieces to configure:
Implement the WebMvcConfigurer interface to discover your static resources:
#Configuration
public class MvcConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
if (!registry.hasMappingForPattern("/assets/**")) {
registry.addResourceHandler("/assets/**")
.addResourceLocations("/assets/");
}
}
}
Setup your security configuration to allow static resources (such as CSS, JavaScripts and images) to be publicly accessible:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
// Your settings
#Override
protected void configure(HttpSecurity http) throws Exception {
// Your AuthN handlers and filter chain...
http
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/css/**").permitAll()
.antMatchers("/img/**").permitAll()
.antMatchers("/js/**").permitAll()
.anyRequest().authenticated();
// Logout handler...
}
}
Supposing that you have a CSS file as follows:
src/main/resources/assets/css/layout.css
The web server will make it accessible at:
http://<root_url>:<port>/css/layout.css
Try to change to:
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/assets/").permitAll()
.and()
.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
web.ignoring().antMatchers("/assets/**");
The statement above will tell spring security to Ignore any request that starts with “/assets/”. So if i were you, i will remove all the following configuration:
.antMatchers("/", "/assets/**")
.permitAll()
fom the configure(HttpSecurity http) method.
I have a problem with Spring Security and error pages , becaus when I am logged in the application I can show when the page is not exist.
But when I am out of the application my spring security show the login page by default.
This is my spring security configuration.
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
#Autowired
private DataSource dataSource;
#Value("${spring.queries.users-query}")
private String usersQuery;
#Value("${spring.queries.roles-query}")
private String rolesQuery;
#Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.
jdbcAuthentication()
.usersByUsernameQuery(usersQuery)
.authoritiesByUsernameQuery(rolesQuery)
.dataSource(dataSource)
.passwordEncoder(bCryptPasswordEncoder);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.
authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/login").permitAll()
.antMatchers("/registration").permitAll()
.antMatchers("/admin/**").hasAuthority("ADMIN")
.antMatchers("/user_login").hasAuthority("USER").anyRequest()
.authenticated().and().csrf().disable().formLogin()
.loginPage("/login").failureUrl("/login?error=true")
.defaultSuccessUrl("/user_login")
.usernameParameter("email")
.passwordParameter("password")
.and().logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/")
.and().exceptionHandling()
.accessDeniedPage("/access-denied");
}
#Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/resources/**", "/static/**", "/css/**", "/js/**", "/images/**");
}
}
This works correctly but I don't know why when I am out of the application I redirect to login page.
Any solution for this?
Regards!
All the requests other than /, /login, /registration requires the user to be authenticated (anyRequest().authenticated()), and when you are enabling formLogin() spring's filters will redirect all the not authenticated requests to the login page even if the page doesn't exits, thats is why you are redirected to the login and not getting a 404 error.
For testing purposes you can add a test matcher without adding an actual endpoint in the controller like this:
.antMatchers("/test").permitAll() and try to access this endpoint without being authenticated and you will get the 404 error page.
p.s. make sure that the 404 response is not blocked as well (if it is a controller response then enable it as well, because your js is allowed for everyone).