[英]Enable role authentication with spring boot (security) and keycloak?
[英]Spring Boot with Spring Security and Keycloak only providing Anonymous Authentication Token
所以我按照指南設置了 Keycloak 來保護我的 Spring Boot REST API 和 Spring Security。 以前,我的應用程序依賴於標准用戶詳細信息服務來驗證用戶身份。 我的代碼依賴於能夠訪問當前登錄用戶的用戶名。 但是,現在我切換到 Keycloak,我只收到用戶名“anonymousUser”。
如何為以下代碼正確配置它以返回首選用戶名:
public static String getCurrentUsername() {
return (String) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
}
我嘗試在Keycloak上修改客戶端和用戶的配置,但即使是例如,添加角色也沒有效果。 Spring 引導僅返回 [ANONYMOUS_USER] 的角色。
您不可能從AnonymousAuthenticationToken
獲得有關當前用戶的任何信息:當請求未成功授權(無法識別用戶)時,此Authentication
實現將置於安全上下文中。 這意味着:
有關如何使用 Keycloak 配置 Spring-boot 3 資源服務器(和客戶端)的基本信息,請參閱我對這個問題的回答: Use Keycloak Spring Adapter with Spring Boot 3
Spring-security 資源服務器中成功的 OAuth2 授權的默認Authentication
是JwtAuthenticationToken
,它返回一個Jwt
實例作為principal
。 您可以從此Jwt
實例獲取任何訪問令牌聲明。 這是帶有preferred_username
的示例。 在諸如https://jwt.io之類的工具中打開一個訪問令牌,以查找具有您要查找的用戶名值的聲明的名稱(它也可以是sub
, email
或您在 Keycloak 中配置的任何私人聲明)
((Jwt) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getClaims().get(StandardClaimNames.PREFERRED_USERNAME);
如果您希望getPrincipal()
返回用戶名而不是Jwt
實例,則必須提供您自己的Authentication
實現。 您可以使用JwtAuthenticationToken
作為基礎(但這不是最佳選擇,請參閱下面的注釋):
public class MyAuthentication extends JwtAuthenticationToken {
public MyAuthentication(Jwt jwt, Collection<? extends GrantedAuthority> authorities) {
super(jwt, authorities);
}
@Override
public String getPrincipal() {
return getToken().getClaimAsString(StandardClaimNames.PREFERRED_USERNAME);
}
}
只需根據我上面鏈接的答案改編Jwt2AuthenticationConverter
@Bean
public Jwt2AuthenticationConverter authenticationConverter(Jwt2AuthoritiesConverter authoritiesConverter) {
return jwt -> new MyAuthentication(jwt, authoritiesConverter.convert(jwt));
}
您最好使用authentication.getName()
而不是authentication.getPrincipal()
來訪問用戶名。 principal
在Authentication
中的類型為Object
,這使得您的表達式非常脆弱:您絕對可以獲得任何類型的數據作為 principal(取決於安全上下文中的身份驗證類型)並且在某些情況下您無法真正控制它(例如由於未經授權的請求,您當前擁有的AnonymousAuthenticationToken
實例)。
但是, JwtAuthenticationToken::getName
返回主題( sub
聲明),因此您仍然必須提供自己的Authentication
實現才能成功授權以在新的 @Override getName()
中返回preferred_username
。 MyAuthentication
將是:
public class MyAuthentication extends JwtAuthenticationToken {
public MyAuthentication(Jwt jwt, Collection<? extends GrantedAuthority> authorities) {
super(jwt, authorities);
}
//Note that this time getName() is overriden instead of getPrincipal()
@Override
public String getName() {
return getToken().getClaimAsString(StandardClaimNames.PREFERRED_USERNAME);
}
}
在請求授權成功的情況下,使用相同的Jwt2AuthenticationConverter
bean 從默認的JwtAuthenticationToken
切換到MyAuthentication
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.