add security
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
package com.billpaymentservice.bbps.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
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 com.billpaymentservice.bbps.entites.UsersDetails;
|
||||
import com.billpaymentservice.bbps.repository.UsersDetailsRepository;
|
||||
|
||||
@Service
|
||||
public class CustomUserDetailsService implements UserDetailsService {
|
||||
|
||||
@Autowired
|
||||
private UsersDetailsRepository userRepo;
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String userMobNo) throws UsernameNotFoundException {
|
||||
|
||||
String normalizedEmail = userMobNo;
|
||||
|
||||
Optional<UsersDetails> adminOptional = userRepo.findByUserMobNo(normalizedEmail);
|
||||
|
||||
if (adminOptional.isPresent()) {
|
||||
UsersDetails user = adminOptional.get();
|
||||
return new User(user.getUserEmailId(), user.getUserMobNo(), new ArrayList<>());
|
||||
} else {
|
||||
throw new UsernameNotFoundException("User not found with MobNo: " + userMobNo);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.billpaymentservice.bbps.config;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
@Component
|
||||
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
|
||||
|
||||
@Override
|
||||
public void commence(HttpServletRequest request, HttpServletResponse response,
|
||||
AuthenticationException authException) throws IOException, ServletException {
|
||||
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Access denied");
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.billpaymentservice.bbps.config;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
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.web.authentication.WebAuthenticationDetailsSource;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
import io.jsonwebtoken.ExpiredJwtException;
|
||||
import io.jsonwebtoken.MalformedJwtException;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
@Component
|
||||
public class JwtFilter extends OncePerRequestFilter {
|
||||
|
||||
@Autowired
|
||||
private JwtUtil jwtUtil;
|
||||
|
||||
@Autowired
|
||||
private CustomUserDetailsService userDetailsService;
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
|
||||
final String authorizationHeader = request.getHeader("Authentication");
|
||||
|
||||
String email = null;
|
||||
String jwt = null;
|
||||
|
||||
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
|
||||
jwt = authorizationHeader.substring(7);
|
||||
try {
|
||||
email = jwtUtil.extractUsername(jwt);
|
||||
} catch (IllegalArgumentException e) {
|
||||
System.out.println("unable to get jwt tokken");
|
||||
} catch (ExpiredJwtException e) {
|
||||
System.out.println("Jwt Exception jwt tokken");
|
||||
} catch (MalformedJwtException e) {
|
||||
System.out.println("invelid jwt token");
|
||||
}
|
||||
}
|
||||
|
||||
if (email != null && SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||
|
||||
UserDetails userDetails = this.userDetailsService.loadUserByUsername(email);
|
||||
|
||||
|
||||
if (jwtUtil.validateToken(jwt, userDetails)) {
|
||||
|
||||
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
|
||||
userDetails, null, userDetails.getAuthorities());
|
||||
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
|
||||
} else {
|
||||
System.out.println("JWT Filter: Token validation failed for user - " + email);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
package com.billpaymentservice.bbps.config;
|
||||
|
||||
import java.security.Key;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import io.jsonwebtoken.Claims;
|
||||
import io.jsonwebtoken.Jwts;
|
||||
import io.jsonwebtoken.SignatureAlgorithm;
|
||||
import io.jsonwebtoken.io.Decoders;
|
||||
import io.jsonwebtoken.security.Keys;
|
||||
|
||||
@Service
|
||||
public class JwtUtil {
|
||||
|
||||
@Value("${jwt.secret}")
|
||||
private String secret;
|
||||
|
||||
private Key getSigningKey() {
|
||||
byte[] keyBytes = Decoders.BASE64.decode(secret);
|
||||
return Keys.hmacShaKeyFor(keyBytes);
|
||||
}
|
||||
|
||||
// Access Token - 2 Hours
|
||||
private final long jwtExpirationInMs = 1000 * 60 * 60 * 2; // 2 hours
|
||||
|
||||
// Refresh Token - 7 Days
|
||||
private final long refreshExpirationDateInMs = 1000L * 60 * 60 * 24 * 7; // 7 days
|
||||
|
||||
private final Map<String, Date> tokenBlacklist = new HashMap<>();
|
||||
|
||||
public String doGenerateRefreshToken(Map<String, Object> claims, String subject) {
|
||||
return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))
|
||||
.setExpiration(new Date(System.currentTimeMillis() + refreshExpirationDateInMs))
|
||||
.signWith(getSigningKey(), SignatureAlgorithm.HS512).compact();
|
||||
}
|
||||
|
||||
public String extractUsername(String token) {
|
||||
return extractClaim(token, Claims::getSubject);
|
||||
}
|
||||
|
||||
public Date extractExpiration(String token) {
|
||||
return extractClaim(token, Claims::getExpiration);
|
||||
}
|
||||
|
||||
public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
|
||||
final Claims claims = extractAllClaims(token);
|
||||
return claimsResolver.apply(claims);
|
||||
}
|
||||
|
||||
private Claims extractAllClaims(String token) {
|
||||
return Jwts.parserBuilder().setSigningKey(getSigningKey()).build().parseClaimsJws(token).getBody();
|
||||
}
|
||||
|
||||
private Boolean isTokenExpired(String token) {
|
||||
return extractExpiration(token).before(new Date());
|
||||
}
|
||||
|
||||
public String generateToken(String username, String mid) {
|
||||
Map<String, Object> claims = new HashMap<>();
|
||||
claims.put("mid", mid);
|
||||
claims.put("expiryTime", new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10).toString());
|
||||
return createToken(claims, username.toUpperCase());
|
||||
}
|
||||
|
||||
private String createToken(Map<String, Object> claims, String subject) {
|
||||
return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))
|
||||
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10))
|
||||
.signWith(getSigningKey(), SignatureAlgorithm.HS512).compact();
|
||||
}
|
||||
|
||||
private String createToken1(String subject) {
|
||||
return Jwts.builder().setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))
|
||||
.setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10))
|
||||
.signWith(getSigningKey(), SignatureAlgorithm.HS512).compact();
|
||||
}
|
||||
|
||||
public Boolean validateToken(String token, UserDetails userDetails) {
|
||||
final String username = extractUsername(token);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void invalidateToken(String token) {
|
||||
tokenBlacklist.put(token, new Date());
|
||||
}
|
||||
|
||||
public boolean isTokenBlacklisted(String token) {
|
||||
Date invalidationTime = tokenBlacklist.get(token);
|
||||
return invalidationTime != null && invalidationTime.before(new Date());
|
||||
}
|
||||
|
||||
public String generateToken(String mobileNo) {
|
||||
return createToken1(mobileNo);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,16 +2,52 @@ package com.billpaymentservice.bbps.config;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.http.SessionCreationPolicy;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.CorsConfigurationSource;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
public class SecurityConfig {
|
||||
|
||||
@Autowired
|
||||
private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;
|
||||
|
||||
@Autowired
|
||||
private JwtFilter jwtFilter;
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
|
||||
|
||||
http.csrf(csrf -> csrf.disable()).cors(cors -> cors.configurationSource(corsConfigurationSource()))
|
||||
.authorizeHttpRequests(auth -> auth
|
||||
.requestMatchers("/masterData/**",
|
||||
"/v3/api-docs/**",
|
||||
"/swagger-ui/**",
|
||||
"/swagger-ui.html",
|
||||
"/swagger-resources/**",
|
||||
"/webjars/**",
|
||||
"/error")
|
||||
.permitAll().requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() // <-- Correct way
|
||||
.anyRequest().authenticated())
|
||||
.exceptionHandling(ex -> ex.authenticationEntryPoint(jwtAuthenticationEntryPoint))
|
||||
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
|
||||
|
||||
http.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
|
||||
|
||||
return http.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CorsConfigurationSource corsConfigurationSource() {
|
||||
CorsConfiguration config = new CorsConfiguration();
|
||||
|
||||
Reference in New Issue
Block a user