By following these steps, you can implement a centralized authentication server with Spring Security and JWT to manage secure authentication and session management across your microservices architecture. This setup addresses common security challenges and enhances the overall security and scalability of your application.
1. Create the Spring Boot Application
Use Spring Initializr to create a Spring Boot project with the following dependencies:
2. Add Dependencies for JWT
Include the following dependency in your pom.xml
file:
xml
Copy <dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
3. Create the Security Configuration
java
Copy import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/public/**").permitAll()
.anyRequest().authenticated()
.and()
.addFilterBefore(new JwtAuthenticationFilter(jwtTokenUtil(), userDetailsService()),
UsernamePasswordAuthenticationFilter.class);
}
@Bean
public UserDetailsService userDetailsService() {
InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();
manager.createUser(User.withDefaultPasswordEncoder()
.username("user")
.password("password")
.roles("USER")
.build());
return manager;
}
@Bean
public JwtTokenUtil jwtTokenUtil() {
return new JwtTokenUtil();
}
}
4. Implement JWT Token Utility
java
Copy import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class JwtTokenUtil {
private static final String SECRET_KEY = "secret";
private static final long EXPIRATION_TIME = 86400000; // 24 hours
public String generateToken(String username) {
return Jwts.builder()
.setSubject(username)
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS512, SECRET_KEY)
.compact();
}
public String getUsernameFromToken(String token) {
Claims claims = Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody();
return claims.getSubject();
}
public boolean validateToken(String token) {
return getUsernameFromToken(token) != null && !isTokenExpired(token);
}
private boolean isTokenExpired(String token) {
Claims claims = Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody();
return claims.getExpiration().before(new Date());
}
}
5. Create JWT Authentication Filter
java
Copy 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.UsernamePasswordAuthenticationFilter;
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 UsernamePasswordAuthenticationFilter {
private JwtTokenUtil jwtTokenUtil;
private UserDetailsService userDetailsService;
public JwtAuthenticationFilter(JwtTokenUtil jwtTokenUtil, UserDetailsService userDetailsService) {
this.jwtTokenUtil = jwtTokenUtil;
this.userDetailsService = userDetailsService;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
throws IOException, ServletException {
String token = request.getHeader("Authorization");
if (token != null && jwtTokenUtil.validateToken(token)) {
String username = jwtTokenUtil.getUsernameFromToken(token);
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
if (userDetails != null) {
SecurityContextHolder.getContext().setAuthentication(
new JwtAuthenticationToken(userDetails, null, userDetails.getAuthorities())
);
}
}
chain.doFilter(request, response);
}
}
6. Secure Your Services
Use the JWT token to secure access to your microservices, ensuring that only authenticated users can access protected resources.