Почему Principal вводит @Context null или неполный в мой ресурс JAX-RS /login?JAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Почему Principal вводит @Context null или неполный в мой ресурс JAX-RS /login?

Сообщение Anonymous »

Я разрабатываю приложение Jakarta EE, используя Open Liberty с JAX-RS для конечных точек RESTful и JWT для аутентификации. Я реализовал ContainerRequestFilter для проверки токенов JWT и установил собственный SecurityContext. Однако в моей конечной точке /login введенный участник либо неполный (getName() имеет значение null), либо выдает ошибку, хотя я правильно устанавливаю SecurityContext в своем фильтре.
JWT Фильтр аутентификации
@Provider
@Priority(Priorities.AUTHENTICATION)
public class JwtAuthenticationFilter implements ContainerRequestFilter {

private final static Set PUBLIC_PATHS = Set.of(
"/auth/register",
"/auth/login");

private IUserDAO userDAO;
private JWTService jwtService;

@Context
private SecurityContext securityContext;

public JwtAuthenticationFilter() {
}

@Inject
public JwtAuthenticationFilter(IUserDAO userDAO, JWTService jwtService) {
this.userDAO = userDAO;
this.jwtService = jwtService;
}

/**
* Checks the validity of JWT for every request that does not belong to the
* "Public paths".
* If there is no SecurityContext associated with current user, it creates one.
*/

@Override
public void filter(ContainerRequestContext containerRequestContext) throws IOException {
UriInfo uriInfo = containerRequestContext.getUriInfo();
System.out.println("JWT "+ containerRequestContext.getRequest());
// Check if the path is public
if (isPublicPath(uriInfo.getPath())) {
return;
}

// Extract the Authorization header
String authorizationHeader = containerRequestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) {
throw new NotAuthorizedException("Authorization Header does not exist, or is invalid.");
}

// Extract token
String token = authorizationHeader.substring("Bearer ".length()).trim();

try {
// Validate and extract subject (email)
String email = jwtService.extractSubject(token);

if (email != null) {
User user = userDAO.findUserByUserEmail(email).orElse(null);

// Validate token and set SecurityContext if valid
if (user != null && jwtService.isTokenValid(token, user)) {
containerRequestContext.setSecurityContext(new CustomSecurityContext(user));

System.out.println("SecurityContext set for user: " + containerRequestContext.getSecurityContext().getUserPrincipal().getName());

return;
} else {
throw new NotAuthorizedException("Invalid token.");
}
}
System.out.println("JWT Validated for user: " + email);
System.out.println("Setting SecurityContext for: " + email);

} catch (Exception e) {
throw new NotAuthorizedException("Invalid token.");
}
}

// Checks if a path belongs to public paths
private boolean isPublicPath(String path) {
System.out.println("Path: " + path);
return PUBLIC_PATHS.stream().anyMatch(path::startsWith);
}
}

Пользовательский контекст безопасности
@RequestScoped
@NoArgsConstructor
@AllArgsConstructor
public class CustomSecurityContext implements SecurityContext {

private User user;

@Override
public Principal getUserPrincipal() {
return user;
}

@Override
public boolean isUserInRole(String role) {
// Role-based checks not implemented
return false;
}

@Override
public boolean isSecure() {
return true; // Assume HTTPS is used
}

@Override
public String getAuthenticationScheme() {
return "Bearer";
}
}


Ресурс для входа
@POST
@Path("/login")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
public Response loginUser(UserLoginDTO userLoginDTO, @Context Principal principal) {
System.out.println(userLoginDTO.getEmail() + " " + userLoginDTO.getPassword() );

// Authentication
boolean isAuthenticated = authenticationProvider.authenticate(userLoginDTO);
if (!isAuthenticated) {
return Response.status(Response.Status.UNAUTHORIZED).build();
}
if (principal != null) {
String username = principal.getName();
if (userLoginDTO.getEmail().equals(username)) {
return Response.status(Response.Status.OK).entity("Already authenticated").build();
}
}

UserReadOnlyDTO userReadOnlyDTO = userService.findUserByEmail(userLoginDTO.getEmail());
String username = userReadOnlyDTO.getName();

// Create a JWT token for current user
String token = jwtService.generateToken(userLoginDTO.getEmail(), username);
AuthenticationResponseDTO authenticationResponseDTO = new AuthenticationResponseDTO(token);

return Response.status(Response.Status.OK).entity(authenticationResponseDTO).build();
}
}

Проблема
Для /auth/login, поскольку это общедоступный путь, JwtAuthenticationFilter пропускает настройку SecurityContext. Однако введенный объект Principal не равен нулю, а является неполным (getName() возвращает значение null), что приводит к запутанному поведению.
Если я проверю Principal.getName() != null в /login ресурса, я все еще сталкиваюсь со следующей ошибкой:
RESTEASY002005: Failed executing POST /auth/login
RESTEASY003880: Unable to find contextual data of type: java.security.Principal


Что мне здесь не хватает?
Заранее спасибо!
Добавление нулевых проверок в ресурс /login:if (principal == null || principal.getName() == null) {
System.out.println("Principal is null or name is null.");
}


Но все время происходит ошибка из-за одной и той же ошибки

RESTEASY002005: Не удалось выполнить POST /auth/login
RESTEASY003880: Не удалось найти контекстные данные типа: java.security.Principal


Подробнее здесь: https://stackoverflow.com/questions/792 ... rs-login-r
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»