前几节主要介绍了什么是oauth2,以及spring security oauth2的简单用法。下面我们来看下oauth2的认证服务和资源服务它们是怎么配置的,流程又是什么样的,首先来看下认证服务。
使用方式:
1、添加注解@EnableAuthorizationServer
2、继承AuthorizationServerConfigurerAdapter
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfigurer extends AuthorizationServerConfigurerAdapter{
}
spring security oauth2的任务服务是通过注解@EnableAuthorizationServer引入的。该注解会导入AuthorizationServerSecurityConfiguration和AuthorizationServerEndpointsConfiguration两个配置类
AuthorizationServerEndpointsConfiguration:主要是配置了任务服务的一些端点请求。比如oauth/token、oauth/authorize、oauth/check_token、oauth/confirm_access、oauth/error等
@Configuration
@Import(TokenKeyEndpointRegistrar.class)
public class AuthorizationServerEndpointsConfiguration {
private AuthorizationServerEndpointsConfigurer endpoints = new AuthorizationServerEndpointsConfigurer();
@Autowired
private ClientDetailsService clientDetailsService;
@Autowired
private List<AuthorizationServerConfigurer> configurers = Collections.emptyList();
@PostConstruct
public void init() {
for (AuthorizationServerConfigurer configurer : configurers) {
try {
configurer.configure(endpoints);
} catch (Exception e) {
throw new IllegalStateException("Cannot configure enpdoints", e);
}
}
endpoints.setClientDetailsService(clientDetailsService);
}
//oauth/authorize
@Bean
public AuthorizationEndpoint authorizationEndpoint() throws Exception {
AuthorizationEndpoint authorizationEndpoint = new AuthorizationEndpoint();
FrameworkEndpointHandlerMapping mapping = getEndpointsConfigurer().getFrameworkEndpointHandlerMapping();
authorizationEndpoint.setUserApprovalPage(extractPath(mapping, "/oauth/confirm_access"));
authorizationEndpoint.setProviderExceptionHandler(exceptionTranslator());
authorizationEndpoint.setErrorPage(extractPath(mapping, "/oauth/error"));
authorizationEndpoint.setTokenGranter(tokenGranter());
authorizationEndpoint.setClientDetailsService(clientDetailsService);
authorizationEndpoint.setAuthorizationCodeServices(authorizationCodeServices());
authorizationEndpoint.setOAuth2RequestFactory(oauth2RequestFactory());
authorizationEndpoint.setOAuth2RequestValidator(oauth2RequestValidator());
authorizationEndpoint.setUserApprovalHandler(userApprovalHandler());
authorizationEndpoint.setRedirectResolver(redirectResolver());
return authorizationEndpoint;
}
//oauth/token
@Bean
public TokenEndpoint tokenEndpoint() throws Exception {
TokenEndpoint tokenEndpoint = new TokenEndpoint();
tokenEndpoint.setClientDetailsService(clientDetailsService);
tokenEndpoint.setProviderExceptionHandler(exceptionTranslator());
tokenEndpoint.setTokenGranter(tokenGranter());
tokenEndpoint.setOAuth2RequestFactory(oauth2RequestFactory());
tokenEndpoint.setOAuth2RequestValidator(oauth2RequestValidator());
tokenEndpoint.setAllowedRequestMethods(allowedTokenEndpointRequestMethods());
return tokenEndpoint;
}
//oauth/check_token
@Bean
public CheckTokenEndpoint checkTokenEndpoint() {
CheckTokenEndpoint endpoint = new CheckTokenEndpoint(getEndpointsConfigurer().getResourceServerTokenServices());
endpoint.setAccessTokenConverter(getEndpointsConfigurer().getAccessTokenConverter());
endpoint.setExceptionTranslator(exceptionTranslator());
return endpoint;
}
//oauth/confirm_access
@Bean
public WhitelabelApprovalEndpoint whitelabelApprovalEndpoint() {
return new WhitelabelApprovalEndpoint();
}
//oauth/error
@Bean
public WhitelabelErrorEndpoint whitelabelErrorEndpoint() {
return new WhitelabelErrorEndpoint();
}
......
}
AuthorizationServerSecurityConfiguration:该类继承了WebSecurityConfigurerAdapter,提供了认证服务的一些相关配置,比如对访问/oauth/token、/oauth/token_key、/oauth/check_token请求要有相对应的访问权限,新增了AuthorizationServerSecurityConfigurer的可配置类,用来配置对token的认证请求过滤器,比如ClientCredentialsTokenEndpointFilter,该过滤器会拦截oauth/token请求,并且对client_id和client_secret进行认证。除此之外,还配置了对实现了AuthorizationServerConfigurer的类进行回调,这样的话,只要实现AuthorizationServerConfigurer接口就可以自由的对认证服务进行相关的业务配置。
@Configuration
@Order(0)
@Import({ ClientDetailsServiceConfiguration.class, AuthorizationServerEndpointsConfiguration.class })
public class AuthorizationServerSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private List<AuthorizationServerConfigurer> configurers = Collections.emptyList();
@Autowired
private ClientDetailsService clientDetailsService;
@Autowired
private AuthorizationServerEndpointsConfiguration endpoints;
@Autowired
public void configure(ClientDetailsServiceConfigurer clientDetails) throws Exception {
//回调AuthorizationServerConfigurer
for (AuthorizationServerConfigurer configurer : configurers) {
configurer.configure(clientDetails);
}
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
...
}
//设置/oauth/token、/oauth/token_key、/oauth/check_token的认证规则
@Override
protected void configure(HttpSecurity http) throws Exception {
AuthorizationServerSecurityConfigurer configurer = new AuthorizationServerSecurityConfigurer();
FrameworkEndpointHandlerMapping handlerMapping = endpoints.oauth2EndpointHandlerMapping();
http.setSharedObject(FrameworkEndpointHandlerMapping.class, handlerMapping);
configure(configurer);
http.apply(configurer);
String tokenEndpointPath = handlerMapping.getServletPath("/oauth/token");
String tokenKeyPath = handlerMapping.getServletPath("/oauth/token_key");
String checkTokenPath = handlerMapping.getServletPath("/oauth/check_token");
if (!endpoints.getEndpointsConfigurer().isUserDetailsServiceOverride()) {
UserDetailsService userDetailsService = http.getSharedObject(UserDetailsService.class);
endpoints.getEndpointsConfigurer().userDetailsService(userDetailsService);
}
// @formatter:off
http
.authorizeRequests()
.antMatchers(tokenEndpointPath).fullyAuthenticated()
.antMatchers(tokenKeyPath).access(configurer.getTokenKeyAccess())
.antMatchers(checkTokenPath).access(configurer.getCheckTokenAccess())
.and()
.requestMatchers()
.antMatchers(tokenEndpointPath, tokenKeyPath, checkTokenPath)
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER);
// @formatter:on
http.setSharedObject(ClientDetailsService.class, clientDetailsService);
}
protected void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
//回调AuthorizationServerConfigurer
for (AuthorizationServerConfigurer configurer : configurers) {
configurer.configure(oauthServer);
}
}
}
附流程图