admin管理员组文章数量:1125455
I am developing a Spring Boot application with spring-boot-starter-security and Thymeleaf. I need to implement JWT-based authentication and ensure the following:
The JWT should be stored in an HTTP-only cookie.
The session and cookies should be cleared upon logout.
A user should not have duplicate sessions (only one active session should be allowed). If the same user logs in from another browser or device, the previous session should be invalidated.
I am currently not using any external JWT libraries and am relying on Spring Security and custom code for JWT generation/validation. I have configured the logout functionality, but I need help with:
Preventing duplicate sessions.
Clearing JWT cookies and invalidating sessions on logout.
Security Configuration:
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/login", "/register").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").permitAll()
.and()
.logout().logoutUrl("/logout").logoutSuccessUrl("/login")
.addLogoutHandler((request, response, authentication) -> {
// Clear the JWT cookie
Cookie cookie = new Cookie("JWT", null);
cookie.setHttpOnly(true);
cookie.setPath("/");
cookie.setMaxAge(0); // Delete the cookie
response.addCookie(cookie);
})
.invalidateHttpSession(true)
.clearAuthentication(true)
.and()
.sessionManagement()
.maximumSessions(1) // Allow only one session per user
.expiredUrl("/login?expired=true") // Redirect if session is invalidated
.and()
.sessionFixation().newSession();
return http.build();
}
}
JWT Utility Class:
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;
public class JwtUtil {
private static final String SECRET_KEY = "your-256-bit-secret";
private static final String ALGORITHM = "HmacSHA256";
public String generateToken(String username) {
long now = System.currentTimeMillis();
long expiry = now + 3600000; // 1 hour
String header = Base64.getEncoder().encodeToString("{\"alg\":\"HS256\",\"typ\":\"JWT\"}".getBytes());
String payload = Base64.getEncoder().encodeToString(
("{\"sub\":\"" + username + "\",\"iat\":" + now + ",\"exp\":" + expiry + "}").getBytes()
);
String signature = createSignature(header + "." + payload);
return header + "." + payload + "." + signature;
}
public boolean validateToken(String token) {
try {
String[] parts = token.split("\\.");
String signature = createSignature(parts[0] + "." + parts[1]);
return signature.equals(parts[2]);
} catch (Exception e) {
return false;
}
}
private String createSignature(String data) {
try {
Mac mac = Mac.getInstance(ALGORITHM);
mac.init(new SecretKeySpec(SECRET_KEY.getBytes(), ALGORITHM));
return Base64.getEncoder().encodeToString(mac.doFinal(data.getBytes()));
} catch (Exception e) {
throw new RuntimeException("Error creating signature", e);
}
}
}
Login Controller:
@Controller
public class LoginController {
private final JwtUtil jwtUtil;
public LoginController(JwtUtil jwtUtil) {
this.jwtUtil = jwtUtil;
}
@GetMapping("/login")
public String loginPage() {
return "login";
}
@PostMapping("/login")
public String login(String username, String password, HttpServletResponse response, Model model) {
if ("user".equals(username) && "password".equals(password)) {
String token = jwtUtil.generateToken(username);
Cookie jwtCookie = new Cookie("JWT", token);
jwtCookie.setHttpOnly(true);
jwtCookie.setPath("/");
jwtCookie.setMaxAge(3600);
response.addCookie(jwtCookie);
return "redirect:/home";
}
model.addAttribute("error", "Invalid username or password");
return "login";
}
@GetMapping("/home")
public String home() {
return "home";
}
}
Thymeleaf Templates:
login.html:
<title>Login</title>
<h1>Login</h1>
<p th:if="${param.expired}" style="color:red;">Your session has expired due to login from another device.</p>
<form th:action="@{/login}" method="post">
<label for="username">Username:</label>
<input type="text" id="username" name="username" required><br>
<label for="password">Password:</label>
<input type="password" id="password" name="password" required><br>
<button type="submit">Login</button>
</form>
home.html:
<title>Home</title>
<h1>Welcome to Home Page</h1>
<form th:action="@{/logout}" method="post">
<button type="submit">Logout</button>
</form>
</htm l>
本文标签:
版权声明:本文标题:How to Implement JWT Authentication with Session Management and Prevent Duplicate Sessions in Spring Boot? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736668046a1946767.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论