连接 OAuth2 资源服务器和认证服务器
Posted
技术标签:
【中文标题】连接 OAuth2 资源服务器和认证服务器【英文标题】:Connecting OAuth2 resource server with authentication server 【发布时间】:2018-05-01 00:54:01 【问题描述】:我正在尝试制作一个示例 OAuth2 Spring 授权和资源服务器。我的意图是实现两个独立的应用程序——一个代表授权服务器,另一个代表资源服务器。由于我是 Spring Security 的初学者,我想我需要一些指导来完成我的任务。
我已经设法使用内存令牌存储(名为“OAuth”的应用程序)实现了一个简单的授权服务器。
AuthServerOAuth2Config.java
@Configuration
@EnableAuthorizationServer
public class AuthServerOAuth2Config extends AuthorizationServerConfigurerAdapter
private static final String RESOURCE_ID = "myResource";
@Autowired
private UserApprovalHandler handler;
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authManager;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception
// @formatter:off
clients.inMemory()
.withClient("test")
.authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
.authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
.scopes("read", "write", "trust")
.resourceIds(RESOURCE_ID)
.secret("test")
.accessTokenValiditySeconds(300).//invalid after 5 minutes.
refreshTokenValiditySeconds(600);//refresh after 10 minutes.
// @formatter:on
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception
endpoints.tokenStore(tokenStore()).userApprovalHandler(handler).authenticationManager(authManager);
@Bean
public TokenStore tokenStore()
return new InMemoryTokenStore();
OAuth2SecurityConfig.java
@Configuration
@EnableWebSecurity
public class OAuth2SecurityConfig extends WebSecurityConfigurerAdapter
private static final Logger LOG = LoggerFactory.getLogger(OAuth2SecurityConfig.class);
@Autowired
private ClientDetailsService clientService;
@Autowired
private DataSource dataSource;
@Autowired
public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception
// @formatter:off
auth.inMemoryAuthentication()
.withUser("javabycode").password("123456").roles("USER")
.and()
.withUser("admin").password("admin123").roles("ADMIN");
// @formatter:on
@Override
protected void configure(HttpSecurity http) throws Exception
// @formatter:off
http
.csrf().disable()
.anonymous().disable()
.authorizeRequests()
.antMatchers("/oauth/token").permitAll();
// @formatter:on
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception
return super.authenticationManagerBean();
@Bean
public TokenStore tokenStore()
return new JdbcTokenStore(dataSource);
@Bean
@Autowired
public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore)
TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler();
handler.setTokenStore(tokenStore);
handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientService));
handler.setClientDetailsService(clientService);
return handler;
@Bean
@Autowired
public ApprovalStore approvalStore(TokenStore tokenStore) throws Exception
TokenApprovalStore store = new TokenApprovalStore();
store.setTokenStore(tokenStore);
return store;
访问http://localhost:9081/OAuth/oauth/token?grant_type=password&username=admin&password=admin123
按预期返回令牌,所以我猜测授权服务器配置正常。
现在有一个资源服务器部分(名为“RestTest”的应用程序)。我设法找到了一些使用RemoteTokenServices
访问驻留在另一个应用程序中的令牌服务的示例。到目前为止,这是我的资源服务器。
OAuth2ResourceConfig.java
@Configuration
@EnableResourceServer
@EnableWebSecurity
public class OAuth2ResourceConfig extends ResourceServerConfigurerAdapter
private static final String RESOURCE_ID = "myResource";
private TokenExtractor tokenExtractor = new BearerTokenExtractor();
@Override
public void configure(HttpSecurity http) throws Exception
// @formatter:off
http.
anonymous().disable()
.requestMatchers().antMatchers("/v1/**")
.and().authorizeRequests()
.antMatchers("/v1/**").access("hasRole('ADMIN')")
.and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
// @formatter:on
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws
Exception
resources.tokenServices(tokenService()).resourceId(RESOURCE_ID).stateless(true);
@Primary
@Bean
public RemoteTokenServices tokenService()
RemoteTokenServices tokenService = new RemoteTokenServices();
tokenService.setCheckTokenEndpointUrl("http://localhost:9081/OAuth/oauth/check_token/");
tokenService.setClientId("test");
tokenService.setClientSecret("test");
return tokenService;
我正在尝试保护我的 REST API (http://localhost:9081/RestTest/v1/foobar
),所以我相信上面的配置是正确的,对吧?问题是当我访问v1/foobar
端点(通过邮递员)时,无需任何身份验证即可访问它。所以我认为我只是缺少配置的某些部分,但我无法弄清楚如何正确连接到授权服务器。还要提一件事 - 我没有使用 Spring Boot!
非常感谢一些指导以使我的示例工作。谢谢!
EDIT1:我已将 resourceId
添加到身份验证和资源服务器 - 不走运。 resourceId
是强制性的吗?
【问题讨论】:
【参考方案1】:您应该在ResourceServer
和AuthorizationServer
中都添加RESOURCE_ID
,方式是(尽管您使用那个sn-p 更新了您的问题)
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception
resources.tokenServices(tokenService()).resourceId(RESOURCE_ID).stateless(true);
在您的身份验证服务器中
.scopes("read", "write", "trust").resourceIds(RESOURCE_ID)
添加一个springSecurityFilterChain
,因为您在web.xml
中错过了您在评论中已经说过的内容
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
来自spring docs:
它创建一个称为 springSecurityFilterChain 的 Servlet 过滤器,它负责您应用程序中的所有安全性(保护应用程序 URL、验证提交的用户名和密码、重定向到登录表单等) .
【讨论】:
我如何在 Spring Boot 中进行相同的配置 你要配置哪个部分?过滤器? Filter .. 我正在实现 spring oauth2.0 并创建了 authserver,但在配置资源服务器时遇到了一些困难。 resourceserver 和 authserver 在不同的端口上。 @PiyushMittal,您可以提出另一个问题来描述您的问题。以上是关于连接 OAuth2 资源服务器和认证服务器的主要内容,如果未能解决你的问题,请参考以下文章
Oauth2 Spring Security 资源服务器和独立认证服务器