3 回答

TA貢獻(xiàn)1848條經(jīng)驗(yàn) 獲得超6個(gè)贊
我知道我參加聚會(huì)遲到了,但當(dāng)前答案中缺少一些信息。
非法狀態(tài)異常:
provided in the configuration did not match the requested issuer
很可能是由于 @Dragana Le Mitova 已經(jīng)在 issues-uri 屬性末尾的斜線提到的那樣引起的。這需要設(shè)置為:
spring.security.oauth2.resourceserver.jwt.issuer-uri=https://mycompb2ctestorg.b2clogin.com/mycompb2ctestorg.onmicrosoft.com/v2.0
然后 Spring 將自動(dòng)提取 OAuth 資源服務(wù)器的配置https://mycompb2ctestorg.b2clogin.com/mycompb2ctestorg.onmicrosoft.com/v2.0/.well-known/openid-configuration。
為了確保我們只接受來(lái)自 Azure 應(yīng)用程序的 JWT,我們需要檢查 JWT 的受眾 (aud) 屬性。對(duì)于 Azure 應(yīng)用程序,這通常與客戶端/應(yīng)用程序 ID 相同。正如 @Wim Deblauwe 已經(jīng)回答的那樣,這是通過(guò)JwtDecoder. Spring Security 甚至在他們的文檔中為我們提供了一個(gè)自定義 JWT 驗(yàn)證器的示例,其中他們實(shí)現(xiàn)了受眾聲明檢查。這是通過(guò)在JwtDecoderbean 中提供我們自己的驗(yàn)證器來(lái)完成的。
受眾(aud)聲明驗(yàn)證器:
public class AudienceValidator implements OAuth2TokenValidator<Jwt> {
OAuth2Error error = new OAuth2Error("invalid_token", "The required audience is missing", null);
public OAuth2TokenValidatorResult validate(Jwt jwt) {
if (jwt.getAudience().contains("messaging")) {
return OAuth2TokenValidatorResult.success();
} else {
return OAuth2TokenValidatorResult.failure(error);
}
}
}
Jwt解碼器:
@Bean
JwtDecoder jwtDecoder() {
NimbusJwtDecoderJwkSupport jwtDecoder = (NimbusJwtDecoderJwkSupport)
JwtDecoders.withOidcIssuerLocation(issuerUri);
OAuth2TokenValidator<Jwt> audienceValidator = new AudienceValidator();
OAuth2TokenValidator<Jwt> withIssuer = JwtValidators.createDefaultWithIssuer(issuerUri);
OAuth2TokenValidator<Jwt> withAudience = new DelegatingOAuth2TokenValidator<>(withIssuer, audienceValidator);
jwtDecoder.setJwtValidator(withAudience);
return jwtDecoder;
}
這與 @Wim Deblauwe 提供的答案略有不同,我們使用JwtValidators.createDefaultWithIssuer(issuerUri)而不是創(chuàng)建驗(yàn)證器JwtValidators.createDefault()。這很重要,因?yàn)槲覀儽举|(zhì)上要檢查 3 個(gè) JWT 屬性:
到期日
發(fā)行人
觀眾
我們JwtValidators.createDefault()只為過(guò)期屬性創(chuàng)建一個(gè)驗(yàn)證器。我們?yōu)镴wtValidators.createDefaultWithIssuer(issuerUri)過(guò)期和發(fā)行者屬性創(chuàng)建驗(yàn)證器。JwtValidators.createDefaultWithIssuer(issuerUri)也是 Spring Security 設(shè)置 issues-uri 屬性時(shí)的默認(rèn)行為。
如果您想更深入地了解,我們目前添加自定義驗(yàn)證器的方式是否是最佳方式正在進(jìn)行討論。

TA貢獻(xiàn)1799條經(jīng)驗(yàn) 獲得超8個(gè)贊
在閱讀了Spring Security 文檔中的自定義令牌驗(yàn)證器后,我添加了一個(gè)自定義驗(yàn)證器來(lái)檢查受眾聲明,以確保令牌是為我自己的應(yīng)用程序頒發(fā)的。為此,請(qǐng)創(chuàng)建此驗(yàn)證器類(lèi):
private static class AudienceValidator implements OAuth2TokenValidator<Jwt> {
@Override
public OAuth2TokenValidatorResult validate(Jwt token) {
if (token.getAudience().contains("my-application-id-here")) {
return OAuth2TokenValidatorResult.success();
} else {
return OAuth2TokenValidatorResult.failure(
new OAuth2Error("invalid_token", "The audience is not as expected, got " + token.getAudience(),
null));
}
}
}
并通過(guò)JwtDecoder在配置類(lèi)中聲明您自己的 bean來(lái)使用它WebSecurityConfigurerAdapter:
@Bean
public JwtDecoder jwtDecoder() {
NimbusJwtDecoder result = NimbusJwtDecoder.withJwkSetUri(properties.getJwt().getJwkSetUri()).build();
result.setJwtValidator(
new DelegatingOAuth2TokenValidator<Jwt>(
JwtValidators.createDefault(),
new AudienceValidator())
);
return result;
}
默認(rèn)驗(yàn)證器將檢查時(shí)間戳等內(nèi)容。如果沒(méi)問(wèn)題,AudienceValidator 將檢查受眾聲明。
注意:您在驗(yàn)證器中傳遞的順序DelegatingOAuth2TokenValidator定義了 JWT 令牌的檢查順序。在此示例中,在觀眾之前檢查時(shí)間戳。如果你想讓觀眾先檢查,你需要把它放在構(gòu)造函數(shù)的前面DelegatingOAuth2TokenValidator

TA貢獻(xiàn)1815條經(jīng)驗(yàn) 獲得超10個(gè)贊
我懷疑您在嘗試聲明自己的JwtDecoder光束時(shí)遇到的異常來(lái)自缺少的斜杠。
請(qǐng)注意,“請(qǐng)求的發(fā)行者”始終缺少尾部斜杠,即使在配置中明確指定了尾部斜杠。
按照規(guī)范的要求, Spring Security在附加之前會(huì)從頒發(fā)者 URI 中刪除所有尾部斜杠。但是,在獲取配置后,返回的配置的頒發(fā)者 URI 與問(wèn)題 URI 的“清理”版本相匹配,而不是最初提供的版本。
由于fromOidcIssuerLocation()不知道最初提供的頒發(fā)者 URL,因此它會(huì)與 cleanIssuer 進(jìn)行匹配,從而導(dǎo)致所描述的問(wèn)題。解決這個(gè)問(wèn)題的最簡(jiǎn)單方法是在fromOidcIssuerLocation()中進(jìn)行清理,然后仍然可以使用原始版本進(jìn)行匹配。
另一條注釋與您提出的第一個(gè)問(wèn)題相關(guān)。
如果我知道您的 API 標(biāo)識(shí)符 + 您的租戶 ID,我可以使用客戶端憑據(jù)獲取您的 API 的訪問(wèn)令牌!令牌不會(huì)包含范圍或角色,它不能。因此,檢查是否存在有效的委派權(quán)限(也稱為范圍)或有效的應(yīng)用程序權(quán)限(在角色聲明中)至關(guān)重要。
看看這個(gè)特定的代碼。
JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
TokenValidationParameters validationParameters = new TokenValidationParameters
{
// We accept both the App Id URI and the AppId of this service application
ValidAudiences = new[] { audience, clientId },
// Supports both the Azure AD V1 and V2 endpoint
ValidIssuers = new[] { issuer, $"{issuer}/v2.0" },
IssuerSigningKeys = signingKeys
};
添加回答
舉報(bào)