У меня есть монолитное приложение JHipster с oauth2, запускающим Keycloak локально.
Я не знаю, как именно jhipster должен работать с oauth2... сначала я думал, что он создаст пользователя автоматически, но это не так, поэтому я настроил keycloak: я создал область jhipster, клиент web_app, клиентские роли ROLE_ADMIN. и ROLE_USER, и пользователи admin и user с их правильными ролями.
Проблема в том, что когда я вхожу в систему как администратор, он не распознается как ROLE_ADMIN, в результате чего я не могу получить доступ к меню администратора. Итак, я начал просматривать код, пытаясь понять, как Jhipster получает учетные данные от Keycloak, и я понял, что объект OAuth2Authentication в AccountResource.java приносит не ROLE_ADMIN, а ROLE_USER, который я не понимаю, почему. Объект OAuth2Authentication в json выглядит так:
{
"authorities": [
{
"authority": "ROLE_USER"
}
],
"details": {
"remoteAddress": "0:0:0:0:0:0:0:1",
"sessionId": "rkkveY_Xa5zFFd0SKu9Of_FLGRnbdiTPHdnpj4gc",
"tokenValue": "eyJhbGciOiJSUzI1...",
"tokenType": "bearer",
"decodedDetails": null
},
"authenticated": true,
"userAuthentication": {
"authorities": [
{
"authority": "ROLE_USER"
}
],
"details": {
"sub": "f348bbbb-9441-4543-9940-9da31e50d877",
"email _verified": true,
"name": "Admin Administrator",
"preferred_username": "admin",
"given_name": "Admin",
"family_name": "Administrator",
"email": "admin@localhost"
},
"authenticated": true,
"principal": "Admin Administrator",
"credentials": "N/A",
"name": "Admin Administrator"
},
"clientO nly": false,
"principal": "Admin Administrator",
"oauth2Request": {
"clientId": "web_app",
"scope": [
],
"requestParameters": {
},
"resourceIds": [
],
"authorities": [
],
"approved": true,
"refresh": false,
"redirectUri": null,
"responseTypes": [
],
"extensions": {
},
"grantType": null,
"refreshTok enRequest": null
},
"credentials": "",
"name": "Admin Administrator"
}
вот yo-rc.json:
{
"generator-jhipster": {
"promptValues": {
"packageName": "xxxxxxxxxxx"
},
"jhipsterVersion": "5.7.2",
"applicationType": "monolith",
"baseName": "XXXXXXXXXX",
"packageName": "xxxxxxxxxxxxxx",
"packageFolder": "xxxxxxxxxxxxxx",
"serverPort": "8080",
"authenticationType": "oauth2",
"cacheProvider": "ehcache",
"enableHibernateCache": true,
"websocket": false,
"databaseType": "sql",
"devDatabaseType": "h2Disk",
"prodDatabaseType": "mysql",
"searchEngine": false,
"messageBroker": false,
"serviceDiscoveryType": false,
"buildTool": "maven",
"enableSwaggerCodegen": false,
"clientFramework": "angularX",
"useSass": false,
"clientPackageManager": "npm",
"testFrameworks": [],
"jhiPrefix": "jhi",
"otherModules": [],
"enableTranslation": false
}
}
Как я могу это исправить?




У меня была та же проблема, я думаю, это связано с тем, что Keycloak дает роли клиента в другом утверждении «resource_access», а библиотека Spring Boot Security Oauth2 не читает роли здесь.
Я изменил UserService.java, чтобы попытаться сначала прочитать это утверждение и подзначение, соответствующее clientId, путем декодирования токена JWT, это чище, потому что он читает только клиентские роли.
public UserDTO getUserFromAuthentication(OAuth2Authentication authentication) {
OAuth2AuthenticationDetails oauth2AuthenticationDetails = (OAuth2AuthenticationDetails) authentication
.getDetails(); // should be an OAuth2AuthenticationDetails
Map<String, Object> details = (Map<String, Object>) authentication.getUserAuthentication().getDetails();
User user = getUser(details);
String tokenValue = oauth2AuthenticationDetails.getTokenValue();
DecodedJWT jwt = JWT.decode(tokenValue);
Map<String, Object> resourceAccessClaim = jwt.getClaim("resource_access").asMap();
String clientId = authentication.getOAuth2Request().getClientId();
if (resourceAccessClaim.containsKey(clientId)) {
((Map<String, Object>) resourceAccessClaim.get(clientId)).values().forEach(rn -> {
user.setAuthorities(extractAuthorities((List<String>) rn));
});
}
if (user.getAuthorities() == null || user.getAuthorities().size() == 0) {
user.setAuthorities(extractAuthorities(authentication, details));
}
// convert Authorities to GrantedAuthorities
Set<GrantedAuthority> grantedAuthorities = user.getAuthorities().stream().map(Authority::getName)
.map(SimpleGrantedAuthority::new).collect(Collectors.toSet());
...
В администрировании keycloak перейдите в раздел «Клиенты» >> YOUR_CLIENT >> Mappers -> Добавить новый преобразователь -> Установите тип преобразователя на «Роль клиента пользователя», а «Имя утверждения токена» установите на «полномочия» и укажите тип JSON на строку.
спасибо за ответ, к сожалению, я все еще учусь использовать картографы в keycloak, и теперь у меня другая проблема с более новой версией JHipster. Буду благодарен, если проверите: stackoverflow.com/questions/56437540/…
Новое решение
Вы можете увидеть больше по ссылке ниже конфигурации Keycloak, поэтому он отправляет роли в токене, и нам не нужно менять исходный код.
Старое решение. Не так хорошо работает, потому что РОЛИ не идут в обычных привилегиях предоставления В UserService.java я изменил так:
public UserDTO getUserFromAuthentication(final AbstractAuthenticationToken authToken) {
Map<String, Object> attributes;
if (authToken instanceof OAuth2AuthenticationToken) {
attributes = ((OAuth2AuthenticationToken) authToken).getPrincipal().getAttributes();
} else if (authToken instanceof JwtAuthenticationToken) {
attributes = ((JwtAuthenticationToken) authToken).getTokenAttributes();
} else {
throw new IllegalArgumentException("AuthenticationToken is not OAuth2 or JWT!");
}
User user = getUser(attributes);
JSONArray auths = (JSONArray) attributes.get("authorities");
Set<Authority> authorities = new HashSet<Authority>();
for(int i=0; i<auths.size(); i++){
Authority au = new Authority();
au.setName(auths.get(i).toString());
authorities.add(au);
}
user.setAuthorities(authorities);
return new UserDTO(syncUserWithIdP(attributes, user));
}
и установите «полномочия» в имени претензии токена, например:

Привет @Fabrice Dominguez Я пытался установить ваш код, но он говорит, что этот класс OAuth2Authentication или OAuth2AuthenticationDetails не существует. Какие-либо предложения