Bor*_*hev 5 spring spring-security oauth-2.0 spring-boot
我正在使用具有 Spring 安全性的 Spring Boot,自定义“过滤器”类调用具有 OAuth 2 身份验证的 CIAM 服务器。我想显式设置或覆盖默认设置,以便我可以在 Spring Security 在后台准备的重定向 URL 中设置自定义动态 STATE 参数,并将用户发送到 CIAM 服务器登录页面。这对我来说是微不足道的,但事实证明远非如此。
目标是添加 OAuth2 重定向链接的自定义 STATE 参数,以便在身份验证完成且 CIAM 服务器将我重定向回我的页面后,我从 CIAM 服务器收回成功重定向链接中自动包含的 STATE 参数.
安全配置
@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");
}
}
Run Code Online (Sandbox Code Playgroud)
自定义过滤器类
@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;
}
}
Run Code Online (Sandbox Code Playgroud)
与问题相关的应用程序 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: ...
Run Code Online (Sandbox Code Playgroud)
小智 1
就我而言
我OAuth2ClientAuthenticationProcessingFilter在某处配置@Configuration:
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;
}
Run Code Online (Sandbox Code Playgroud)
您可以通过以下方式访问当前请求StateKeyGeneratorWithRedirectUrl:
RequestContextHolder.getRequestAttributes()
Run Code Online (Sandbox Code Playgroud)
所以你可以提取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;
}
}
Run Code Online (Sandbox Code Playgroud)
接下来 - 从回调中读取状态:
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];
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3620 次 |
| 最近记录: |