Я создаю веб-приложение AngularJS, которое использует API RESTful (Джерси).Как правильно аутентифицировать клиента AngularJS на сервере
На стороне сервера я использую сервер приложений Java (подробно Glassfish 4).
Моя установка выглядит следующим образом:
- AngularJS WebApp развернут в качестве единого военного файла на сервер Java EE приложений.
- RESTfulAPI (и внутренняя логика) также развертывается в качестве военного файла на том же сервере приложений Java EE.
- Приложение AngularJS webapp вызывает API REST для получения необходимых ему данных.
- RESTful API:
/api/public/*
для общественности не ограниченного доступа (например,/API/общественности/пользователей/регистрации для регистрации в качестве нового пользователя). Любой пользователь имеет доступ к этой области. Нет Войти не требуется/api/private/*
для ограниченного доступа (например,/апи/частный/счет/{ID}, чтобы получить какой-то счет конкретных данных)
- Частные ресурсы защищены с понятиями внутренней безопасности Java EE (см для деталей web.xml).
web.xml
<security-constraint>
<web-resource-collection>
<web-resource-name>PRIVATE REST API</web-resource-name>
<url-pattern>/private/*</url-pattern>
<http-method>GET</http-method>
<http-method>POST</http-method>
<http-method>HEAD</http-method>
<http-method>PUT</http-method>
<http-method>OPTIONS</http-method>
<http-method>TRACE</http-method>
<http-method>DELETE</http-method>
</web-resource-collection>
<auth-constraint>
<description>Have to be a USER</description>
<role-name>USERS</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>userauth</realm-name>
</login-config>
<security-role>
<description/>
<role-name>USERS</role-name>
</security-role>
Эта установка работает для меня, но только если я призываю URL-адреса вручную в браузере. Если я не аутентифицирован и не адресую защищенную зону, браузер запрашивает имя пользователя и пароль. Если предоставленные полномочия действительны, я оттуда имею доступ к запрещенной зоне: Хорошо.
Но как мне получить эту работу с AngularJS? Для входа в систему есть вызов POST API: /api/public/users/login
, где вы должны предоставить учетные данные из формы (имя пользователя и пароль).
сторона код клиента:
ctrls.controller('LoginController', function($scope, $http, $log, $location, UserService, RemoteServerHelperService) {
$scope.loginDataWrong = undefined;
$scope.login = function(credentials) {
$http.post(RemoteServerHelperService.buildURL('/public/users/login'), credentials)
.success(function (data, status) {
UserService.setLoggedIn(credentials.email);
$scope.loginDataWrong = undefined;
$location.path('/app');
$log.info("login attempt: successfull. User.loggedIn:" + UserService.isLoggedIn());
}).error(function (data, status, headers, config) {
UserService.invalidate();
$scope.loginDataWrong = true;
$log.info("login attempt: failed. User.loggedIn:" + UserService.isLoggedIn());
});
};
});
Клиентская часть кода, кажется, работает. У меня также есть несколько путей для защиты контента на стороне клиента и т. Д. Есть несколько сообщений, которые подробно описывают код на стороне клиента. Поэтому этого «фрагмента» должно быть достаточно.
сторона код сервера:
@POST
@Path("/login")
@Consumes(MediaType.APPLICATION_JSON)
public Response login(Credentials credentials, @Context HttpServletRequest request) {
if (isAlreadyAuthenticated(request)) {
try {
request.logout();
} catch (ServletException ex) {
return Response.status(Status.CONFLICT).build();
}
}
// not authenticated
try {
request.login(credentials.getEmail(), credentials.getPassword());
return Response.ok().build();
} catch (ServletException ex) {
return Response.status(Status.CONFLICT).build();
}
}
Но тем не менее, это не «аутентификации» на стороне клиента для дальнейших запросов. Когда я делаю вызов API в ограниченной области после успешного входа в систему, я получаю ответ от со стороны сервера. Поэтому я предполагаю, что я делаю что-то неправильно. Есть ли у вас какие-либо идеи по аутентификации клиента на сервере для дальнейших запросов?
Возможное решение может заключаться в том, чтобы переключиться на аутентификацию на основе FORM и просто вызвать j_security_check с j_username и j_password, но на данный момент я хочу придерживаться BASIC-аутентификации и выполнять аутентификацию вручную через RESTful API.
Настройка $httpProvider.defaults.withCredentials = true;
как-то не имеет никакого эффекта.
Update:
Благодаря кончике lossleader я решил проблему. Я удалил метод login()
, потому что я хочу, чтобы Java EE-Server выполнял проверку подлинности.
Для доступа к защищенным областям веб-приложение AngularJS должно правильно установить HTTP-заголовок. В моем случае $http.defaults.headers.common['Authorization'] = 'Basic <username:pw>';
, где username:password
должен быть закодирован Base64.
После того, как я правильно установил заголовки, не отображается «Запрос пароля», и веб-приложение AngularJS может получить доступ к API REST.
Я не вижу, как запрос request.login() приведет к тому, что клиент получит HTTP-заголовки auth (правда, только ваш 200 возвращается?), В то время как request.authenticate() довольно четко работает с ответом и может поэтому установите заголовки. Я либо использовал бы аутентификацию, либо позволял браузеру выполнять свою работу или использовать формы. Если вы действительно хотите что-то посреди, я думаю, вам лучше посмотреть ответ и посмотреть, установлены ли какие-либо заголовки. – lossleader
Эй, спасибо, благодарю за ваш ответ. Конечно, вы правы, я не задавал заголовки правильно, и это, конечно, было моей проблемой. После вашего намека я получил аутентификацию для работы с аутентификацией на базе BASIC и FORM. – zip