OAuth2 - @EnableResourceServer vs @ EnableOAuth2Sso
1. Visão geral
Neste tutorial, vamos falar sobre as anotações@EnableResourceServere@EnableOAuth2Sso no Spring Security.
Começaremos explicando odifferences between an OAuth2 Client and an OAuth2 Resource Server. Posteriormente, falaremos um pouco sobre o que essas anotações podem fazer por nós e demonstrar seu uso com um exemplo usandoZuule uma API simples.
Para o propósito deste artigo, vamos supor alguma experiência pré-existente comZuuleOAuth2.
Se você não tiver nenhum ou achar que uma revisão de qualquer um deles seria útil, consulte nossosquick overview on Zuule nossosguide to OAuth2.
2. Cliente e servidor de recursos OAuth2
Existem quatroroles diferentes no OAuth2 que precisamos considerar:
-
Resource Owner - uma entidade que pode conceder acesso aos seus recursos protegidos
-
Authorization Server - concede tokens de acesso aClients depois de autenticar com sucessoResourceOwners e obter sua autorização
-
Resource Server - um componente que requer um token de acesso para permitir, ou pelo menos considerar, o acesso aos seus recursos
-
Client - uma entidade que é capaz de obter tokens de acesso de servidores de autorização
Anotar nossa classe de configuração com@EnableResourceServer, ou@EnableOAuth2Sso, instrui o Spring a configurar os componentes que transformam nosso aplicativo em uma das duas últimas funções mencionadas acima.
The @EnableResourceServer annotation enables our application to behave as a Resource Server configurando umOAuth2AuthenticationProcessingFilter e outros componentes igualmente importantes.
Confira a aulaResourceServerSecurityConfigurer para ter uma ideia melhor do que está sendo configurado nos bastidores.
Por outro lado,the @EnableOAuth2Sso annotation transforms our application into an OAuth2 client. Ele instrui o Spring a configurar umOAuth2ClientAuthenticationProcessingFilter, junto com outros componentes que nosso aplicativo precisa para ser capaz de obter tokens de acesso de um servidor de autorização.
Dê uma olhada na classeSsoSecurityConfigurer para mais detalhes sobre o que o Spring configura para nós.
A combinação dessas anotações com algumas propriedades nos permite colocar as coisas em funcionamento rapidamente. Vamos criar dois aplicativos diferentes para vê-los em ação e como eles podem se complementar:
-
Nosso primeiro aplicativo será nosso nó de borda, um aplicativoZuul simples que usará a anotação@EnableOAuth2Sso. Ele será responsável por autenticar usuários (com a ajuda de umAuthorizationServer) e delegar solicitações de entrada para outros aplicativos
-
O segundo aplicativo usará a anotação@EnableResourceServer e permitirá o acesso a recursos protegidos se as solicitações de entrada contiverem um token de acesso OAuth2 válido
3. Zuul -@EnableOAuth2Sso
Vamos começar criando um aplicativoZuul que atuará como nosso nó de extremidade e será responsável por autenticar usuários usando um OAuth2AuthorizationServer:
@Configuration
@EnableZuulProxy
@EnableOAuth2Sso
@Order(value = 0)
public class AppConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private ResourceServerTokenServices
resourceServerTokenServices;
@Override
public void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/authorization-server-1/**",
"/login").permitAll()
.anyRequest().authenticated().and()
.logout().permitAll().logoutSuccessUrl("/");
}
}
Anotar nosso aplicativoZuul com@EnableOAuth2Sso também notifica o Spring para configurar um filtroOAuth2TokenRelayFilter. Esse filtro recupera tokens de acesso obtidos anteriormente das sessões HTTP dos usuários e os propaga a jusante.
Observe que também estamos usando a anotação@Order em nossa classe de configuraçãoAppConfiguration. Isso é para garantir queFilters criado por nossoWebSecurityConfigurerAdapter tenha precedência sobreFilters criado por outroWebSecurityConfigurerAdapters.
Por exemplo, poderíamos anotar nosso aplicativoZuul com@EnableResourceServer para oferecer suporte a identificadores de sessão HTTP e tokens de acesso OAuth2. No entanto, fazer isso cria novosFilters que, por padrão, têm precedência sobre os criados pela classeAppConfiguration. Isso acontece porqueResouceServerConfiguration, uma classe de configuração disparada por@EnableResourceServer, especifica umorder padrão de 3, enquantoWebSecurityConfigureAdapter tem umorder padrão de 100.
Antes de passarmos para o nossoResourceServer,, precisamos configurar algumas propriedades:
zuul:
routes:
resource-server-mvc-1: /resource-server-mvc-1/**
authorization-server-1:
sensitiveHeaders: Authorization
path: /authorization-server-1/**
stripPrefix: false
add-proxy-headers: true
security:
basic:
enabled: false
oauth2:
sso:
loginPath: /login
client:
accessTokenUri: http://localhost:8769/authorization-server-1/oauth/token
userAuthorizationUri: /authorization-server-1/oauth/authorize
clientId: fooClient
clientSecret: fooSecret
resource:
jwt:
keyValue: "abc"
id: fooScope
serviceId: ${PREFIX:}resource
Sem entrar em muitos detalhes, usando esta configuração, somos:
-
Configurando nossas rotasZuul e dizendo quais cabeçalhos devem ser adicionados / removidos antes de enviar solicitações para o downstream.
-
Definir algumas propriedades OAuth2 para que nosso aplicativo seja capaz de se comunicar com nossoAuthorizationServere configurarJWT com criptografiasymmetric.
4. API -@EnableResourceServer
Agora que temos nosso aplicativoZuul no lugar, vamos criar nossoResourceServer:
@SpringBootApplication
@EnableResourceServer
@Controller
@RequestMapping("/")
class ResourceServerApplication {
public static void main(String[] args) {
SpringApplication.run(ResourceServerApplication.class, args);
}
@RequestMapping(method = RequestMethod.GET)
@ResponseBody
public String helloWorld(Principal principal) {
return "Hello " + principal.getName();
}
}
É um aplicativo simples que expõe um único ponto de extremidade para retornarname dePrincipal que iniciou a solicitação.
Vamos encerrar configurando algumas propriedades:
security:
basic:
enabled: false
oauth2:
resource:
jwt:
keyValue: "abc"
id: fooScope
service-id: ${PREFIX:}resource
Lembre-se de quewe need a valid access token (que é armazenado na Sessão HTTP do usuário em nosso nó de extremidade)to access the endpoint of our Resource Server.
5. Conclusão
Neste artigo, explicamos as diferenças entre as anotações@EnableOAuth2Ssoe@EnableResourceServer. Também demonstramos como usá-los com um exemplo prático usandoZuule uma API simples.
A implementação completa deste exemplo pode ser encontradaover on Github.
Ao executar localmente, podemos executar e testar o aplicativo emhttp://192.168.1.67:8765/resource-server-mvc-1