JWT in Spring Security 6 with Database connection (without WebSecurityConfigurerAdapter)
JWT is an important concept in authenticating and authorizing access to an application. In a Java application, especially after migrating to Spring Security 6, you may need to create or update your security configurations without using WebSecurityConfigurerAdapter.
In this article, I will discuss the issue of JWT in a Java Maven project. I will be using Spring Security 6 and of course without the WebSecurityConfigurerAdapter.
I will use PostgreSQL as the database.
My IDE will be IntelliJ IDEA and you should have the basic understanding of Spring Boot Security to better benefit from this article.
I create my project at the start.spring.io:
1. Spring Security Dependency
And now I add firstly Spring Security dependency in the pom.xml file:
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>6.2.0</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>6.0.3</version>
</dependency>
I add the PostgreSQL configuration codes below to the application.propertiesfile:
spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
spring.datasource.username=postgres
spring.datasource.password=<your passsword here>
spring.datasource.driver-class-name=org.postgresql.Driver
spring.jpa.hibernate.ddl-auto=update
After that once you run the project, you can see a generated password in the console:
But we don’t need that as we will customize the security settings of the project.
领英推荐
2. Security Filter Chain
The security filter is the first thing a request goes through when you send an HTTP request to a server. Spring Security handles incoming requests under the security layer and ensures that these requests are authenticated and authorized. When using JWT, incoming requests are expected to contain JWT. These tokens are validated by Spring Security and if the validation is successful, the request is processed or rejected based on the user’s authorizations.
Now I add the SecurityConfigclass under the security package. The file looks like this:
@Configuration
@EnableWebSecurity
public class SecurityConfig {
public static final String ADMIN = "admin";
public static final String USER = "user";
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(
(authz) -> authz.requestMatchers("/api/some-path-here/**")
.permitAll()
.requestMatchers(HttpMethod.GET)
.permitAll()
.requestMatchers(HttpMethod.PUT)
.hasAuthority(USER)
.requestMatchers(HttpMethod.POST)
.permitAll()
.anyRequest()
.authenticated());
http.csrf(c -> c.disable());
return http.build();
}
}
@Configuration marks the class as a Spring Boot configuration class and with @EnableWebSecuritywe enable Spring Security’s web features.
I defined two roles, but they can differ according to your app’s needs.
By requestMatchersmethod allows you to allow or restrict paths within the application or http-method whichever you want, and to set permissions on them.
Project Structure
First, I want to add some classes and interfaces to the application that I can use to manage users and roles.
I add lombok to the pom.xml that provides less code:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
Now I create the controller, service, entities, dao, dto packages and associated classes under those packages.
I need two entities. One is for users another is for roles:
Under the package modelI add the class AppUser:
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
@Entity
@Table(name = "app_user")
public class AppUser implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column
private Integer id;
@Column(name = "username", columnDefinition = "text", unique = true)
private String username;
@Column(name = "password")
private String password;
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(name = "user_roles",
joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"))
private List<Role> roles = new ArrayList<>();
}
you can access the rest of this article at this link.
???IT Security Specialist || Cyber Security Analyst || Threat Hunter || Incident Responder || Information Security Manager || System Engineer || Life-Long Learner???
5 个月Good, inspiring...