Add token checking at every http request.
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
package org.sportshub.application.configuration;
|
package org.sportshub.application.configuration;
|
||||||
|
|
||||||
|
import org.sportshub.application.security.JwtAuthenticationFilter;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
@@ -10,24 +11,25 @@ import org.springframework.security.config.annotation.web.configurers.AbstractHt
|
|||||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.security.web.SecurityFilterChain;
|
import org.springframework.security.web.SecurityFilterChain;
|
||||||
|
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||||
|
|
||||||
import static jakarta.servlet.DispatcherType.FORWARD;
|
import static jakarta.servlet.DispatcherType.FORWARD;
|
||||||
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
|
import static jakarta.servlet.http.HttpServletResponse.SC_FORBIDDEN;
|
||||||
import static jakarta.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
|
import static jakarta.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
|
||||||
import jakarta.servlet.DispatcherType;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableWebSecurity
|
@EnableWebSecurity
|
||||||
public class SecurityConfiguration {
|
public class SecurityConfiguration {
|
||||||
@Bean
|
@Bean
|
||||||
public SecurityFilterChain securityFilterChain(
|
public SecurityFilterChain securityFilterChain(
|
||||||
HttpSecurity httpSecurity
|
HttpSecurity httpSecurity,
|
||||||
|
JwtAuthenticationFilter jwtAuthenticationFilter
|
||||||
) throws Exception {
|
) throws Exception {
|
||||||
httpSecurity
|
httpSecurity
|
||||||
.csrf(AbstractHttpConfigurer::disable)
|
.csrf(AbstractHttpConfigurer::disable)
|
||||||
.httpBasic(Customizer.withDefaults())
|
.httpBasic(Customizer.withDefaults())
|
||||||
|
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
|
||||||
.authorizeHttpRequests(requests -> requests
|
.authorizeHttpRequests(requests -> requests
|
||||||
.dispatcherTypeMatchers(FORWARD).permitAll()
|
.dispatcherTypeMatchers(FORWARD).permitAll()
|
||||||
.requestMatchers(
|
.requestMatchers(
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package org.sportshub.application.security;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static org.springframework.http.HttpHeaders.AUTHORIZATION;
|
||||||
|
import static org.springframework.util.ObjectUtils.isEmpty;
|
||||||
|
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.stereotype.Component;
|
||||||
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
|
import jakarta.servlet.FilterChain;
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class JwtAuthenticationFilter extends OncePerRequestFilter {
|
||||||
|
private static final String BEARER_PREFIX = "Bearer ";
|
||||||
|
private final JwtService jwtService;
|
||||||
|
private final UserDetailsService userDetailsService;
|
||||||
|
|
||||||
|
public JwtAuthenticationFilter(JwtService jwtService, UserDetailsService userDetailsService) {
|
||||||
|
this.jwtService = jwtService;
|
||||||
|
this.userDetailsService = userDetailsService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doFilterInternal(
|
||||||
|
HttpServletRequest request,
|
||||||
|
HttpServletResponse response,
|
||||||
|
FilterChain filterChain
|
||||||
|
) throws ServletException, IOException {
|
||||||
|
String authorizationHeader = request.getHeader(AUTHORIZATION);
|
||||||
|
|
||||||
|
if (!isEmpty(authorizationHeader) && authorizationHeader.startsWith(BEARER_PREFIX)) {
|
||||||
|
String token = authorizationHeader.substring(BEARER_PREFIX.length());
|
||||||
|
String username = jwtService.extractUsername(token);
|
||||||
|
|
||||||
|
if (!isEmpty(username) && SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||||
|
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
|
||||||
|
if (jwtService.isValid(token) && userDetails.getUsername().equals(username)) {
|
||||||
|
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
|
||||||
|
userDetails,
|
||||||
|
null,
|
||||||
|
userDetails.getAuthorities()
|
||||||
|
);
|
||||||
|
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
filterChain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,14 +14,19 @@ import com.auth0.jwt.exceptions.JWTVerificationException;
|
|||||||
public class JwtService {
|
public class JwtService {
|
||||||
private final Algorithm algorithm;
|
private final Algorithm algorithm;
|
||||||
private final JWTVerifier jwtVerifier;
|
private final JWTVerifier jwtVerifier;
|
||||||
|
private final int tokenExpirationDelayInMinutes;
|
||||||
|
|
||||||
public JwtService(@Value("${application.security.secretKey}") String secretKey) {
|
public JwtService(
|
||||||
|
@Value("${application.security.secretKey}") String secretKey,
|
||||||
|
@Value("${application.security.tokenExpirationDelayInMinutes}") int tokenExpirationDelayInMinutes
|
||||||
|
) {
|
||||||
algorithm = Algorithm.HMAC512(secretKey);
|
algorithm = Algorithm.HMAC512(secretKey);
|
||||||
|
this.tokenExpirationDelayInMinutes = tokenExpirationDelayInMinutes;
|
||||||
jwtVerifier = JWT.require(algorithm).build();
|
jwtVerifier = JWT.require(algorithm).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String createJwt(User user) {
|
public String createJwt(User user) {
|
||||||
ZonedDateTime expirationDate = ZonedDateTime.now().plusMinutes(30);
|
ZonedDateTime expirationDate = ZonedDateTime.now().plusMinutes(tokenExpirationDelayInMinutes);
|
||||||
|
|
||||||
return JWT.create()
|
return JWT.create()
|
||||||
.withSubject(user.id().toString())
|
.withSubject(user.id().toString())
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
application:
|
application:
|
||||||
security:
|
security:
|
||||||
secretKey: "secret-key"
|
secretKey: "secret-key"
|
||||||
|
tokenExpirationDelayInMinutes: 30
|
||||||
|
|
||||||
logging:
|
logging:
|
||||||
level:
|
level:
|
||||||
|
|||||||
Reference in New Issue
Block a user