3 回答

TA貢獻(xiàn)2003條經(jīng)驗(yàn) 獲得超2個(gè)贊
是的,您可以使用 OAuth 2.0 客戶端憑據(jù)流程和服務(wù)帳戶。
Keycloak 建議使用 3 種方法來(lái)保護(hù) SpringBoot REST 服務(wù)的安全:
帶有 Keycloak Spring Boot 適配器
帶 keycloak Spring 安全適配器
與 OAuth2 / OpenID 連接
請(qǐng)注意將您的客戶端配置為:
訪問(wèn)類型:機(jī)密
授權(quán):已啟用
服務(wù)帳戶(OAuth 客戶端憑據(jù)流程):已啟用
請(qǐng)注意將您的目標(biāo)服務(wù)配置為:
訪問(wèn)類型:僅承載
因此,調(diào)用者應(yīng)該是confidential
,目標(biāo)服務(wù)應(yīng)該是bearer-only
。
創(chuàng)建您的用戶、角色、映射器...并將角色分配給您的用戶。
檢查您的 spring 項(xiàng)目中是否有此依賴項(xiàng):
<dependency>
? <groupId>org.springframework.boot</groupId>
? <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
? <groupId>org.springframework.security.oauth.boot</groupId>
? <artifactId>spring-security-oauth2-autoconfigure</artifactId>
</dependency>
配置要在 REST 客戶端 (application.properties) 中使用的身份驗(yàn)證,例如:
security.oauth2.client.client-id=employee-service
security.oauth2.client.client-secret=68977d81-c59b-49aa-aada-58da9a43a850
security.oauth2.client.user-authorization-uri=${rest.security.issuer-uri}/protocol/openid-connect/auth
security.oauth2.client.access-token-uri=${rest.security.issuer-uri}/protocol/openid-connect/token
security.oauth2.client.scope=openid
security.oauth2.client.grant-type=client_credentials
JwtAccessTokenCustomizer像 Arun 的示例一樣實(shí)現(xiàn)您的SecurityConfigurer (ResourceServerConfigurerAdapter) 。
最后實(shí)現(xiàn)你的服務(wù)控制器:
@RestController
@RequestMapping("/api/v1/employees")
public class EmployeeRestController {
? @GetMapping(path = "/username")
? @PreAuthorize("hasAnyAuthority('ROLE_USER')")
? public ResponseEntity<String> getAuthorizedUserName() {
? ? return ResponseEntity.ok(SecurityContextUtils.getUserName());
? }
? @GetMapping(path = "/roles")
? @PreAuthorize("hasAnyAuthority('ROLE_USER')")
? public ResponseEntity<Set<String>> getAuthorizedUserRoles() {
? ? return ResponseEntity.ok(SecurityContextUtils.getUserRoles());
? }
}

TA貢獻(xiàn)1873條經(jīng)驗(yàn) 獲得超9個(gè)贊
按照@dmitri-algazin 實(shí)施工作流程,您基本上有兩個(gè)選擇:
如果您想涵蓋除 Keycloak 之外的其他 IdM,它以某種方式解決了單一責(zé)任原則,我會(huì)使用RestTemplate. 您可以在下面找到變量:
//Constants
@Value("${keycloak.url}")
private String keycloakUrl;
@Value("${keycloak.realm}")
private String keycloakRealm;
@Value("${keycloak.client_id}")
private String keycloakClientId;
RestTemplate restTemplate = new RestTemplate();
private static final String BEARER = "BEARER ";
首先,您需要生成訪問(wèn)令牌:
@Override
public AccessTokenResponse login(KeycloakUser user) throws NotAuthorizedException {
try {
String uri = keycloakUrl + "/realms/" + keycloakRealm +
"/protocol/openid-connect/token";
String data = "grant_type=password&username="+
user.getUsername()+"&password="+user.getPassword()+"&client_id="+
keycloakClientId;
HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type", "application/x-www-form-urlencoded");
HttpEntity<String> entity = new HttpEntity<String>(data, headers);
ResponseEntity<AccessTokenResponse> response = restTemplate.exchange(uri,
HttpMethod.POST, entity, AccessTokenResponse.class);
if (response.getStatusCode().value() != HttpStatus.SC_OK) {
log.error("Unauthorised access to protected resource", response.getStatusCode().value());
throw new NotAuthorizedException("Unauthorised access to protected resource");
}
return response.getBody();
} catch (Exception ex) {
log.error("Unauthorised access to protected resource", ex);
throw new NotAuthorizedException("Unauthorised access to protected resource");
}
}
然后使用令牌,您可以從用戶那里檢索信息:
@Override
public String user(String authToken) throws NotAuthorizedException {
if (! authToken.toUpperCase().startsWith(BEARER)) {
throw new NotAuthorizedException("Invalid OAuth Header. Missing Bearer prefix");
}
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", authToken);
HttpEntity<String> entity = new HttpEntity<>(headers);
ResponseEntity<AccessToken> response = restTemplate.exchange(
keycloakUrl + "/realms/" + keycloakRealm + "/protocol/openid-connect/userinfo",
HttpMethod.POST,
entity,
AccessToken.class);
if (response.getStatusCode().value() != HttpStatus.SC_OK) {
log.error("OAuth2 Authentication failure. "
+ "Invalid OAuth Token supplied in Authorization Header on Request. Code {}", response.getStatusCode().value());
throw new NotAuthorizedException("OAuth2 Authentication failure. "
+ "Invalid OAuth Token supplied in Authorization Header on Request.");
}
log.debug("User info: {}", response.getBody().getPreferredUsername());
return response.getBody().getPreferredUsername();
}
您可以將此 URL 替換為 @dimitri-algazin 提供的 URL,以檢索所有用戶信息。
可以使用 Keycloak 依賴項(xiàng):
<!-- keycloak -->
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-admin-client</artifactId>
<version>3.4.3.Final</version>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-client</artifactId>
<version>3.1.4.Final</version>
</dependency>
并使用類來(lái)生成令牌:
Keycloak keycloak = KeycloakBuilder
.builder()
.serverUrl(keycloakUrl)
.realm(keycloakRealm)
.username(user.getUsername())
.password(user.getPassword())
.clientId(keycloakClientId)
.resteasyClient(new ResteasyClientBuilder().connectionPoolSize(10).build())
.build();
return keycloak.tokenManager().getAccessToken();
示例摘自此處。我們還將鏡像上傳到 Docker Hub,以方便與 Keycloak 交互。因此我們從選項(xiàng) 2) 開始。目前,我們正在覆蓋其他 IdM,我們選擇了選項(xiàng) 1),以避免包含額外的依賴項(xiàng)。結(jié)論:
如果您堅(jiān)持使用 Keycloak,我會(huì)選擇選項(xiàng) 2 ,因?yàn)轭惏?Keycloak 工具的額外功能。我會(huì)選擇選項(xiàng) 1以獲得更多的覆蓋范圍和其他 OAuth 2.0 工具。

TA貢獻(xiàn)1833條經(jīng)驗(yàn) 獲得超4個(gè)贊
我們有類似的需求,通過(guò)用戶 uuid 獲取用戶電子郵件。
創(chuàng)建服務(wù)用戶,確保用戶具有“領(lǐng)域管理”->“查看用戶”角色(也可能是查詢用戶)
過(guò)程很簡(jiǎn)單:使用服務(wù)用戶登錄 keycloak(將密碼和/或用戶名編碼在屬性文件中),使用授權(quán)標(biāo)頭中的 accessToken 向 keycloak 發(fā)出請(qǐng)求
獲取 http://{yourdomainadress}/auth/admin/realms/{yourrealmname}/users/{userId}
使用REST API登錄keycloak的方法:
POST http://{yourdomainadress}/auth/realms/{yourrealmname}/protocol/openid-connect/token
標(biāo)題:
內(nèi)容類型:application/x-www-form-urlencoded
正文 x-www-form-urlencoded:
client_id:您的客戶
用戶名:您正在使用的用戶
密碼:用戶密碼
grant_type:密碼
client_secret:11112222-3333-4444-5555-666666666666(如果客戶端“訪問(wèn)類型”=“機(jī)密”,則需要客戶端密鑰)
很快:確保您的服務(wù)用戶分配了正確的角色來(lái)執(zhí)行操作、登錄、查詢 keycloak(檢查文檔以獲取正確的查詢 url 和參數(shù),總是具有挑戰(zhàn)性)
添加回答
舉報(bào)