refactor(auth): centralise cookie building
- Move cookie construction logic into CookieManager - Remove CookieService
This commit is contained in:
5 files changed
+89
-93
No files matched your search
@@ -2,11 +2,8 @@ package com.onixbyte.deltaforceguide.controller;
|
||||
|
||||
import com.onixbyte.deltaforceguide.domain.dto.LoginRequest;
|
||||
import com.onixbyte.deltaforceguide.domain.dto.UserResponse;
|
||||
import com.onixbyte.deltaforceguide.client.TokenClient;
|
||||
import com.onixbyte.deltaforceguide.security.annotation.RequiresAuth;
|
||||
import com.onixbyte.deltaforceguide.service.AuthService;
|
||||
import com.onixbyte.deltaforceguide.service.CookieService;
|
||||
import com.onixbyte.deltaforceguide.shared.CookieName;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
@@ -17,9 +14,6 @@ import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* REST controller for user authentication endpoints (login, logout).
|
||||
*
|
||||
@@ -31,34 +25,23 @@ import java.time.LocalDateTime;
|
||||
public class AuthController {
|
||||
|
||||
private final AuthService authService;
|
||||
private final TokenClient tokenClient;
|
||||
private final CookieService cookieService;
|
||||
|
||||
public AuthController(AuthService authService, TokenClient tokenClient, CookieService cookieService) {
|
||||
public AuthController(AuthService authService) {
|
||||
this.authService = authService;
|
||||
this.tokenClient = tokenClient;
|
||||
this.cookieService = cookieService;
|
||||
}
|
||||
|
||||
@Operation(description = "用户登录")
|
||||
@PostMapping("/login")
|
||||
public ResponseEntity<UserResponse> login(@Validated @RequestBody LoginRequest request) {
|
||||
var user = authService.login(request);
|
||||
var currentTime = LocalDateTime.now();
|
||||
var accessToken = tokenClient.generateToken(user);
|
||||
var accessTokenCookie = cookieService.buildCookie(CookieName.ACCESS_TOKEN, accessToken);
|
||||
var cookieMaxAge = accessTokenCookie.getMaxAge();
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.header(HttpHeaders.SET_COOKIE, accessTokenCookie.toString())
|
||||
.body(UserResponse.from(user, currentTime.plus(cookieMaxAge)));
|
||||
return authService.getUserResponseResponseEntity(user);
|
||||
}
|
||||
|
||||
@RequiresAuth
|
||||
@Operation(description = "退出登录")
|
||||
@PostMapping("/logout")
|
||||
public ResponseEntity<Void> logout() {
|
||||
var expiredCookie = cookieService.buildCookie(CookieName.ACCESS_TOKEN, "", Duration.ZERO);
|
||||
var expiredCookie = authService.logout();
|
||||
return ResponseEntity.noContent()
|
||||
.header(HttpHeaders.SET_COOKIE, expiredCookie.toString())
|
||||
.build();
|
||||
|
||||
@@ -3,10 +3,10 @@ package com.onixbyte.deltaforceguide.filter;
|
||||
import com.auth0.jwt.exceptions.JWTVerificationException;
|
||||
import com.onixbyte.deltaforceguide.client.TokenClient;
|
||||
import com.onixbyte.deltaforceguide.exeption.UnauthorisedException;
|
||||
import com.onixbyte.deltaforceguide.manager.CookieManager;
|
||||
import com.onixbyte.deltaforceguide.manager.UserManager;
|
||||
import com.onixbyte.deltaforceguide.manager.UserRoleManager;
|
||||
import com.onixbyte.deltaforceguide.security.authentication.UsernamePasswordAuthentication;
|
||||
import com.onixbyte.deltaforceguide.service.CookieService;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.Cookie;
|
||||
@@ -45,20 +45,20 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
|
||||
private final UserManager userManager;
|
||||
private final UserRoleManager userRoleManager;
|
||||
private final TokenClient tokenClient;
|
||||
private final CookieService cookieService;
|
||||
private final CookieManager cookieManager;
|
||||
private final HandlerExceptionResolver handlerExceptionResolver;
|
||||
|
||||
public TokenAuthenticationFilter(
|
||||
UserManager userManager,
|
||||
UserRoleManager userRoleManager,
|
||||
TokenClient tokenClient,
|
||||
CookieService cookieService,
|
||||
CookieManager cookieManager,
|
||||
HandlerExceptionResolver handlerExceptionResolver
|
||||
) {
|
||||
this.userManager = userManager;
|
||||
this.userRoleManager = userRoleManager;
|
||||
this.tokenClient = tokenClient;
|
||||
this.cookieService = cookieService;
|
||||
this.cookieManager = cookieManager;
|
||||
this.handlerExceptionResolver = handlerExceptionResolver;
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
|
||||
|
||||
if (shouldRenew(decodedToken.getExpiresAt().toInstant())) {
|
||||
var renewedToken = tokenClient.generateToken(user);
|
||||
var renewedTokenCookie = cookieService.buildCookie("AccessToken", renewedToken);
|
||||
var renewedTokenCookie = cookieManager.buildCookie("AccessToken", renewedToken);
|
||||
response.addHeader(HttpHeaders.SET_COOKIE, renewedTokenCookie.toString());
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.onixbyte.deltaforceguide.manager;
|
||||
|
||||
import com.onixbyte.deltaforceguide.properties.CookieProperties;
|
||||
import org.springframework.boot.web.server.Cookie;
|
||||
import org.springframework.http.ResponseCookie;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Duration;
|
||||
@@ -39,4 +40,49 @@ public class CookieManager {
|
||||
public Duration getMaxAge() {
|
||||
return cookieProperties.maxAge();
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a response cookie with the default max age from configuration.
|
||||
*
|
||||
* @param cookieName the cookie name
|
||||
* @param value the cookie value
|
||||
* @return a configured ResponseCookie
|
||||
*/
|
||||
public ResponseCookie buildCookie(String cookieName, String value) {
|
||||
return buildCookieInternal(cookieName, value, getMaxAge());
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a response cookie with a custom valid duration.
|
||||
*
|
||||
* @param cookieName the cookie name
|
||||
* @param value the cookie value
|
||||
* @param validDuration the cookie's max age
|
||||
* @return a configured ResponseCookie
|
||||
*/
|
||||
public ResponseCookie buildCookie(String cookieName, String value, Duration validDuration) {
|
||||
return buildCookieInternal(cookieName, value, validDuration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a response cookie builder with specified name, value and valid duration.
|
||||
*
|
||||
* @param name name of the cookie
|
||||
* @param value value of the cookie
|
||||
* @param maxAge valid duration of the cookie
|
||||
* @return cookie builder
|
||||
*/
|
||||
protected ResponseCookie buildCookieInternal(
|
||||
String name,
|
||||
String value,
|
||||
Duration maxAge
|
||||
) {
|
||||
return ResponseCookie.from(name, value)
|
||||
.secure(getSecure())
|
||||
.maxAge(maxAge)
|
||||
.httpOnly(getHttpOnly())
|
||||
.path(getPath())
|
||||
.sameSite(getSameSite().attributeValue())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,25 @@
|
||||
package com.onixbyte.deltaforceguide.service;
|
||||
|
||||
import com.onixbyte.deltaforceguide.client.TokenClient;
|
||||
import com.onixbyte.deltaforceguide.domain.dto.LoginRequest;
|
||||
import com.onixbyte.deltaforceguide.domain.dto.UserResponse;
|
||||
import com.onixbyte.deltaforceguide.domain.entity.User;
|
||||
import com.onixbyte.deltaforceguide.exeption.InternalServerErrorException;
|
||||
import com.onixbyte.deltaforceguide.manager.CookieManager;
|
||||
import com.onixbyte.deltaforceguide.security.authentication.UsernamePasswordAuthentication;
|
||||
import com.onixbyte.deltaforceguide.shared.CookieName;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpCookie;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* Service handling user authentication, login, and session management.
|
||||
*
|
||||
@@ -19,9 +30,17 @@ public class AuthService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(AuthService.class);
|
||||
private final AuthenticationManager authenticationManager;
|
||||
private final TokenClient tokenClient;
|
||||
private final CookieManager cookieManager;
|
||||
|
||||
public AuthService(AuthenticationManager authenticationManager) {
|
||||
public AuthService(
|
||||
AuthenticationManager authenticationManager,
|
||||
TokenClient tokenClient,
|
||||
CookieManager cookieManager
|
||||
) {
|
||||
this.authenticationManager = authenticationManager;
|
||||
this.tokenClient = tokenClient;
|
||||
this.cookieManager = cookieManager;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -47,4 +66,19 @@ public class AuthService {
|
||||
return authentication.getDetails();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public ResponseEntity<UserResponse> getUserResponseResponseEntity(User user) {
|
||||
var currentTime = LocalDateTime.now();
|
||||
var accessToken = tokenClient.generateToken(user);
|
||||
var accessTokenCookie = cookieManager.buildCookie(CookieName.ACCESS_TOKEN, accessToken);
|
||||
var cookieMaxAge = accessTokenCookie.getMaxAge();
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.header(HttpHeaders.SET_COOKIE, accessTokenCookie.toString())
|
||||
.body(UserResponse.from(user, currentTime.plus(cookieMaxAge)));
|
||||
}
|
||||
|
||||
public HttpCookie logout() {
|
||||
return cookieManager.buildCookie(CookieName.ACCESS_TOKEN, "", Duration.ZERO);
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
package com.onixbyte.deltaforceguide.service;
|
||||
|
||||
import com.onixbyte.deltaforceguide.manager.CookieManager;
|
||||
import org.springframework.http.ResponseCookie;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
/**
|
||||
* Service for building HTTP cookies with configurable properties.
|
||||
*
|
||||
* @author zihluwang
|
||||
*/
|
||||
@Service
|
||||
public class CookieService {
|
||||
|
||||
private final CookieManager cookieManager;
|
||||
|
||||
public CookieService(CookieManager cookieManager) {
|
||||
this.cookieManager = cookieManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a response cookie with the default max age from configuration.
|
||||
*
|
||||
* @param cookieName the cookie name
|
||||
* @param value the cookie value
|
||||
* @return a configured ResponseCookie
|
||||
*/
|
||||
public ResponseCookie buildCookie(String cookieName, String value) {
|
||||
return buildCookieInternal(cookieName, value, cookieManager.getMaxAge());
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a response cookie with a custom valid duration.
|
||||
*
|
||||
* @param cookieName the cookie name
|
||||
* @param value the cookie value
|
||||
* @param validDuration the cookie's max age
|
||||
* @return a configured ResponseCookie
|
||||
*/
|
||||
public ResponseCookie buildCookie(String cookieName, String value, Duration validDuration) {
|
||||
return buildCookieInternal(cookieName, value, validDuration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a response cookie builder with specified name, value and valid duration.
|
||||
*
|
||||
* @param name name of the cookie
|
||||
* @param value value of the cookie
|
||||
* @param maxAge valid duration of the cookie
|
||||
* @return cookie builder
|
||||
*/
|
||||
protected ResponseCookie buildCookieInternal(
|
||||
String name,
|
||||
String value,
|
||||
Duration maxAge
|
||||
) {
|
||||
return ResponseCookie.from(name, value)
|
||||
.secure(cookieManager.getSecure())
|
||||
.maxAge(maxAge)
|
||||
.httpOnly(cookieManager.getHttpOnly())
|
||||
.path(cookieManager.getPath())
|
||||
.sameSite(cookieManager.getSameSite().attributeValue())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user