Добавление сервера ресурсов в существующее приложение безопасности JSF / Spring - PullRequest
0 голосов
/ 13 декабря 2018

В настоящее время мы внедрили централизованный сервер авторизации с использованием протоколов oauth2.0 и потока паролей.Я опубликую user, pwd, secret и clientID на конечной точке сервера аутентификации, получу JWT и буду в пути.

В настоящее время в этом существующем «клиентском» приложении у меня есть образец весенней безопасности, которыйнастраивает трафик на основе ролей.

Что мне нужно сделать, это (я думаю) - Когда я войду в приложение, я получу токен.Этот токен хранится в сеансе, и всякий раз, когда я получаю доступ к странице в этом приложении, я либо подтверждаю, что токен по-прежнему исправен, либо обновляю токен, чтобы продолжить доступ к защищенному контенту.

Я предполагаю, что мне нужносделать следующее:

  1. Добавить сервер ресурсов в мое существующее приложение (@EnableResourceServer), чтобы трафик проходил через процесс oauth2.0.
  2. Настройте указанный сервер ресурсов (аналогичнов мой класс конфигурации WebSecurityConfigurerAdapter), чтобы токен был проверен
  3. Оставьте все остальное (роли, файловую структуру и т. д.) таким же

Как мне это сделать с помощью Spring?Я посмотрел учебные пособия, и большинство из них - это либо решения для домашнего ресурса, либо для сервера аутентификации, либо есть минимальное объяснение того, как что-то можно настроить.

Файл свойств:

security.oauth2.client.client-id= clientid
security.oauth2.client.client-secret= clientsecret
security.oauth2.client.access-token-uri= http://localhost:1234/oauth/token
security.oauth2.client.user-authorization-uri= http://localhost:1234/oauth/authorize

security.oauth2.resource.service-id=res_id
security.oauth2.resource.user-info-uri= http://localhost:1234/me
security.oauth2.resource.token-info-uri= http://localhost:1234/oauth/check_token
security.oauth2.resource.token-type= Bearer

Текущий WebSecurityConfigurerAdapter:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@ComponentScan("com.testproj")
public class CustomWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {

    @Autowired
    private CustomAuthenticationProvider authProvider;

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

        // Authentication control
        http
            .authorizeRequests()
            .antMatchers("/login.xhtml**").permitAll() // All everyone to see login page
            .antMatchers("/login").permitAll() // All everyone to see login page
            .antMatchers("/views/**").hasAnyAuthority("USER", "ADMIN")
            .antMatchers("/javax.faces.resource/**").permitAll() // All everyone to see resources
            .antMatchers("/resources/**").permitAll() // All everyone to see resources
            .anyRequest().authenticated(); // Ensure any request to application is authenticated

        // Login control
        http
            .formLogin()
                .loginPage("/login.xhtml")
                .loginProcessingUrl("/login")
                .successForwardUrl("/views/home.xhtml")
                .failureUrl("/login.xhtml?error=true");

        // not needed as JSF 2.2 is implicitly protected against CSRF
        http
            .csrf().disable();
    } 

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(authProvider);
    }   
} 

Пользовательский аутентификатор:

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private AppUserDAO appUserDAO;

    private String accessTokenUri = "http://localhost:1234/oauth/token";
    private String clientId = "clientid";
    private String clientSecret = "clientsecret";

    public AccessTokenProvider userAccessTokenProvider() {
        ResourceOwnerPasswordAccessTokenProvider accessTokenProvider = new ResourceOwnerPasswordAccessTokenProvider();
        return accessTokenProvider;
    }

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {

        final String username = authentication.getName();
        final String password = authentication.getCredentials().toString();

        List<String> scopes = new ArrayList<String>();
        scopes.add("read");

        final ResourceOwnerPasswordResourceDetails resource = new ResourceOwnerPasswordResourceDetails();

        resource.setUsername(username);
        resource.setPassword(password);
        resource.setAccessTokenUri(accessTokenUri);
        resource.setClientId(clientId);
        resource.setClientSecret(clientSecret);
        resource.setGrantType("password");
        resource.setScope(scopes);

        // Generate an access token
        final OAuth2RestTemplate template = new OAuth2RestTemplate(resource, new DefaultOAuth2ClientContext(new DefaultAccessTokenRequest()));
        template.setAccessTokenProvider(userAccessTokenProvider());

        OAuth2AccessToken accessToken = null;

        try {
            accessToken = template.getAccessToken();
            System.out.println("Grabbed access token from " + accessTokenUri);
        }
        catch (OAuth2AccessDeniedException e) {
            if (e.getCause() instanceof ResourceAccessException) {
                final String errorMessage = String.format(
                        "While authenticating user '%s': " + "Unable to access accessTokenUri '%s'.", username,
                        accessTokenUri);
                throw new AuthenticationServiceException(errorMessage, e);
            }
            throw new BadCredentialsException(String.format("Access denied for user '%s'.", username), e);
        }
        catch (OAuth2Exception e) {
            throw new AuthenticationServiceException(
                    String.format("Unable to perform OAuth authentication for user '%s'.", username), e);
        }

        // Determine roles for user
        List<GrantedAuthority> grantList = ...

        // Create custom user for the principal
        User user = .....

        UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user, null /*dont store password*/, grantList);

        return token;
    }

    @Override
    public  boolean supports(Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }
}

Сервер ресурсов:

@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
    ????
}

Редактировать :

Поэтому я переместил свойКонфигурация httpsecurity в конфигурацию моего сервера ресурсов, и я получаю сообщение «Отказано в доступе» при попытке перейти на страницу /views/home.xhtml.

В журнале указывается, что принципал является анонимным (в отличие отsecurityconfig)

Secure object: FilterInvocation: URL: /views/home.xhtml; Attributes: [#oauth2.throwOnError(hasAuthority('USER'))]
Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@fc4a062: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true;

Edit 2

Это может быть вопрос о том, что возможно с oauth2, потому что я немного схожу с ума.

В соответствии со спецификацией oauth существует 4 компонента - Auth-сервер, сервер ресурсов, клиент и владелец ресурса

Наверное, мой вопрос - могу ли я на самом деле объединить сервер ресурсов и клиент?Владелец ресурса будет входить в мое приложение (клиент), получать авторизацию от сервера авторизации для просмотра своих ресурсов на сервере / клиенте ресурсов.

Мне бы очень хотелось найти хороший пример этого - кажется, такокончательный и общий.

...