Как защитить приложение MVC с помощью OAuth2 с помощью Spring?

Извините мой английский.

У меня есть приложение, в которое я могу войти обычным способом.

@Configuration
@EnableWebSecurity
public class LoginSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        System.out.println("LoginSecurityConfig :: configure");

        auth.jdbcAuthentication().dataSource( getDataSource() )
            .passwordEncoder( new BCryptPasswordEncoder(16) )
            .usersByUsernameQuery(
                "select user_name as username,password,enabled from users where user_name=?")
            .authoritiesByUsernameQuery(
                "select user_name as username, role_name from users_roles ur join users u on ur.user_id = u.user_id and u.user_name = ?");

    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {


        http
        .csrf().disable()
        .authorizeRequests()
        .antMatchers("/login*").anonymous()
        .antMatchers("/resources/**").permitAll()
        .antMatchers("/fotos/**").permitAll()
        .antMatchers("/users").access("hasRole('ROLE_ADMIN')")
        .antMatchers("/user").access("hasRole('ROLE_ADMIN')")
        .anyRequest().authenticated()
        .and()

        .formLogin()
        .loginPage("/loginPage")
        .defaultSuccessUrl("/home", true)
        .failureUrl("/loginPage?error=true")
        .loginProcessingUrl("/login")
        .usernameParameter("username")
        .passwordParameter("password")
        .and()

        .logout()
        .logoutSuccessUrl("/loginPage")
        .invalidateHttpSession(true); 



    }    

}

Используя это, я могу попытаться получить доступ к любому защищенному ресурсу, и система отправляет меня в loginPage, где я могу отправить username и password на внутренний контроллер login, после чего у меня есть Principal и я могу получить доступ к защищенным ресурсам (дом, пользователи, пользователь). Работает нормально.

Но... Мне нужно удалить содержимое базы данных управления пользователями и использовать OAuth2, чтобы разрешить такой же доступ. Я больше не хочу иметь пользователей в своей базе данных. Мне нужен экран входа в систему, а затем запрос токена, например http://myserver/oauth/token?grant_type=password&username=admin&password=admin, передающий client_id и client_secret в Basic. Я знаю, как выполнить часть «получить токен», и мой сервер работает нормально и дает мне токен и токен обновления, но только с помощью Postman, потому что я понятия не имею, как использовать его в коде моего веб-приложения. Все учебники, которые я нашел, используют как сервер, так и клиент в одном приложении и фактически не показывают, как использовать удаленный сервер OAuth2.

Уже пытались использовать это. Это отличный учебник и очень близок к тому, что мне нужно, но слишком сложен для меня.

У меня есть этот код, и я понимаю, что он может использовать сервер и выдавать токен, используя учетные данные клиента, но не знаю, как предоставить пользователю экран входа в систему и использовать его учетные данные для выполнения запроса (часть GET).

@Configuration
@EnableResourceServer
public class OAuth2ResourceServerConfigRemoteTokenService extends ResourceServerConfigurerAdapter {

    @Override
    public void configure(final HttpSecurity http) throws Exception {
                http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
                    .and()
                    .authorizeRequests().anyRequest().permitAll();              
    }

    @Primary
    @Bean
    public RemoteTokenServices tokenServices() {
        final RemoteTokenServices tokenService = new RemoteTokenServices();
        tokenService.setCheckTokenEndpointUrl("http://myoauthserver/oauth/check_token");
        tokenService.setClientId("clientid");
        tokenService.setClientSecret("password");
        return tokenService;
    }

}

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

Или OAuth2 предназначен только для безопасного REST API?

введите здесь описание изображения

Пожалуйста, будьте дружелюбны к новичкам, потому что мне не очень удобно использовать Spring.


person Magno C    schedule 30.05.2018    source источник


Ответы (2)


Я сам недавно работал над этим, и я хотел бы сказать, что у меня есть простой ответ, но у меня его нет. Я должен был бы начать с вопросов, например, является ли это веб-приложением (JSP и т. д.) или REST API, используемым веб-приложением, или REST API, используемым мобильным приложением, и т. д. и т. д.

Причина, по которой это важно, заключается в том, что вам сначала нужно выбрать один из профилей OAuth2 и типов предоставления, и все они имеют разные требования и конфигурацию в Spring.

Кроме того, пытаетесь ли вы интегрироваться со сторонним поставщиком аутентификации OAuth2 (например, Facebook) или ваше приложение выступает как в качестве поставщика аутентификации (где происходит проверка логина и пароля), так и в качестве защищенного ресурса (куда отправляются запросы веб-страницы или вызовы API). к)?

Поэтому я думаю, что лучшее, что я могу сделать, это дать вам домашнее задание:

(1) Прочтите о различных профилях OAuth2 и определите, какой из них лучше всего подходит для вашего приложения, и изучите всю терминологию (например, что такое секрет клиента?).

Это определенно НЕ один из тех случаев, когда вы можете просто вырезать и вставить пример кода, не понимая его. Если у вас нет разумного понимания того, как работает OAuth2, у вас возникнут большие трудности.

Кроме того: здесь мы говорим о БЕЗОПАСНОСТИ, поэтому делать что-то без понимания — очень плохая идея. Если вы не будете осторожны, вы можете подумать, что это работает, но на самом деле вы оставляете себя открытым для атак.

(2) если вы не знакомы с Spring Framework Security, вам понадобятся базовые знания, чтобы понять, что вы делаете.

(3) Как только у вас появится идея, какой профиль вы будете использовать, используйте его в поиске Google, например. «Неявный грант Spring oauth2», чтобы найти пример, адаптированный для этого профиля.

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

Справочное руководство Spring также полезно, но не обязательно дает все подробности обо всех проблемах, с которыми вы можете столкнуться. Наконец, попробуйте реализовать с вашим приложением.

Вам понадобятся хорошие инструменты для отправки запросов в ваше приложение (мне нравится PostMan для этой цели), чтобы вы могли проверять данные, передаваемые туда и обратно. OAuth2 включает в себя сложную серию перенаправлений HTTP, поэтому тестирование может быть немного сложным.

Кроме того, будьте терпеливы. Я считаю себя экспертом по Spring, и мне потребовалось несколько дней, чтобы все заработало так, как я хотел. Обратите внимание, что на самом деле вы пишете ОЧЕНЬ МАЛЕНЬКОЕ количество кода, но очень сложно правильно написать небольшое количество кода.

person Community    schedule 02.06.2018
comment
У меня есть доверенная среда с некоторыми веб-приложениями, каждое из которых имеет свою собственную базу данных безопасности и методы входа в систему. Мне просто нужно централизовать всех пользователей и учетные данные в одном месте, чтобы все мои веб-приложения могли их использовать. Это военный набор приложений, и управлять одним и тем же пользователем в таком количестве сред — кошмар. Было бы неплохо иметь только одно место для подтверждения моих пользователей, прежде чем они войдут в какое-либо приложение, и он мог бы снова и снова переключаться между приложениями без входа в систему. - person Magno C; 02.06.2018

Просто как 1,2,3...

Просто немного измените мой сервер OAuth2, чтобы он принимал метод oauth/authorize.

@Override
protected void configure(HttpSecurity http) throws Exception {

    http
        .requestMatchers()
        .antMatchers("/login", "/oauth/authorize")
    .and()
        .authorizeRequests()
        .anyRequest()
        .authenticated()
    .and()
        .formLogin()
        .permitAll();       
}

и создайте пользовательскую форму входа. Теперь все клиенты (веб-приложения) могут войти в него.

Здесь вы можете найти образец клиента и более подробную информацию: http://www.baeldung.com/sso-spring-security-oauth2

Также вы можете проверить весь мой сервер и клиент в моем репозитории github:

https://github.com/icemagno/geoinfra/cerberus

а также

https://github.com/icemagno/geoinfra/atlas

It is in pt_BR

person Magno C    schedule 03.06.2018