1. Обзор
В этом кратком руководстве мы собираемся показать, как мы можем добавить функцию выхода из системы в приложение OAuth Spring Security .
Мы, конечно же, будем использовать приложение OAuth, описанное в предыдущей статье — Создание REST API с помощью OAuth2 .
Примечание . В этой статье используется устаревший проект Spring OAuth . Версию этой статьи, использующую новый стек Spring Security 5, можно найти в нашей статье Выход из защищенного приложения OAuth .
2. Удалите токен доступа
Проще говоря, выход из системы в защищенной OAuth среде приводит к тому, что токен доступа пользователя становится недействительным , поэтому его больше нельзя использовать.
В реализации на основе JdbcTokenStore
это означает удаление токена из TokenStore
.
Давайте реализуем операцию удаления для токена. Здесь мы будем использовать структуру URL-адреса parimary /oauth/token
и просто введем для нее новую операцию DELETE.
Теперь, поскольку мы на самом деле используем URI /oauth/token
здесь, нам нужно обращаться с ним осторожно. Мы не сможем просто добавить это к любому контроллеру — потому что в фреймворке уже есть операции, сопоставленные с этим URI — с POST и GET.
Вместо этого нам нужно определить, что это @FrameworkEndpoint
, чтобы он подхватывался и разрешался с помощью FrameworkEndpointHandlerMapping
вместо стандартного RequestMappingHandlerMapping
. Таким образом, мы не столкнемся с частичными совпадениями и у нас не будет конфликтов:
@FrameworkEndpoint
public class RevokeTokenEndpoint {
@Resource(name = "tokenServices")
ConsumerTokenServices tokenServices;
@RequestMapping(method = RequestMethod.DELETE, value = "/oauth/token")
@ResponseBody
public void revokeToken(HttpServletRequest request) {
String authorization = request.getHeader("Authorization");
if (authorization != null && authorization.contains("Bearer")){
String tokenId = authorization.substring("Bearer".length()+1);
tokenServices.revokeToken(tokenId);
}
}
}
Обратите внимание, как мы извлекаем токен из запроса, просто используя стандартный заголовок авторизации .
3. Удалите токен обновления
В предыдущей статье об обработке токена обновления мы настроили наше приложение так, чтобы оно могло обновлять токен доступа с помощью токена обновления. В этой реализации используется прокси-сервер Zuul с CustomPostZuulFilter
для добавления значения refresh_token
, полученного от сервера авторизации, в файл cookie refreshToken
.
При отзыве маркера доступа, как показано в предыдущем разделе, маркер обновления, связанный с ним, также становится недействительным. Однако файл cookie httpOnly
останется установленным на клиенте, учитывая, что мы не можем удалить его с помощью JavaScript, поэтому нам нужно удалить его на стороне сервера.
Давайте улучшим реализацию CustomPostZuulFilter
, которая перехватывает URL-адрес /oauth/token/revoke
, чтобы он удалял файл cookie refreshToken
при обнаружении этого URL-адреса:
@Component
public class CustomPostZuulFilter extends ZuulFilter {
//...
@Override
public Object run() {
//...
String requestMethod = ctx.getRequest().getMethod();
if (requestURI.contains("oauth/token") && requestMethod.equals("DELETE")) {
Cookie cookie = new Cookie("refreshToken", "");
cookie.setMaxAge(0);
cookie.setPath(ctx.getRequest().getContextPath() + "/oauth/token");
ctx.getResponse().addCookie(cookie);
}
//...
}
}
4. Удалите токен доступа из клиента AngularJS.
Помимо отзыва токена доступа из хранилища токенов, файл cookie access_token
также необходимо будет удалить со стороны клиента.
Давайте добавим в наш контроллер AngularJS метод, который очищает файл cookie
access_token
и вызывает сопоставление /oauth/token/revoke
DELETE:
$scope.logout = function() {
logout($scope.loginData);
}
function logout(params) {
var req = {
method: 'DELETE',
url: "oauth/token"
}
$http(req).then(
function(data){
$cookies.remove("access_token");
window.location.href="login";
},function(){
console.log("error");
}
);
}
Эта функция будет вызываться при нажатии на ссылку Выход :
<a class="btn btn-info" href="#" ng-click="logout()">Logout</a>
5. Вывод
В этом кратком, но подробном руководстве мы показали, как мы можем выйти из системы пользователя из защищенного приложения OAuth
и аннулировать токены этого пользователя.
Полный исходный код примеров можно найти на GitHub .