How to implement security in a spring application? - java

I'm creating a spring application for a college project.
package com.sales.security;
import org.springframework.context.annotation.Bean;
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.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/showProducts.html", "/showOrders.html", "/showCustomers.html","/newOrder.html","/addProduct.html","/addCustomer.html")
.authenticated()
.and()
.formLogin();
}
private static final String ENCODED_PASSWORD = "$2y$12$i4Cl5SZgrPFItSz/G5cvTObf0sqzHszwwKMZ4pQeUlElY1BR7KxdO"; //password is "user" encrypted using BCrypt
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.passwordEncoder(passwordEncoder())
.withUser("user").password(ENCODED_PASSWORD).roles("USER");
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
I've taken the code from user TwiN at Java Spring Security - User.withDefaultPasswordEncoder() is deprecated?
I have changed the hash to be "user" and have confirmed it's definitely "user" using https://bcrypt-generator.com/
but no matter what now, the login page won't allow me to login and says that my login details are incorrect
here's what my application looks like after entering a username="user" and password ="user"

there are a lot of methods to implement security in spring i can't follow what you are doing but here's my github repo Spring Boot Security you can shange the branches to see diffrent ways to apply security, select the branche "in memory" its the semplest one.

Add below properties in application.properties
spring.security.user.name = user
spring.security.user.password = user
spring.security.user.roles = USER
OR
Add these to the current SecurityConfig class
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)

Related

I've implemented the config class for the springBoot security but I dont have the generated password in the console, how can I access the log in?

I've tried to set the username and the password in the properties but didnt work
I'm trying to create a login and registration web app and I am stuck at this now
I was implementing the old way but it is deprecated so I saw this way, it is working but I cannot find a way to log in
package com.sample.security.config;
import com.sample.services.UserService;
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.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
#Configuration
#AllArgsConstructor
#EnableWebSecurity
public class WebSecurityConfig {
private final UserService userService;
private final BCryptPasswordEncoder bCryptPasswordEncoder;
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authenticationProvider(authenticationProvider())
.csrf()
.disable()
.authorizeRequests()
.antMatchers("/api/v*/registration**")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin();
return http.build();
}
#Bean
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userService);
authProvider.setPasswordEncoder(bCryptPasswordEncoder);
return authProvider;
}
}
The DaoAuthenticationProvider in your example is the default, and so does not need to be published as a #Bean or configured manually as you have done with .authenticationProvider(...). If you want to use the BCryptPasswordEncoder instead of DelegatingPasswordEncoder, you can publish it as an #Bean and it will be picked up automatically, like so:
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
Take a look at samples like our Username and Password sample for a minimal example of a basic Spring Security application that you can build from.

Error with using basic spring boot authentication

I am going through a spring security tutorial where I am trying to configure a basic security using the spring-boot-starter-security using the class like below
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.NoOpPasswordEncoder;
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/","/api/*").permitAll()
.anyRequest().authenticated().and().formLogin().loginPage("/login").permitAll()
.and().logout().permitAll();
}
#Autowired
public void ConfigureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().passwordEncoder(NoOpPasswordEncoder.getInstance())
.withUser("user").password("password").roles("USER");
}
}
But when I try to use the page localhost:8080 or localhost:8080/api/hello?name=test, it's not asking for login and directly showing the requested page. please help me with the issue.
Code allows access without authentication for / and /api/*
http.authorizeRequests().antMatchers("/","/api/*").permitAll()
It restricts access without authentication to any requests which are not matched with above url
.anyRequest().authenticated()

How to implement security in a spring boot application?

I'm creating a spring application for a college project and need help implementing a login page
package com.sales.security;
import org.springframework.context.annotation.Bean;
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.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
#Configuration
#EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter{
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/showProducts.html", "/showOrders.html", "/showCustomers.html","/newOrder.html","/addProduct.html","/addCustomer.html")
.authenticated()
.and()
.formLogin();
}
private static final String ENCODED_PASSWORD = "$2y$12$i4Cl5SZgrPFItSz/G5cvTObf0sqzHszwwKMZ4pQeUlElY1BR7KxdO"; //password is "user" encrypted using BCrypt
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.passwordEncoder(passwordEncoder())
.withUser("user").password(ENCODED_PASSWORD).roles("USER");
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
I've taken the code from user TwiN at Java Spring Security - User.withDefaultPasswordEncoder() is deprecated?
I have changed the hash to be "user" and have confirmed it's definitely "user" using https://bcrypt-generator.com/
but no matter what now, the login page won't allow me to login and says that my login details are incorrect
here's what my application looks like after entering a username="user" and password ="user"
You are encoding an already encoded password. Try something like this:
#EnableWebSecurity
public class WebConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
BCryptPasswordEncoder encoder = passwordEncoder();
auth.inMemoryAuthentication().withUser("user").password(encoder.encode("password")).roles("USER");
}
#Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
please check your encrypted password again, it seem's your password didn't encrypted correctly.
I managed to fix it.
package com.sales.security;
import org.springframework.context.annotation.Bean;
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.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Bean
public PasswordEncoder getPasswordEncoder() {
return NoOpPasswordEncoder.getInstance();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("user")
.password("user")
.roles("USER");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/showCustomers.html","/showProducts.html","/showOrders.html","/addCustomer.html","/newOrder.html","/addProduct.html").hasAnyRole("USER")
.and()
.formLogin()
.and()
.logout();
}
}

Spring Security Authentication issue: HTTP 401

I've encountered a bizarre situation using spring security. Having used:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
</parent>
With following simple security configuration:
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.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
UserDetails user = User.builder().username("1").password("1").roles("USER").build();
auth.inMemoryAuthentication().withUser(user).passwordEncoder(new BCryptPasswordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests().antMatchers("/inquiry").authenticated().anyRequest().permitAll().and()
.httpBasic();
}
}
I constantly get the 401 Http Status code. But I dig deeper into the code and I've realized that in the spring security core there is a minor issue.
The class DaoAuthenticationProvider tries to check if the provided password matches the actual credential with password encoder(in my case BCrypt) in hand. So
if (!passwordEncoder.matches(presentedPassword, userDetails.getPassword()))
But in the encoder, the method signature of matches is:
public boolean matches(CharSequence rawPassword, String encodedPassword)
So the authentication fails.
When you use in-memory authentication with BCrypt in your security configuration, you need to encrypt the password string first.
So you can try
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// First encrypt the password string
String encodedPassword = passwordEncoder().encode("1");
// Set the password
UserDetails user = User.builder()
.username("1")
.password(encodedPassword)
.roles("USER")
.build();
// Use in-memory authentication with BCryptEncoder
auth.inMemoryAuthentication()
.withUser(user)
.passwordEncoder(passwordEncoder());
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}

Spring Security with JSON does not work

I'm brand new to spring and I'm trying to figure out how to authenticate a user.
Currently, it looks like everything is set up correctly. When I use x-www-form-urlencoded, I can successfully log in. When using application/json, my application does not receive the emailAddress parameter.
I have been googling and checking SO, but I can't find anything related.
Here is my SecurityConfig.
package com.myapp.config;
import com.myapp.security.RestAuthenticationEntryPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
import org.springframework.web.bind.annotation.RestController;
#EnableWebSecurity
#Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
#Qualifier("customUserDetailsService")
private UserDetailsService userDetailsService;
#Autowired
private RestAuthenticationEntryPoint restAuthenticationEntryPoint;
#Autowired
public void configure(AuthenticationManagerBuilder builder) throws Exception {
builder.userDetailsService(userDetailsService);
builder.authenticationProvider(this.authenticationProvider());
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
public DaoAuthenticationProvider authenticationProvider() {
DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
authenticationProvider.setUserDetailsService(userDetailsService);
authenticationProvider.setPasswordEncoder(passwordEncoder());
return authenticationProvider;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.csrf().disable()
.exceptionHandling()
.authenticationEntryPoint(restAuthenticationEntryPoint)
.and()
.authorizeRequests()
.antMatchers("/").authenticated()
.and()
.formLogin().loginPage("/login").usernameParameter("emailAddress").passwordParameter("password")
.successHandler(new SimpleUrlAuthenticationSuccessHandler())
.failureHandler(new SimpleUrlAuthenticationFailureHandler())
.and()
.logout();
}
}
formLogin().loginPage("/login").usernameParameter("emailAddress").passwordParameter("password")
.successHandler(new SimpleUrlAuthenticationSuccessHandler())
.failureHandler(new SimpleUrlAuthenticationFailureHandler())
In the above configure, a standard UsernamePasswordAuthenticationFilter is used to obtain username and password from request parameter. However, the standard filter do not parse parameters from your json string in the request.
You may try to create a custom UsernamePasswordAuthenticationFilter to obtain username and password from the your json string and apply your custom filter in configuration. However, unlike XML configuration that can use <custom-filter position="FORM_LOGIN_FILTER" ref="yourCustomFilter" />, you cannot replace the form login filter with your custom filter by Java Config.
As a workaround, you can try with follows:
Create a custom filter extends AbstractAuthenticationProcessingFilter to obtain the username and password from json string and put the parsed parameters into the request. The solution is to use HttpRequestWrapper class, which allow you to wrap one request with another. You can subclass that, and override the getParameter to return username and password which is parsed from json string. You can then pass the wrapped request to chain.doFilter.
Add the custom filter before the standard UsernamePasswordAuthenticationFilter with HttpSecurity#addFilterBefore(yourCustomFilter, UsernamePasswordAuthenticationFilter.class)
As the username and password is parsed from json string to the request parameter, the standard UsernamePasswordAuthenticationFilter should be able to perform authentication.

Categories

Resources