我正在编写一个Spring Boot 2 Webapp。它使用Azure AD进行用户身份验证(使用授权代码流和委派权限),并利用了Spring Security的OAuth 2.0登录支持。它还尝试访问Microsoft Graph资源。但是,它没有在春季使用Microsoft的Azure库。
在大多数情况下,以下代码可以正常工作。 (我在本地运行。)
@Autowired
private RestTemplateBuilder restTemplateBuilder;
@RequestMapping("/aboutMe")
public String aboutMe(Model model,
@RegisteredOAuth2AuthorizedClient("azure") OAuth2AuthorizedClient authorizedClient) {
String accessTokenValue = authorizedClient.getAccessToken().getTokenValue();
RestTemplate restTemplate = buildRestTemplate(accessTokenValue);
String user = restTemplate.getForObject("https://graph.microsoft.com/v1.0/me", String.class);
model.addAttribute("user", user);
return "pages/me";
}
private RestTemplate buildRestTemplate(String accessTokenValue) {
RestTemplate restTemplate = restTemplateBuilder.additionalInterceptors(
new ClientHttpRequestInterceptor() {
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] bytes,
ClientHttpRequestExecution execution) throws IOException {
request.getHeaders().add("Authorization", "Bearer " + accessTokenValue);
return execution.execute(request, bytes);
}
}).build();
return restTemplate;
}
但是,只有在重新启动应用程序之后,以下测试用例才能按预期工作。
http://localhost:8080/aboutMe
。/aboutMe
页。http://localhost:8080/aboutMe
。https://login.microsoftonline.com/[tenantId]/oauth2/v2.0/authorize
端点。authorize
请求将浏览器重定向到应用程序的redirect-uri
,在这种情况下,它以http://localhost:8080/login/oauth2/code/azure
开头。要么:
404似乎是由于该应用的redirect-uri
并不总是“在听”,特别是在这种情况下。
在上面的控制器代码中,@RegisteredOAuth2AuthorizedClient("azure")
导致Spring Security的OAuth2AuthorizedClientArgumentResolver
抛出ClientAuthorizationRequiredException
,因为它找不到OAuth2AuthorizedClient
,这就是我们要解决的问题。 d期望,因为该应用已重新启动。
然后,ClientAuthorizationRequiredException
使OAuth2AuthorizationRequestRedirectFilter
将浏览器重定向到Azure以请求授权。
但是,Azure不会要求用户提供凭据,而是使用新的授权将浏览器重定向到应用程序的redirect-uri
。 (我假设这是因为浏览器发送了带有其请求的cookie,Azure认为该请求仍然有效。)
处理这种情况的最佳方法是什么,以避免使用户感到困惑?当然,我总是可以告诉用户只关闭所有浏览器窗口,然后重试。但是,从用户的角度来看,这种行为本身并不是完全干净的。
我相信/login/oauth2/code/azure
端点通常由Spring Security过滤器处理,所以我不确定如何拦截它。
也许解决方案是让应用在启动时清除浏览器中的所有cookie?但是Azure的cookie呢?
答案 0 :(得分:0)
我可以通过向Spring Security配置添加.oauth2Client()
来解决此问题。这是工作配置:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/web/**")
.hasRole("USER")
.antMatchers("/")
.permitAll()
.and()
.oauth2Login()
.userInfoEndpoint()
.oidcUserService(this.oidcUserService())
.and()
.defaultSuccessUrl("/", false)
.and()
.logout()
.logoutSuccessUrl(azureLogoutUri)
.permitAll()
// Without the oauth2Client(), the 404 happens
.and()
.oauth2Client();
}
添加.oauth2Client()
会使Spring将第二个OAuth2AuthorizationRequestRedirectFilter
和一个OAuth2AuthorizationCodeGrantFilter
添加到安全过滤器链中。
我错误地认为不需要oauth2Client()
。只有在找不到WebSecurityConfigurerAdapter
的情况下,这才是正确的。