Spring Boot 2.0 & OAuth 2.0 客户端实现
在oauth2.0框架中,主要包含了三个角色,授权端,客户端,资源端。
授权端指的是oauth2.0的授权服务,客户端可能是浏览器,也可能是java服务,资源端是给客户端提供资源服务的.
从流程上看,客户端提供认证信息,从授权服务获取令牌,让拿着令牌到资源服务获取内容,资源服务会拿着客户端给的令牌去授权服务校验令牌的有效性,无问题则返回相应资源。
单论客户端而言,首先需要配置授权必须的配置,比如clientid,clientSecret等。
配置模板如下
client: clientId: spring-security-oauth2-read-client clientSecret: spring-security-oauth2-read-client-password1234 accessTokenUri: http://localhost:8080/oauth/token userAuthorizationUri: http://localhost:8080/oauth/authorize clientAuthenticationScheme: form authenticationScheme: query resource: userInfoUri: http://localhost:8080/secured/user
然后需要实现登入功能,需要跳转到收取按服务的登入页面获取令牌。
具体的写个类实现继承WebSecurityConfigurerAdapter。
在这里我们需要重写下void configure(HttpSecurity http)
,主要配置下那些接口需要认证,那些不需要,登入成功后跳转哪个页面,添加认证过滤器等。
具体的可以查看下HttpSecurity的用法。
@Override protected void configure(HttpSecurity http) throws Exception { // @formatter:off http.antMatcher("/**").authorizeRequests().antMatchers("/", "/login**", "/webjars/**", "/error**").permitAll().anyRequest() .authenticated().and().exceptionHandling() .authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/")).and().logout() .logoutSuccessUrl("/").permitAll().and().csrf() .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and() .addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class); // @formatter:on }
接下来,需要实现一个客户端认证的过滤器,并加载之前写的配置信息。
首先声明一个配置类,包装了配置过滤器需要的参数。
class ClientResources { @NestedConfigurationProperty private AuthorizationCodeResourceDetails client = new AuthorizationCodeResourceDetails(); @NestedConfigurationProperty private ResourceServerProperties resource = new ResourceServerProperties(); public AuthorizationCodeResourceDetails getClient() { return client; } public ResourceServerProperties getResource() { return resource; } }
再写个创建bean的方法。
@Bean @ConfigurationProperties("client") public ClientResources github() { return new ClientResources(); }
接下来,我们调用这个配置好的bean创建过滤器。
private Filter ssoFilter() { CompositeFilter filter = new CompositeFilter(); Listfilters = new ArrayList<>(); filters.add(ssoFilter(github(), "/login/github")); filter.setFilters(filters); return filter; } private Filter ssoFilter(ClientResources client, String path) { OAuth2ClientAuthenticationProcessingFilter oAuth2ClientAuthenticationFilter = new OAuth2ClientAuthenticationProcessingFilter(path); OAuth2RestTemplate oAuth2RestTemplate = new OAuth2RestTemplate(client.getClient(), oauth2ClientContext); oAuth2ClientAuthenticationFilter.setRestTemplate(oAuth2RestTemplate); UserInfoTokenServices tokenServices = new UserInfoTokenServices(client.getResource().getUserInfoUri(), client.getClient().getClientId()); tokenServices.setRestTemplate(oAuth2RestTemplate); oAuth2ClientAuthenticationFilter.setTokenServices(tokenServices); return oAuth2ClientAuthenticationFilter; }
这个时候基本配置完毕,能够调用认证服务登入了。