0% found this document useful (0 votes)
4 views17 pages

TP - Code

The document outlines the steps to create a security system using Spring Boot, including the creation of entities for Role and User, repositories for data access, DTOs for data transfer, JWT security implementation, and controllers for authentication and testing. It provides detailed code snippets for each component, including configurations for Spring Security and JWT utilities. The final sections include the setup of authentication and authorization mechanisms through controllers and filters.

Uploaded by

ouhssainanouar
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views17 pages

TP - Code

The document outlines the steps to create a security system using Spring Boot, including the creation of entities for Role and User, repositories for data access, DTOs for data transfer, JWT security implementation, and controllers for authentication and testing. It provides detailed code snippets for each component, including configurations for Spring Security and JWT utilities. The final sections include the setup of authentication and authorization mechanisms through controllers and filters.

Uploaded by

ouhssainanouar
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 17

Étape 1 : Création des modèles (entités)

Création de l'entité Role

1. Créez un package `model` :


`src/main/java/com/example/securitytp/model`

2. Créez une classe `Role.java` dans ce package :

```java
package com.example.securitytp.model;

import javax.persistence.*;
import lombok.*;

@Entity
@Table(name = "roles")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Role {
​ @Id
​ @GeneratedValue(strategy = GenerationType.IDENTITY)
​ private Long id;

​ @Column(unique = true, nullable = false)


​ private String name;
}
```

Création de l'entité User


Créez une classe `User.java` dans le package `model` :

```java
package com.example.securitytp.model;

import javax.persistence.*;
import lombok.*;
import java.util.Set;

@Entity
@Table(name = "users")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
​ @Id
​ @GeneratedValue(strategy = GenerationType.IDENTITY)
​ private Long id;

​ @Column(unique = true, nullable = false)


​ private String username;

​ @Column(nullable = false)
​ private String password;

​ @ManyToMany(fetch = FetchType.EAGER)
​ @JoinTable(name = "user_roles",
​ joinColumns = @JoinColumn(name = "user_id"),
​ inverseJoinColumns = @JoinColumn(name = "role_id"))
​ private Set<Role> roles;
}
```
Étape 2 : Création des repositories

Création du RoleRepository

1. Créez un package `repository` :


`src/main/java/com/example/securitytp/repository`

2. Créez une interface `RoleRepository.java` :

```java
package com.example.securitytp.repository;

import com.example.securitytp.model.Role;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;

public interface RoleRepository extends JpaRepository<Role, Long> {


​ Optional<Role> findByName(String name);
}
```

Création du UserRepository

Créez une interface `UserRepository.java` :

```java
package com.example.securitytp.repository;

import com.example.securitytp.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;

public interface UserRepository extends JpaRepository<User, Long> {


​ Optional<User> findByUsername(String username);
}
```

Étape 3 : Création des DTOs (Data Transfer


Objects)

Création du LoginRequest

1. Créez un package `dto` : `src/main/java/com/example/securitytp/dto`

2. Créez une classe `LoginRequest.java` :

```java
package com.example.securitytp.dto;

import lombok.Data;
import javax.validation.constraints.NotBlank;

@Data
public class LoginRequest {
​ @NotBlank
​ private String username;

​ @NotBlank
​ private String password;
}
```

Création du JwtResponse

Créez une classe `JwtResponse.java` :

```java
package com.example.securitytp.dto;

import lombok.AllArgsConstructor;
import lombok.Data;
import java.util.Set;

@Data
@AllArgsConstructor
public class JwtResponse {
​ private String token;
​ private String type = "Bearer";
​ private Long id;
​ private String username;
​ private Set<String> roles;
}
```

Étape 4 : Implémentation de la sécurité JWT

Création de l'utilitaire JWT

1. Créez un package `security/jwt` :


`src/main/java/com/example/securitytp/security/jwt`

2. Créez une classe `JwtUtils.java` :

```java
package com.example.securitytp.security.jwt;

import io.jsonwebtoken.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

import java.util.Date;

@Component
public class JwtUtils {
​ private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class);

​ @Value("${jwt.secret}")
​ private String jwtSecret;

​ @Value("${jwt.expiration-in-ms}")
​ private int jwtExpirationMs;

​ public String generateJwtToken(Authentication authentication) {


​ UserDetails userPrincipal = (UserDetails) authentication.getPrincipal();

​ return Jwts.builder()
​ .setSubject(userPrincipal.getUsername())
​ .setIssuedAt(new Date())
​ .setExpiration(new Date((new Date()).getTime() + jwtExpirationMs))
​ .signWith(SignatureAlgorithm.HS512, jwtSecret)
​ .compact();
​ }

​ public String getUserNameFromJwtToken(String token) {


​ return
Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(token).getBody().getSubject();
​ }

​ public boolean validateJwtToken(String authToken) {


​ try {
​ Jwts.parser().setSigningKey(jwtSecret).parseClaimsJws(authToken);
​ return true;
​ } catch (SignatureException e) {
​ logger.error("Invalid JWT signature: {}", e.getMessage());
​ } catch (MalformedJwtException e) {
​ logger.error("Invalid JWT token: {}", e.getMessage());
​ } catch (ExpiredJwtException e) {
​ logger.error("JWT token is expired: {}", e.getMessage());
​ } catch (UnsupportedJwtException e) {
​ logger.error("JWT token is unsupported: {}", e.getMessage());
​ } catch (IllegalArgumentException e) {
​ logger.error("JWT claims string is empty: {}", e.getMessage());
​ }

​ return false;
​ }
}
```
Création du service UserDetails

1. Créez un package `security/service` :


`src/main/java/com/example/securitytp/security/service`

2. Créez une classe `UserDetailsImpl.java` :

```java
package com.example.securitytp.security.service;

import com.example.securitytp.model.User;
import com.fasterxml.jackson.annotation.JsonIgnore;
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.List;
import java.util.Objects;
import java.util.stream.Collectors;

public class UserDetailsImpl implements UserDetails {


​ private static final long serialVersionUID = 1L;

​ private Long id;


​ private String username;

​ @JsonIgnore
​ private String password;

​ private Collection<? extends GrantedAuthority> authorities;

​ public UserDetailsImpl(Long id, String username, String password,


​Collection<? extends GrantedAuthority> authorities) {
​ this.id = id;
​ this.username = username;
​ this.password = password;
​ this.authorities = authorities;
​ }

​ public static UserDetailsImpl build(User user) {


​ List<GrantedAuthority> authorities = user.getRoles().stream()
​ .map(role -> new SimpleGrantedAuthority(role.getName()))
​ .collect(Collectors.toList());
​ return new UserDetailsImpl(
​ user.getId(),
​ user.getUsername(),
​ user.getPassword(),
​ authorities);
​ }

​ public Long getId() {


​ return id;
​ }

​ @Override
​ public Collection<? extends GrantedAuthority> getAuthorities() {
​ return authorities;
​ }

​ @Override
​ public String getPassword() {
​ return password;
​ }

​ @Override
​ public String getUsername() {
​ return username;
​ }

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

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

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

​ @Override
​ public boolean isEnabled() {
​ return true;
​ }

​ @Override
​ public boolean equals(Object o) {
​ if (this == o) return true;
​ if (o == null || getClass() != o.getClass()) return false;
​ UserDetailsImpl user = (UserDetailsImpl) o;
​ return Objects.equals(id, user.id);
​ }
}
```

3. Créez une classe `UserDetailsServiceImpl.java` :

```java
package com.example.securitytp.security.service;

import com.example.securitytp.model.User;
import com.example.securitytp.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

​ @Override
​ @Transactional
​ public UserDetails loadUserByUsername(String username) throws
UsernameNotFoundException {
​ User user = userRepository.findByUsername(username)
​ .orElseThrow(() -> new UsernameNotFoundException("User Not Found with
username: " + username));

​ return UserDetailsImpl.build(user);
​ }
}
```
Création du filtre JWT

1. Créez un package `security/filter` :


`src/main/java/com/example/securitytp/security/filter`

2. Créez une classe `JwtAuthenticationFilter.java` :

```java
package com.example.securitytp.security.filter;

import com.example.securitytp.security.jwt.JwtUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

public class JwtAuthenticationFilter extends OncePerRequestFilter {


​ private static final Logger logger =
LoggerFactory.getLogger(JwtAuthenticationFilter.class);

​ @Autowired
​ private JwtUtils jwtUtils;

​ @Autowired
​ private UserDetailsService userDetailsService;

​ @Override
​ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse
response, FilterChain filterChain)
​ throws ServletException, IOException {
​ try {
​ String jwt = parseJwt(request);
​ if (jwt != null && jwtUtils.validateJwtToken(jwt)) {
​ String username = jwtUtils.getUserNameFromJwtToken(jwt);
​ UserDetails userDetails =
userDetailsService.loadUserByUsername(username);
​ UsernamePasswordAuthenticationToken authentication = new
UsernamePasswordAuthenticationToken(
​ userDetails, null, userDetails.getAuthorities());
​ authentication.setDetails(new
WebAuthenticationDetailsSource().buildDetails(request));

​ SecurityContextHolder.getContext().setAuthentication(authentication);
​ }
​ } catch (Exception e) {
​ logger.error("Cannot set user authentication: {}", e.getMessage());
​ }

​ filterChain.doFilter(request, response);
​ }

​ private String parseJwt(HttpServletRequest request) {


​ String headerAuth = request.getHeader("Authorization");

​ if (StringUtils.hasText(headerAuth) && headerAuth.startsWith("Bearer ")) {


​ return headerAuth.substring(7);
​ }

​ return null;
​ }
}
```

Configuration de Spring Security

Créez une classe `WebSecurityConfig.java` dans le package `security` :

```java
package com.example.securitytp.security;

import com.example.securitytp.security.filter.JwtAuthenticationFilter;
import com.example.securitytp.security.service.UserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import
org.springframework.security.config.annotation.authentication.builders.AuthenticationManag
erBuilder;
import
org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodS
ecurity;
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.WebSecurityConfigurerAd
apter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import
org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
​ @Autowired
​ UserDetailsServiceImpl userDetailsService;

​ @Bean
​ public JwtAuthenticationFilter authenticationJwtTokenFilter() {
​ return new JwtAuthenticationFilter();
​ }

​ @Override
​ public void configure(AuthenticationManagerBuilder authenticationManagerBuilder)
throws Exception {

authenticationManagerBuilder.userDetailsService(userDetailsService).passwordEncoder(pa
sswordEncoder());
​ }

​ @Bean
​ @Override
​ public AuthenticationManager authenticationManagerBean() throws Exception {
​ return super.authenticationManagerBean();
​ }

​ @Bean
​ public PasswordEncoder passwordEncoder() {
​ return new BCryptPasswordEncoder();
​ }

​ @Override
​ protected void configure(HttpSecurity http) throws Exception {
​ http.cors().and().csrf().disable()

.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
​ .authorizeRequests()
​ .antMatchers("/api/auth/**").permitAll()
​ .antMatchers("/h2-console/**").permitAll()
​ .antMatchers("/api/test/all").permitAll()
​ .antMatchers("/api/test/user").hasRole("USER")
​ .antMatchers("/api/test/admin").hasRole("ADMIN")
​ .anyRequest().authenticated();

​ // Fix for H2 console


​ http.headers().frameOptions().sameOrigin();

​ http.addFilterBefore(authenticationJwtTokenFilter(),
UsernamePasswordAuthenticationFilter.class);
​ }
}
```

Étape 5 : Création des contrôleurs

Contrôleur d'authentification

Créez un package `controller` :


`src/main/java/com/example/securitytp/controller`

Créez une classe `AuthController.java` :

```java
package com.example.securitytp.controller;

import com.example.securitytp.dto.JwtResponse;
import com.example.securitytp.dto.LoginRequest;
import com.example.securitytp.model.Role;
import com.example.securitytp.security.jwt.JwtUtils;
import com.example.securitytp.security.service.UserDetailsImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.Set;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/api/auth")
@CrossOrigin(origins = "*", maxAge = 3600)
public class AuthController {
​ @Autowired
​ private AuthenticationManager authenticationManager;

​ @Autowired
​ private JwtUtils jwtUtils;

​ @PostMapping("/login")
​ public ResponseEntity<?> authenticateUser(@Valid @RequestBody LoginRequest
loginRequest) {
​ Authentication authentication = authenticationManager.authenticate(
​ new UsernamePasswordAuthenticationToken(loginRequest.getUsername(),
loginRequest.getPassword()));

​ SecurityContextHolder.getContext().setAuthentication(authentication);
​ String jwt = jwtUtils.generateJwtToken(authentication);

​ UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();
​ Set<String> roles = userDetails.getAuthorities().stream()
​ .map(item -> item.getAuthority())
​ .collect(Collectors.toSet());

​ return ResponseEntity.ok(new JwtResponse(


​ jwt,
​ "Bearer",
​ userDetails.getId(),
​ userDetails.getUsername(),
​ roles));
​ }
}
```

Contrôleur de test

Créez une classe `TestController.java` :

```java
package com.example.securitytp.controller;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/test")
@CrossOrigin(origins = "*", maxAge = 3600)
public class TestController {

​ @GetMapping("/all")
​ public String allAccess() {
​ return "Public Content.";
​ }

​ @GetMapping("/user")
​ @PreAuthorize("hasRole('USER') or hasRole('ADMIN')")
​ public String userAccess() {
​ return "User Content.";
​ }

​ @GetMapping("/admin")
​ @PreAuthorize("hasRole('ADMIN')")
​ public String adminAccess() {
​ return "Admin Content.";
​ }
}
```
Étape 6 : Initialisation des données

Modifiez la classe principale `SecurityTpApplication.java` pour initialiser


des utilisateurs et des rôles :

```java
package com.example.securitytp;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.security.crypto.password.PasswordEncoder;

import com.example.securitytp.model.Role;
import com.example.securitytp.model.User;
import com.example.securitytp.repository.RoleRepository;
import com.example.securitytp.repository.UserRepository;

import java.util.Set;

@SpringBootApplication
public class SecurityTpApplication {
​ public static void main(String[] args) {
​ SpringApplication.run(SecurityTpApplication.class, args);
​ }

​ @Bean
​ CommandLineRunner init(RoleRepository roleRepo, UserRepository userRepo,
PasswordEncoder encoder) {
​ return args -> {
​ // Create roles if they don't exist
​ Role userRole = roleRepo.findByName("ROLE_USER")
​ .orElse(new Role(null, "ROLE_USER"));
​ Role adminRole = roleRepo.findByName("ROLE_ADMIN")
​ .orElse(new Role(null, "ROLE_ADMIN"));

​ roleRepo.save(userRole);
​ roleRepo.save(adminRole);

​ // Create test users if they don't exist
​ if (userRepo.findByUsername("user").isEmpty()) {
​ User user = new User(null, "user", encoder.encode("password"),
Set.of(userRole));
​ userRepo.save(user);
​ }

​ if (userRepo.findByUsername("admin").isEmpty()) {
​ User admin = new User(null, "admin", encoder.encode("adminpass"),
Set.of(adminRole));
​ userRepo.save(admin);
​ }
​ };
​ }
}
```

You might also like