【发布时间】:2021-04-17 17:54:06
【问题描述】:
我已经使用 spring-security-oauth2-autoconfigure 2.1.8.RELEASE 实现了 SSO,它在首次启动时运行良好。我可以登录并调用我的后端 api。
活动一小时后,由于访问令牌已过期且 OAuth2RestTemplate 无法刷新,因此由于 UserRedirectRequiredException 而对我的后端 api 的 REST 调用失败。我得到了这个堆栈:
org.springframework.security.oauth2.client.resource.UserRedirectRequiredException: A redirect is required to get the users approval
at org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider.getRedirectForAuthorization(AuthorizationCodeAccessTokenProvider.java:359)
at org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider.obtainAccessToken(AuthorizationCodeAccessTokenProvider.java:205)
at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainNewAccessTokenInternal(AccessTokenProviderChain.java:148)
at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainAccessToken(AccessTokenProviderChain.java:121)
at org.springframework.security.oauth2.client.OAuth2RestTemplate.acquireAccessToken(OAuth2RestTemplate.java:221)
at org.springframework.security.oauth2.client.OAuth2RestTemplate.getAccessToken(OAuth2RestTemplate.java:173)
我的应用配置代码是:
@Configuration
@EnableOAuth2Sso
@Order(value = 0)
public class AppConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private Environment env;
@Autowired
OAuth2ProtectedResourceDetails oAuth2ProtectedResourceDetails;
@Autowired
OAuth2ClientContext oauth2ClientContext;
@Autowired
private OAuth2ClientContextFilter oauth2ClientContextFilter;
@Value("${security.oauth2.resource.user-info-uri}")
private String userInfoUri;
@Value("${security.oauth2.client.access-token-uri}")
private String accessTokenUri;
@Value("${security.oauth2.client.user-authorization-uri}")
private String userAuthorizationUri;
@Value("${security.oauth2.client.client-id}")
private String clientID;
@Value("${security.oauth2.client.client-secret}")
private String clientSecret;
@Value("${security.oauth2.client.pre-established-redirect-uri}")
private String preEstRedirectUri;
@Value("#{'${security.oauth2.client.scope}'.split(' ')}")
private List<String> scope;
@Override
public void configure(HttpSecurity http) throws Exception {
String logoutUrl = env.getProperty("endSessionEndpoint") + "?post_logout_redirect_uri=" +
URLEncoder.encode(env.getProperty("homePage"), "UTF-8");
http.requiresChannel().anyRequest().requiresSecure();
http.antMatcher("/**")
.authorizeRequests(a -> a
.antMatchers("/", "/static/**", "/webjars/**", "/login**", "/error**", "/js/**", "/css/**", "/img/**").permitAll()
.anyRequest().authenticated()
)
.csrf(c -> c
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
)
.logout(l -> l
.deleteCookies()
.invalidateHttpSession(true)
.logoutSuccessUrl(logoutUrl)
);
http.addFilterAfter(oauth2ClientContextFilter, SecurityContextPersistenceFilter.class);
http.addFilterBefore(swqSSOFilter(), BasicAuthenticationFilter.class);
http.exceptionHandling().authenticationEntryPoint(unauthorizedEntryPoint());
}
private Filter swqSSOFilter() {
private Filter swqSSOFilter() {
OAuth2ClientAuthenticationProcessingFilter azureSsoFilter = new OAuth2ClientAuthenticationProcessingFilter(preEstRedirectUri);
OAuth2RestTemplate oauth2RestTemplate = new OAuth2RestTemplate(oAuth2ProtectedResourceDetails, oauth2ClientContext);
azureSsoFilter.setRestTemplate(oauth2RestTemplate);
UserInfoTokenServices tokenServices = new UserInfoTokenServices(userInfoUri, oAuth2ProtectedResourceDetails.getClientId());
tokenServices.setRestTemplate(oauth2RestTemplate);
azureSsoFilter.setTokenServices(tokenServices);
return azureSsoFilter;
}
@Bean
public AuthenticationEntryPoint unauthorizedEntryPoint() {
return (request, response, authException) -> response.sendRedirect(preEstRedirectUri);
}
@Bean
public OAuth2RestTemplate oauth2RestTemplate(OAuth2ClientContext oauth2ClientContext, OAuth2ProtectedResourceDetails details) {
return new OAuth2RestTemplate(details, oauth2ClientContext);
}
@Bean
public FilterRegistrationBean<OAuth2ClientContextFilter> oauth2ClientFilterRegistration(
OAuth2ClientContextFilter filter) {
FilterRegistrationBean<OAuth2ClientContextFilter> registration = new FilterRegistrationBean<OAuth2ClientContextFilter>();
registration.setFilter(filter);
registration.setOrder(-100);
return registration;
}
}
我关注了很多 stackoverflow 帖子,但没有一个解决方案对我有用。 有人可以告诉我我做错了什么吗?
【问题讨论】:
-
嗨@Ranbir,为了增加你的令牌寿命,你需要在你的代码中实现刷新令牌。请参考ms docs
-
我在范围中添加了“offline_access”,在grant_type中添加了“authorization_code”来获取刷新令牌并使用正确的令牌服务提供商,显然它解决了这个问题。
-
@感谢您的更新。我会将我的答案从 cmets 转移到 answer。
标签: spring azure spring-boot azure-active-directory single-sign-on