我使用Spring启动Spring安全性,自定义“Filter”类使用OAuth 2身份验证调用CIAM服务器。我想明确设置或覆盖默认设置,以便我可以在Spring Security准备的重定向URL中设置自定义动态STATE参数,并将用户发送到CIAM服务器登录页面。这对我来说是微不足道的,但结果却远非如此。
目标是添加OAuth2重定向链接的自定义STATE参数,以便在身份验证完成后CIAM服务器将我重定向回我的页面时,我会收回自动包含在成功重定向链接中的STATE参数。 CIAM服务器。
安全配置
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true,
proxyTargetClass = true)
@EnableOAuth2Client
@Order(3)
public class OAuth2LoginWebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
CiamOAuth2ClientFilter oAuth2CiamClientFilter;
@Bean
public InMemoryUserDetailsManager inMemoryUserDetailsManager() {
return new InMemoryUserDetailsManager();
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/**/*.css", "/**/*.png", "/**/*.gif", "/**/*.jpg", "/h2-console/**", "/css/**",
"/img/**", "/font-awesome/**", "/fonts/**", "/js/**", "/signout","/signout/**", "/health");
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.antMatcher("/**")
.authorizeRequests()
.antMatchers("/user/**").hasRole("USER")
.antMatchers("/backoffice/**").hasRole("ADMIN")
.antMatchers("/api/**").hasRole("API")
.antMatchers(/*"/", */"/login**", "/webjars/**", "/favicon.*", "/resources/**",
"/auth/**", "/signin/**","css/**","js/**", "/signup/**", "/signout/", "/health", "/awsTest/login")
.permitAll()
.anyRequest()
.authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(new LoginUrlAuthenticationEntryPoint("/login/callback"))
.and()
.addFilterBefore(oAuth2CiamClientFilter.ciamFilter(), BasicAuthenticationFilter.class)
.logout()
.logoutUrl("/signout")
.logoutSuccessUrl("/logout");
}
}
自定义过滤器类
@Configuration
public class CiamOAuth2ClientFilter {
@Autowired
AuthorizationCodeResourceDetails oauth2CiamResourceDetails;
@Autowired
CiamOAuth2ClientProperties oauth2CiamClientProperties;
@Autowired
OAuth2ClientContext oauth2ClientContext;
@Autowired
CiamPrincipalExtractor ciamPrincipalExtractor;
@Bean
public FilterRegistrationBean oauth2ClientFilterRegistration(OAuth2ClientContextFilter filter) {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(filter);
registration.setOrder(-100);
registration.addInitParameter("test", "trrrrrrr");
System.out.println("333333333333333333333333");
System.out.println(registration);
return registration;
}
public Filter ciamFilter() {
System.out.println("postaeget");
System.out.println(oauth2CiamClientProperties);
System.out.println(" _-------------------------------: " + oauth2CiamClientProperties.getResource().getUserInfoUri());
UserInfoTokenServices tokenService = new UserInfoTokenServices(oauth2CiamClientProperties.getResource().getUserInfoUri(), oauth2CiamResourceDetails.getClientId());
OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(oauth2CiamResourceDetails, oauth2ClientContext);
OAuth2ClientAuthenticationProcessingFilter filter = new OAuth2ClientAuthenticationProcessingFilter("/login/callback");
tokenService.setRestTemplate(restTemplate);
tokenService.setPrincipalExtractor(ciamPrincipalExtractor);
filter.setRestTemplate(restTemplate);
filter.setTokenServices(tokenService);
return filter;
}
}
与问题相关的应用程序yml设置文件
security:
oauth2:
client:
clientId: ...
clientSecret: ....
accessTokenUri: ...
userAuthorizationUri: ...
useCurrentUri: false
preEstablishedRedirectUri: https://localhost/login/callback
clientAuthenticationScheme: query
authenticationScheme: header
serverLogoutUrl: ..
postLogoutRedirectUri: https://localhost/signout
scope:
- openid
- profile
- email
- offline_access
state: TEST
resource:
userInfoUri: ...
preferTokenInfo: ...
答案 0 :(得分:-1)
就我而言
我在@Configuration中的某处配置OAuth2ClientAuthenticationProcessingFilter:
private Filter ssoFilter() {
OAuth2ClientAuthenticationProcessingFilter facebookFilter = new OAuth2ClientAuthenticationProcessingFilter(API_LOGIN_FACEBOOK);
OAuth2RestTemplate facebookTemplate = new OAuth2RestTemplate(facebook(), oauth2ClientContext);
AuthorizationCodeAccessTokenProvider authorizationCodeAccessTokenProviderWithUrl = new AuthorizationCodeAccessTokenProvider();
authorizationCodeAccessTokenProviderWithUrl.setStateKeyGenerator(new StateKeyGeneratorWithRedirectUrl());
facebookTemplate.setAccessTokenProvider(authorizationCodeAccessTokenProviderWithUrl);
facebookFilter.setRestTemplate(facebookTemplate);
UserInfoTokenServices tokenServices = new CheckedUserInfoTokenServices(
facebookResource().getUserInfoUri(), facebook().getClientId(),
facebookPrincipalExtractor, blogPreAuthenticationChecks(), blogPostAuthenticationChecks());
tokenServices.setAuthoritiesExtractor(new FacebookAuthoritiesExtractor());
tokenServices.setRestTemplate(facebookTemplate);
facebookFilter.setTokenServices(tokenServices);
facebookFilter.setAuthenticationSuccessHandler(new OAuth2AuthenticationSuccessHandler());
return facebookFilter;
}
您可以通过以下方式访问StateKeyGeneratorWithRedirectUrl中的当前请求:
RequestContextHolder.getRequestAttributes()
因此您可以提取Referer标头,例如:
public class StateKeyGeneratorWithRedirectUrl extends DefaultStateKeyGenerator {
private RandomValueStringGenerator generator = new RandomValueStringGenerator();
@Override
public String generateKey(OAuth2ProtectedResourceDetails resource) {
HttpServletRequest currentHttpRequest = getCurrentHttpRequest();
if (currentHttpRequest!=null){
String referer = currentHttpRequest.getHeader("Referer");
if (!StringUtils.isEmpty(referer)){
return generator.generate()+","+referer;
}
}
return generator.generate();
}
private static HttpServletRequest getCurrentHttpRequest(){
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
if (requestAttributes instanceof ServletRequestAttributes) {
return ((ServletRequestAttributes)requestAttributes).getRequest();
}
return null;
}
}
下一步-从回调读取状态:
public class OAuth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
public static final String DEFAULT = "/";
@Override
protected String determineTargetUrl(HttpServletRequest request,
HttpServletResponse response) {
UriComponents uriComponents = UriComponentsBuilder.newInstance()
.query(request.getQueryString())
.build();
MultiValueMap<String, String> queryParams = uriComponents.getQueryParams();
String stateEncoded = queryParams.getFirst("state");
if (stateEncoded == null) {
return DEFAULT;
}
String stateDecoded = URLDecoder.decode(stateEncoded, StandardCharsets.UTF_8);
String[] split = stateDecoded.split(",");
String redirect;
if (split.length != 2){
return DEFAULT;
} else {
return split[1];
}
}
}