我有一个使用配置A扩展的现有Spring应用程序 ResourceServerConfigureAdapter 以保护API免受内部oauth服务A. 我正在尝试添加另一个扩展 WebSecurityConfigurerAdapter 的配置B,它针对外部oauth提供程序进行身份验证。
目标是继续B确定/ api /相关端点的身份验证,而A确定Web应用程序的整体登录。
以下是使用ResourceServerConfigureAdapter的现有代码: -
@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Value("${oauth.clientId}")
private String clientId;
@Value("${oauth.clientSecret}")
private String clientSecret;
@Autowired
private RestTemplate restTemplate;
@Bean
public RemoteTokenServices remoteTokenServices() {
RemoteTokenServices remoteTokenServices = new RemoteTokenServices();
remoteTokenServices.setRestTemplate(restTemplate);
remoteTokenServices.setClientId(clientId);
remoteTokenServices.setClientSecret(clientSecret);
remoteTokenServices.setCheckTokenEndpointUrl("srvc://myservice/api/v2/oauth/check_token");
return remoteTokenServices;
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId(null);
resources.tokenServices(remoteTokenServices());
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.anonymous()
.and().authorizeRequests()
.antMatchers("/api/secured/**").authenticated()
.antMatchers("/api/**").permitAll();
}}
以下是使用WebSecurityConfigurerAdapter的代码: -
@SpringBootApplication
@EnableOAuth2Client
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
public class DemoService extends WebSecurityConfigurerAdapter {
@Autowired
OAuth2ClientContext oauth2ClientContext;
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http.antMatcher("/**").authorizeRequests().antMatchers("/", "/login**", "/webjars/**").permitAll().anyRequest()
.authenticated().and().exceptionHandling()
.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/")).and().logout()
.logoutSuccessUrl("/").permitAll().and().csrf()
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()
.addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);
// @formatter:on
}
public static void main(String[] args) {
SpringApplication.run(DemoService.class, args);
}
@Bean
public FilterRegistrationBean oauth2ClientFilterRegistration(OAuth2ClientContextFilter filter) {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(filter);
registration.setOrder(-100);
return registration;
}
private Filter ssoFilter() {
OAuth2ClientAuthenticationProcessingFilter googleFilter = new OAuth2ClientAuthenticationProcessingFilter(
"/login/google");
OAuth2RestTemplate googleTemplate = new OAuth2RestTemplate(google(), oauth2ClientContext);
googleFilter.setRestTemplate(googleTemplate);
UserInfoTokenServices tokenServices = new UserInfoTokenServices(googleResource().getUserInfoUri(),
google().getClientId());
tokenServices.setRestTemplate(googleTemplate);
googleFilter.setTokenServices(
new UserInfoTokenServices(googleResource().getUserInfoUri(), google().getClientId()));
return googleFilter;
}
@Bean
@ConfigurationProperties("google.client")
public AuthorizationCodeResourceDetails google() {
return new AuthorizationCodeResourceDetails();
}
@Bean
@ConfigurationProperties("google.resource")
public ResourceServerProperties googleResource() {
return new ResourceServerProperties();
}
}
他们两人单独运行良好,但在同一个项目中放在一起,问题开始显现。一切都编译并运行良好,但当我点击localhost:8080 /以下发生 - 页面加载正常但是当我点击localhost:8080 / login / google时,它会显示一个whitelabel错误页面,如下所示
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Thu Apr 06 13:22:27 IST 2017
There was an unexpected error (type=Not Found, status=404).
Not Found
我尝试阅读一下有关ResourceServerConfigureAdapter和WebSecurityConfigurerAdapter的内容,我只能理解有某种过滤器顺序可以确定每个配置器的优先级。但这并没有帮助我解决这个问题。有什么指针吗?
更新: Swagger集成的另一个适配器也是项目的一部分。
@EnableSwagger2
@Configuration
public class SwaggerConfiguration extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addRedirectViewController("/docs", "/swagger-ui.html");
registry.addRedirectViewController("/docs/", "/swagger-ui.html");
registry.addRedirectViewController("/docs.json", "/v2/api-docs");
}
@Bean
public Docket swaggerSpringMvcPlugin() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(new ApiInfoBuilder()
.title("Spring Boot Service")
.description("Sample project documentation")
.contact("a@b.com")
.version("1.0")
.license("Apache")
.build())
.forCodeGeneration(true)
.ignoredParameterTypes(Principal.class)
.useDefaultResponseMessages(false)
.select()
.paths(documentedPaths())
.build();
}
private Predicate<String> documentedPaths() {
return or(
regex("/api.*"));
}
}
答案 0 :(得分:0)
.addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);
OAuth2ClientAuthenticationProcessingFilter
必须在OAuth2ClientContextFilter
之后,OAuth2ClientAuthenticationProcessingFilter
在请求错误时抛出redirect exception
(否code
等等),< / p>
,OAuth2ClientContextFilter
会抓住它并重定向到userAuthorizationUri
;
BasicAuthenticationFilter
在OAuth2ClientContextFilter
正常之前,所以您应该更改顺序:
@Autowired
private OAuth2ClientContextFilter oAuth2ClientContextFilter;
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterAfter(oAuth2ClientContextFilter, ExceptionTranslationFilter.class)
.addFilterAfter(ssoFilter(), OAuth2ClientContextFilter.class);
}
更新:
还有另一个地方需要更新,如果你有多链,你应该定义请求匹配,默认值是'/ **',默认顺序ResourceServerConfiguration
是3,默认WebSecurityConfigurerAdapter
的顺序为100,ResourceServerConfiguration
具有高优先级。
// only handle the request start with `/api`
http.requestMatcher(new AntPathRequestMatcher("/api/**"))
http.anonymous()
.and().authorizeRequests()
.antMatchers("/api/secured/**").authenticated()
.antMatchers("/api/**").permitAll();
如果您通过更改订单将WebSecurityConfigurerAdapter
置于ResourceServerConfiguration
之前,则还应将WebSecurityConfigurerAdapter
配置为不处理/api/**
// skip the request start with '/api'
http.requestMatcher(new RegexRequestMatcher("^(?!/api).*$", null))
.authorizeRequests().antMatchers("/", "/login/**", "/webjars/**").permitAll().anyRequest()
UPDATE2:
.authorizeRequests().antMatchers("/", "/login**")
此匹配器与/login/google
不符,请更新为/login/**
,因此应该
.authorizeRequests().antMatchers("/", "/login/**").permitAll()