Spring Cloud Security 的 OAuth2 示例
下面我们通过一个基于 Spring Cloud Security 的 OAuth2 示例来演示 OAuth2 的工作流程。
添加依赖
在 pom.xml 文件中添加以下依赖:
代码语言:javascript复制<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
配置授权服务器
在授权服务器中,我们需要配置客户端信息、用户信息和端点信息等。下面是一个示例:
代码语言:javascript复制@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private ClientDetailsService clientDetailsService;
@Autowired
private TokenStore tokenStore;
@Autowired
private JwtAccessTokenConverter accessTokenConverter;
@Value("${jwt.clientId:client}")
private String clientId;
@Value("${jwt.client-secret:secret}")
private String clientSecret;
@Value("${jwt.accessTokenValidititySeconds:43200}") // 12 hours
private int accessTokenValiditySeconds;
@Value("${jwt.authorizedGrantTypes:password,refresh_token}")
private String[] authorizedGrantTypes;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient(clientId)
.secret(clientSecret)
.authorizedGrantTypes(authorizedGrantTypes)
.scopes("read", "write")
.accessTokenValiditySeconds(accessTokenValiditySeconds);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager)
.accessTokenConverter(accessTokenConverter)
.tokenStore(tokenStore)
.userDetailsService(userDetailsService);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey("123456");
return converter;
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
}
配置资源服务器
在资源服务器中,我们需要配置访问规则和访问令牌的校验规则等。下面是一个示例:
代码语言:javascript复制@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/api/**").authenticated()
.anyRequest().permitAll();
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId("resource");
}
}
在上面的代码中,我们将所有以 /api 开头的请求都设置为需要认证。此外,我们还将资源服务器的资源 ID 设置为 resource。
配置客户端
在客户端中,我们需要配置客户端 ID、客户端密钥、访问令牌 URL 和访问令牌校验 URL 等信息。下面是一个示例:
代码语言:javascript复制@Configuration
public class ClientConfig {
@Bean
public OAuth2RestTemplate oauth2RestTemplate(OAuth2ClientContext oauth2ClientContext) {
OAuth2ProtectedResourceDetails details = new ClientCredentialsResourceDetails();
details.setAccessTokenUri("http://localhost:8080/oauth/token");
details.setClientId("client");
details.setClientSecret("secret");
return new OAuth2RestTemplate(details, oauth2ClientContext);
}
}
在上面的代码中,我们使用 ClientCredentialsResourceDetails 类来配置客户端信息,并使用 OAuth2RestTemplate 类来发送请求和获取访问令牌。
测试 OAuth2
现在我们已经完成了 OAuth2 的配置,下面我们来测试一下它是否可以正常工作。
首先,我们需要使用用户名和密码获取授权码:
代码语言:javascript复制http://localhost:8080/oauth/authorize?response_type=code&client_id=client&redirect_uri=http://localhost:8081/login/oauth2/code/custom
然后,我们使用授权码获取访问令牌:
代码语言:javascript复制http://localhost:8080/oauth/token?grant_type=authorization_code&code=[code]&redirect_uri=http://localhost:8081/login/oauth2/code/custom&client_id=client&client_secret=secret
最后,我们使用访问令牌来请求受保护的资源:
代码语言:javascript复制curl -H "Authorization: Bearer [access_token]" http://localhost:8081/api/test
如果一切正常,我们应该可以看到请求成功返回了受保护的资源。