Я разрабатываю приложение 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
Почему Principal вводит @Context null или неполный в мой ресурс JAX-RS /login? ⇐ JAVA
Программисты JAVA общаются здесь
1734378360
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
Подробнее здесь: [url]https://stackoverflow.com/questions/79285902/why-is-principal-injected-with-context-null-or-incomplete-in-my-jax-rs-login-r[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия