Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: user authentication with httpBasic #3

Merged
merged 1 commit into from
Sep 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions shopping-cart-backend/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,12 @@
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>${spring-boot.version}</version>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
Expand Down
2 changes: 1 addition & 1 deletion shopping-cart-backend/shopping-cart.iml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<module version="4">
<component name="SonarLintModuleSettings">
<option name="uniqueId" value="f9191aba-e1f6-4c69-8236-d02c6617288d" />
<option name="uniqueId" value="042c3486-cc76-4a26-9870-da4929abf0f5" />
</component>
</module>
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ShoppingCartApplication {
public class Main {

public static void main(String[] args) {
SpringApplication.run(ShoppingCartApplication.class, args);
SpringApplication.run(Main.class, args);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package fptu.swp391.shoppingcart.authentication.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

@Configuration
public class PasswordEncoderConfig {
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package fptu.swp391.shoppingcart.authentication.config;

import fptu.swp391.shoppingcart.authentication.service.AuthenticationProviderService;
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.WebSecurityConfigurerAdapter;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AuthenticationProviderService authenticationProvider;

@Override
protected void configure(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(authenticationProvider);
}

@Override
protected void configure(HttpSecurity http) throws Exception {
//@formatter:off
http
.csrf().disable()
.authorizeRequests()
.mvcMatchers("/login").permitAll()
.anyRequest().authenticated()
.and().httpBasic();
// .and().formLogin();
//@formatter:on
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package fptu.swp391.shoppingcart.authentication.entity;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;

@Entity
@Getter
@Setter
@Table(name = "AUTHORITY")
public class Authority extends BaseEntity {
@Column(name = "NAME", nullable = false, length = 50)
private String name;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package fptu.swp391.shoppingcart.authentication.entity;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;

@Getter
@Setter
@MappedSuperclass
public abstract class BaseEntity {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "ID", nullable = false)
private Long id;

@Version
@Column(name = "VERSION", nullable = false)
private int version;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package fptu.swp391.shoppingcart.authentication.entity;

import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;
import java.io.Serializable;
import java.util.LinkedHashSet;
import java.util.Objects;
import java.util.Set;

@Entity
@Getter
@Setter
@Table(name = "USER")
public class UserEntity extends BaseEntity implements Serializable {

private static final long serialVersionUID = 1L;

@Column(name = "USERNAME", nullable = false, unique = true)
private String username;

@Column(name = "PASSWORD", nullable = false)
private String password;

@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "USER_ID")
private Set<Authority> authorities = new LinkedHashSet<>();

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

UserEntity that = (UserEntity) o;

if (!username.equals(that.username)) return false;
if (!password.equals(that.password)) return false;
return Objects.equals(authorities, that.authorities);
}

@Override
public int hashCode() {
int result = username.hashCode();
result = 31 * result + password.hashCode();
result = 31 * result + (authorities != null ? authorities.hashCode() : 0);
return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package fptu.swp391.shoppingcart.authentication.model;

import fptu.swp391.shoppingcart.authentication.entity.UserEntity;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Collection;
import java.util.stream.Collectors;

public class CustomUserDetails implements UserDetails{

private final UserEntity user;

public CustomUserDetails(UserEntity user) {
this.user = user;
}

@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return user.getAuthorities().stream()
.map(a -> new SimpleGrantedAuthority(a.getName()))
.collect(Collectors.toList());
}

@Override
public String getPassword() {
return user.getPassword();
}

@Override
public String getUsername() {
return user.getUsername();
}

@Override
public boolean isAccountNonExpired() {
return true;
}

@Override
public boolean isAccountNonLocked() {
return true;
}

@Override
public boolean isCredentialsNonExpired() {
return true;
}

@Override
public boolean isEnabled() {
return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package fptu.swp391.shoppingcart.authentication.repository;

import fptu.swp391.shoppingcart.authentication.entity.UserEntity;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Optional;

public interface UserRepository extends JpaRepository<UserEntity, Integer> {
Optional<UserEntity> findUserByUsername(String username);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package fptu.swp391.shoppingcart.authentication.service;

import fptu.swp391.shoppingcart.authentication.model.CustomUserDetails;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

@Service
public class AuthenticationProviderService implements AuthenticationProvider {
@Autowired
private JpaUserDetailsService userDetailsService;

@Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;

@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String username = authentication.getName();
String password = authentication.getCredentials().toString();

CustomUserDetails userDetails = userDetailsService.loadUserByUsername(username);

if (bCryptPasswordEncoder.matches(password, userDetails.getPassword())) {
return new UsernamePasswordAuthenticationToken(userDetails.getUsername(), userDetails.getPassword(), userDetails.getAuthorities());
}

throw new BadCredentialsException("Bad credentials");
}

@Override
public boolean supports(Class<?> authentication) {
return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package fptu.swp391.shoppingcart.authentication.service;

import fptu.swp391.shoppingcart.authentication.entity.UserEntity;
import fptu.swp391.shoppingcart.authentication.model.CustomUserDetails;
import fptu.swp391.shoppingcart.authentication.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.function.Supplier;

@Service
public class JpaUserDetailsService implements UserDetailsService {
@Autowired
private UserRepository userRepository;

@Override
public CustomUserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Supplier<UsernameNotFoundException> s =
() -> new UsernameNotFoundException("Problem during authentication!");

UserEntity u = userRepository.findUserByUsername(username).orElseThrow(s);

return new CustomUserDetails(u);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class ShoppingCartApplicationTests {
class MainTests {

@Test
void contextLoads() {
Expand Down