Рубрики
Без рубрики

Выход из защищенного приложения OAuth (с использованием устаревшего стека Spring Security OAuth)

Практическое глубокое погружение в то, как реализовать выход из системы в приложении Spring Security OAuth2 с помощью JWT, используя устаревший стек Spring Security OAuth.

Автор оригинала: baeldung.

1. Обзор

В этом кратком руководстве мы покажем, как мы можем добавить функцию выхода из системы в приложение безопасности OAuth Spring .

Мы, конечно, будем использовать приложение OAuth, описанное в предыдущей статье, – создание REST API с помощью OAuth2 .

Примечание : в этой статье используется устаревший проект Spring OAuth . Для версии этой статьи, использующей новый стек Spring Security 5, ознакомьтесь с нашей статьей Выход из защищенного приложения OAuth .

2. Удалите маркер доступа

Проще говоря, выход из системы в среде, защищенной OAuth, включает в себя вывод маркера доступа пользователя недействительным -поэтому он больше не может использоваться.

В реализации на основе JdbcTokenStore- это означает удаление токена из TokenStore .

Давайте реализуем операцию удаления для токена. Мы собираемся использовать здесь основную структуру /oauth/token URL и просто ввести для нее новую операцию УДАЛЕНИЯ.

Теперь, поскольку мы на самом деле используем /oauth/токен URI здесь – нам нужно обращаться с ним осторожно. Мы не сможем просто добавить это к любому контроллеру – потому что фреймворк уже имеет операции, сопоставленные с этим 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);
        }
    }
}

Обратите внимание, как мы извлекаем токен из запроса, просто используя стандартный заголовок Authorization .

3. Удалите маркер обновления

В предыдущей статье , посвященной Обработке маркера обновления , мы настроили наше приложение так, чтобы оно могло обновлять маркер доступа с помощью маркера обновления. Эта реализация использует прокси – сервер Zuul-с CustomPostZuulFilter для добавления значения refresh_token , полученного с Сервера авторизации, в файл cookie refreshToken .

При отмене маркера доступа, как показано в предыдущем разделе, связанный с ним маркер обновления также становится недействительным. Однако файл HttpOnly cookie останется установленным на клиенте, учитывая, что мы не можем удалить его с помощью JavaScript, поэтому нам нужно удалить его со стороны сервера.

Давайте улучшим реализацию CustomPostZuulFilter , которая перехватывает /oauth/token/revoke URL, чтобы удалить refreshToken cookie при обнаружении этого 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");
        }
    );
}

Эта функция будет вызвана при нажатии на ссылку Выход из системы :

5. Заключение

В этом быстром, но подробном уроке мы показали, как мы можем выйти из системы пользователя из OAuth защищенное приложение и аннулирует токены этого пользователя.

Полный исходный код примеров можно найти на GitHub .