Spring 启动 Azure AD 承载 Header 身份验证(签名的 JWT 被拒绝:签名无效)
Spring Boot Azure AD Bearer Header Authentication (Signed JWT rejected: Invalid signature)
我有一个用 Spring Boot 编写的 GraphQL API。我想将它与 Azure Active Directory 连接,但是当我发送一个包含身份验证承载 header.
的请求时出现该错误
com.nimbusds.jose.proc.BadJWSException: Signed JWT rejected: Invalid signature
我正在使用 Azure Active Directory Starter,这是我的设置:
网络安全配置器:
import com.microsoft.azure.spring.autoconfigure.aad.AADAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class ADConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Autowired
private AADAuthenticationFilter aadAuthenticationFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers().frameOptions().disable();
http.addFilterBefore(aadAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
.csrf().disable()
.authorizeRequests().antMatchers("/api").hasAnyRole("developer")
.and()
.authorizeRequests().antMatchers("/").permitAll()
.and()
.authorizeRequests().anyRequest().permitAll()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
从MSAL-AngularJS获取不记名令牌front-end:
app.config(['msalAuthenticationServiceProvider', '$locationProvider', (msalProvider, $locationProvider)=>{
msalProvider.init({
clientID: CLIENT_ID,
authority: 'https://login.microsoftonline.com/'+TENANT,
validateAuthority: false,
tokenReceivedCallback: function (errorDesc, token, error, tokenType) {
},
optionalParams: {
cacheLocation: 'localStorage',
storeAuthStateInCookie: true,
logger: logger,
endPoints: endpointsMap
},
routeProtectionConfig: {
popUp: true
},
});
$locationProvider.html5Mode(false).hashPrefix('');
}]);
...
app.controller("NavController", ['$scope', '$rootScope', '$window', 'msalAuthenticationService', ($scope, $rootScope, $window, msalService)=>{
$scope.$evalAsync(()=>{
$scope.userInfo = msalService.userInfo;
if($scope.userInfo.isAuthenticated){
msalService.acquireTokenSilent(['user.read']).then(token=>{
$rootScope.authToken = token;
$rootScope.$broadcast("authTokenSet");
}).catch(error=>{
console.log("Error: ",error)
});
}
})
...
我还通过 Postman 使用 acquireTokenSilent
请求返回的令牌对其进行了手动测试。
这是错误信息:
com.nimbusds.jose.proc.BadJWSException: Signed JWT rejected: Invalid signature
at com.nimbusds.jwt.proc.DefaultJWTProcessor.<clinit>(DefaultJWTProcessor.java:103) ~[nimbus-jose-jwt-7.9.jar:7.9]
at com.microsoft.azure.spring.autoconfigure.aad.UserPrincipalManager.getAadJwtTokenValidator(UserPrincipalManager.java:91) ~[azure-spring-boot-2.1.7.jar:na]
at com.microsoft.azure.spring.autoconfigure.aad.UserPrincipalManager.buildUserPrincipal(UserPrincipalManager.java:82) ~[azure-spring-boot-2.1.7.jar:na]
at com.microsoft.azure.spring.autoconfigure.aad.AADAuthenticationFilter.doFilterInternal(AADAuthenticationFilter.java:78) ~[azure-spring-boot-2.1.7.jar:na]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) ~[spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:74) ~[spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) ~[spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) ~[spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) ~[spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) ~[spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:114) ~[spring-boot-actuator-2.1.8.RELEASE.jar:2.1.8.RELEASE]
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:104) ~[spring-boot-actuator-2.1.8.RELEASE.jar:2.1.8.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:526) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1587) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.24.jar:9.0.24]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_222]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_222]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.24.jar:9.0.24]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_222]
我找不到很多相关文档。
降级了 Azure Active Directory Starter Library 的版本。之后它与 active sign-in 一起工作。将 front-end 库从 MSAL 更改为 ADAL,并且 header 身份验证也以某种方式起作用。
使用 azure-spring-boot 库 (2.2.0.M1) 的最新里程碑版本来解决此错误。
当您使用 v2.0 端点获取令牌(MSAL 这样做)并且还使用最新的 azure-spring-boot 库(当时为 2.1.7)时,会出现此错误写作)。
主要区别在于 v2.0 端点 return 与 v1.0 端点
不同的颁发者在 JWT 内部声明 id_tokens
- v1.0 声明:
"iss": "https://sts.windows.net/{tenant_id}/"
- v2.0 声明:
"iss": "https://login.microsoftonline.com/{tenant_id}/v2.0"
如果您查看引发错误的代码,您会发现它正在对发行者进行显式检查,以确保它即将使用的令牌实际上来自 Microsoft。参见:https://github.com/microsoft/azure-spring-boot/blob/2.1.7/azure-spring-boot/src/main/java/com/microsoft/azure/spring/autoconfigure/aad/UserPrincipalManager.java#L102
但是,在 2.2.0.M1 中,检查被扩展为包括 login.microsoftonline.com,因此令牌成功通过了此检查。
以上问题已通过以下步骤解决。
1) 将azurespringbootapi修改为2.2.0M1版本
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-spring-boot</artifactId>
<version>2.2.0.M1</version>
</dependency>
2) 在您的 Web 配置过滤器中,只需自动装配 AADAppRoleStatelessAuthenticationFilter
@Autowired
私人 AADAppRoleStatelessAuthenticationFilter aadAuthFilter;
3) 在 spring 引导应用程序 application.properties 文件中添加一个条目
azure.activedirectory.session-stateless=true
下面是完整的过滤器代码
package com.staples.dmp.web;
import java.util.Collection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import com.microsoft.azure.spring.autoconfigure.aad.AADAppRoleStatelessAuthenticationFilter;
@SuppressWarnings("unused")
@EnableGlobalMethodSecurity(securedEnabled = true,
prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AADAppRoleStatelessAuthenticationFilter aadAuthFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
// require OAuth JWT token from AzureAD app for /api
http.csrf().disable()
.authorizeRequests()
.antMatchers("/v1/**").permitAll()
.antMatchers("/datascience/v1/ds_batch").permitAll()
.antMatchers("/v2/ad/**").hasAnyRole("USER")
.anyRequest().authenticated();
// adding userid Password authentication filter to the filter chain
http.addFilterBefore(aadAuthFilter, UsernamePasswordAuthenticationFilter.class);
}
}
我有一个用 Spring Boot 编写的 GraphQL API。我想将它与 Azure Active Directory 连接,但是当我发送一个包含身份验证承载 header.
的请求时出现该错误com.nimbusds.jose.proc.BadJWSException: Signed JWT rejected: Invalid signature
我正在使用 Azure Active Directory Starter,这是我的设置:
网络安全配置器:
import com.microsoft.azure.spring.autoconfigure.aad.AADAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class ADConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Autowired
private AADAuthenticationFilter aadAuthenticationFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers().frameOptions().disable();
http.addFilterBefore(aadAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
.csrf().disable()
.authorizeRequests().antMatchers("/api").hasAnyRole("developer")
.and()
.authorizeRequests().antMatchers("/").permitAll()
.and()
.authorizeRequests().anyRequest().permitAll()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
}
从MSAL-AngularJS获取不记名令牌front-end:
app.config(['msalAuthenticationServiceProvider', '$locationProvider', (msalProvider, $locationProvider)=>{
msalProvider.init({
clientID: CLIENT_ID,
authority: 'https://login.microsoftonline.com/'+TENANT,
validateAuthority: false,
tokenReceivedCallback: function (errorDesc, token, error, tokenType) {
},
optionalParams: {
cacheLocation: 'localStorage',
storeAuthStateInCookie: true,
logger: logger,
endPoints: endpointsMap
},
routeProtectionConfig: {
popUp: true
},
});
$locationProvider.html5Mode(false).hashPrefix('');
}]);
...
app.controller("NavController", ['$scope', '$rootScope', '$window', 'msalAuthenticationService', ($scope, $rootScope, $window, msalService)=>{
$scope.$evalAsync(()=>{
$scope.userInfo = msalService.userInfo;
if($scope.userInfo.isAuthenticated){
msalService.acquireTokenSilent(['user.read']).then(token=>{
$rootScope.authToken = token;
$rootScope.$broadcast("authTokenSet");
}).catch(error=>{
console.log("Error: ",error)
});
}
})
...
我还通过 Postman 使用 acquireTokenSilent
请求返回的令牌对其进行了手动测试。
这是错误信息:
com.nimbusds.jose.proc.BadJWSException: Signed JWT rejected: Invalid signature
at com.nimbusds.jwt.proc.DefaultJWTProcessor.<clinit>(DefaultJWTProcessor.java:103) ~[nimbus-jose-jwt-7.9.jar:7.9]
at com.microsoft.azure.spring.autoconfigure.aad.UserPrincipalManager.getAadJwtTokenValidator(UserPrincipalManager.java:91) ~[azure-spring-boot-2.1.7.jar:na]
at com.microsoft.azure.spring.autoconfigure.aad.UserPrincipalManager.buildUserPrincipal(UserPrincipalManager.java:82) ~[azure-spring-boot-2.1.7.jar:na]
at com.microsoft.azure.spring.autoconfigure.aad.AADAuthenticationFilter.doFilterInternal(AADAuthenticationFilter.java:78) ~[azure-spring-boot-2.1.7.jar:na]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116) ~[spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:74) ~[spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105) ~[spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56) ~[spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334) ~[spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:215) ~[spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:178) ~[spring-security-web-5.1.6.RELEASE.jar:5.1.6.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:357) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:270) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:92) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:93) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.filterAndRecordMetrics(WebMvcMetricsFilter.java:114) ~[spring-boot-actuator-2.1.8.RELEASE.jar:2.1.8.RELEASE]
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:104) ~[spring-boot-actuator-2.1.8.RELEASE.jar:2.1.8.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:118) ~[spring-web-5.1.9.RELEASE.jar:5.1.9.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:526) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1587) [tomcat-embed-core-9.0.24.jar:9.0.24]
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.24.jar:9.0.24]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_222]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_222]
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.24.jar:9.0.24]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_222]
我找不到很多相关文档。
降级了 Azure Active Directory Starter Library 的版本。之后它与 active sign-in 一起工作。将 front-end 库从 MSAL 更改为 ADAL,并且 header 身份验证也以某种方式起作用。
使用 azure-spring-boot 库 (2.2.0.M1) 的最新里程碑版本来解决此错误。
当您使用 v2.0 端点获取令牌(MSAL 这样做)并且还使用最新的 azure-spring-boot 库(当时为 2.1.7)时,会出现此错误写作)。
主要区别在于 v2.0 端点 return 与 v1.0 端点
不同的颁发者在 JWT 内部声明 id_tokens- v1.0 声明:
"iss": "https://sts.windows.net/{tenant_id}/"
- v2.0 声明:
"iss": "https://login.microsoftonline.com/{tenant_id}/v2.0"
如果您查看引发错误的代码,您会发现它正在对发行者进行显式检查,以确保它即将使用的令牌实际上来自 Microsoft。参见:https://github.com/microsoft/azure-spring-boot/blob/2.1.7/azure-spring-boot/src/main/java/com/microsoft/azure/spring/autoconfigure/aad/UserPrincipalManager.java#L102
但是,在 2.2.0.M1 中,检查被扩展为包括 login.microsoftonline.com,因此令牌成功通过了此检查。
以上问题已通过以下步骤解决。
1) 将azurespringbootapi修改为2.2.0M1版本
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-spring-boot</artifactId>
<version>2.2.0.M1</version>
</dependency>
2) 在您的 Web 配置过滤器中,只需自动装配 AADAppRoleStatelessAuthenticationFilter
@Autowired 私人 AADAppRoleStatelessAuthenticationFilter aadAuthFilter;
3) 在 spring 引导应用程序 application.properties 文件中添加一个条目
azure.activedirectory.session-stateless=true
下面是完整的过滤器代码
package com.staples.dmp.web;
import java.util.Collection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import com.microsoft.azure.spring.autoconfigure.aad.AADAppRoleStatelessAuthenticationFilter;
@SuppressWarnings("unused")
@EnableGlobalMethodSecurity(securedEnabled = true,
prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AADAppRoleStatelessAuthenticationFilter aadAuthFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
// require OAuth JWT token from AzureAD app for /api
http.csrf().disable()
.authorizeRequests()
.antMatchers("/v1/**").permitAll()
.antMatchers("/datascience/v1/ds_batch").permitAll()
.antMatchers("/v2/ad/**").hasAnyRole("USER")
.anyRequest().authenticated();
// adding userid Password authentication filter to the filter chain
http.addFilterBefore(aadAuthFilter, UsernamePasswordAuthenticationFilter.class);
}
}