В последнее время я играл с AngularJS и Java EE 6. Я создал веб-сервис с Джерси и развернул проект на Glassfish. Поскольку мне нужна была какая-то аутентификация, а реализация OAuth или JDBCRealm казалась излишней, я решил просто создать сеанс, если пользователь успешно вошел в систему.
@POST
@Path("/login")
@Produces({MediaType.APPLICATION_JSON})
@Consumes({MediaType.APPLICATION_JSON})
public Response login(LoginDAO loginData, @Context HttpServletRequest req) {
req.getSession().invalidate();
loginData.setPassword(PasswordGenerator.hash(loginData.getPassword()));
User foundUser = database.login(loginData);
if(foundUser == null) {
return Response.status(Status.CONFLICT).build();
}
req.getSession(true).setAttribute("username", foundUser.getUsername());
return Response.ok().build();
}
@GET
@Path("/ping")
public Response ping(@Context HttpServletRequest req) {
if(req.getSession().getAttribute("username") == null) {
return Response.ok("no session with an username attribute has been set").build();
}
return Response.ok(req.getSession(true).getAttribute("username")).build();
}
Кажется, что все работает нормально, если я отправляю сообщение в/из Postman или с базовой веб-страницы jQuery, развернутой на стеклянной платке, я верну свое имя пользователя и сессия была помещена. Если я затем отправлю запрос GET в /ping, я получаю имя пользователя, с которого я вошел.
У меня есть приложение AngularJS, развернутое на веб-сервере node.js, которому необходимо войти в систему. Поскольку этот сервер находится на другом порту, он находится в другом домене, и мне пришлось пройти через боль от включения корса. Я сделал это, создав фильтр ответов контейнера, который устанавливает заголовки ответов.
public class CrossOriginResourceSharingFilter implements ContainerResponseFilter {
@Override
public ContainerResponse filter(ContainerRequest creq, ContainerResponse cresp) {
cresp.getHttpHeaders().putSingle("Access-Control-Allow-Origin", "http://localhost:8000");
cresp.getHttpHeaders().putSingle("Access-Control-Allow-Credentials", "true");
cresp.getHttpHeaders().putSingle("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
cresp.getHttpHeaders().putSingle("Access-Control-Allow-Headers", "Content-Type, Accept, X-Requested-With");
return cresp;
}
}
Это позволило мне отправить различные типы HTTP-запросов от приложения AngularJS к Java EE 6, развернутого на стеклянной платке.
Проблема заключается в том, что когда я отправляю запрос POST из AngularJS в метод /login, создается сеанс, и я возвращаю свое имя пользователя. Но когда я отправляю запрос GET методу /ping, я получаю уведомление об отсутствии "сеанса с атрибутом имени пользователя".
Я считаю, что это связано с предотвращением перекрестных доменов и что я должен установить тег withCredentials, когда я отправляю запрос xhr. Я пытался сделать это в AngularJS, но не узнал, как это сделать.
function LoginCtrl($scope, $http) {
$scope.login = function() {
$http.post("glassfish:otherport/api/login", $scope.credentials).
success(function(data) {
console.log(data);
}).
error(function(data, error) {
console.log(error);
});
};
};
И в другом контроллере:
$scope.getUsername = function() {
$http.get("glassfish:otherport/api/ping", {}).
success(function(data) {
$scope.username = data;
}).
error(function() {
$scope.username = "error";
})
}
Я попытался установить withCredentials, это правда
$http.defaults.withCredentials = true;
Это, однако, не решило мою проблему. Я также попытался отправить его с каждым запросом в параметре конфигурации, но это также не решило мою проблему.