创建keycloak用户、角色、用户角色映射关系(Java API + Rest API实现)

@Slf4j
@Service
public class KeyCloakService {
    private RestTemplate restTemplate;
    private KeycloakAdminClient keycloakAdminClient;
    /**
     * kc新增用户
     *
     * @param username
     */
 public Boolean addUser(String username) {
        RealmResource realmResource = keycloakAdminClient.getEdge();
        UsersResource userResource = realmResource.users();
        UserRepresentation newUser = new UserRepresentation();
        newUser.setUsername(username);
        newUser.setEnabled(true);
        newUser.setFirstName("nickName");
        Map<String, List<String>> attributeMap = Maps.newHashMap();
        attributeMap.put("nickName", Collections.singletonList("nickName"));
        newUser.setAttributes(attributeMap);
        // 创建用户
        Response createUserResponse = userResource.create(newUser);
        // 判断创建用户状态
        Response.StatusType createUserStatus = createUserResponse.getStatusInfo();
        // *返回请求的地址
        URI location = createUserResponse.getLocation();
        String userId;
        if (Response.Status.CREATED.getStatusCode() == createUserStatus.getStatusCode()) {
            log.info("keycloak client 创建用户成功,创建用户的URI:{}", location);
            // 获取用户id
            userId = createUserResponse.getLocation().getPath().replaceAll(".*/([^/]+)$", "$1");
            // 设置密码
            CredentialRepresentation passwordCred = new CredentialRepresentation();
            passwordCred.setTemporary(false);
            passwordCred.setType(CredentialRepresentation.PASSWORD);
            // 初始密码
            passwordCred.setValue("123456");
            userResource.get(userId).resetPassword(passwordCred);
            log.info("keycloak 创建{}用户成功", username);
        } else {
            log.error("新增{}用户异常", username);
        }
        return true;
    }


    /**
     * kc新增角色
     *
     * @param sysUserEntity
     */
    private void addRealmRole(Keycloak keycloak, SysRoleEntity roleEntity) {
        List<RoleRepresentation> roleRepresentations = keycloak.realm(workPropertise.getRealm()).roles().list();
        boolean hasRepeat = roleRepresentations.stream().anyMatch(o -> o.getName().equals(roleEntity.getName()));
//        if (hasRepeat){
//            // 删除域角色
//          keycloak.realm(workPropertise.getRealm()).roles().deleteRole(role.getName());
//        }
        if (!hasRepeat) {
            // 创建keycloak域角色
            Map<String, List<String>> attributesMap = new HashMap<>();
            // 角色额外属性
            attributesMap.put("roleCode", Collections.singletonList(roleEntity.getRoleCode()));
            attributesMap.put("allWorkCenter", Collections.singletonList(String.valueOf(roleEntity.getAllWorkCenter())));
            attributesMap.put("roleLevel", Collections.singletonList(String.valueOf(roleEntity.getRoleLevel())));
            attributesMap.put("status", Collections.singletonList(EnabledEnum.ENABLE.getCode()));
            RoleRepresentation role = new RoleRepresentation();
            role.setName(roleEntity.getName());
            role.setDescription("xxx");
            role.setComposite(false);
            role.setAttributes(attributesMap);
            keycloak.realm(workPropertise.getRealm()).roles().create(role);
        }
    }


    /**
     * kc新增角色用户映射关系
     *
     * @param sysUserEntity
     */
 public void syncUserRoleMapping(SysUserEntity sysUserEntity) {
         //务必获取Master realm admin-cli token (!其他token可能权限不足)
        String masterToken = iAuthService.getMasterToken();
        Keycloak keycloak = keycloakAdminClient.getKeycloak();
        // 构建keycloak域角色映射url
        // http://127.0.0.1:8411/auth/admin/realms/{realm}/users/{userId}/role-mappings/realm
        String url = workPropertise.getAuthServerUrl() + "admin/realms/" + workPropertise.getRealm() + "/users/" + sysUserEntity.getKeycloakId() + "/role-mappings/realm";
        // 获取用户角色名称列表
        List<String> roleNames = sysRoleMapper.selectUserRoleByUserId(sysUserEntity.getId());
        ArrayList<RoleRepresentation> roleMappingList = new ArrayList<>();
        for (String roleName : roleNames) {
            // 获取域角色by name
            List<RoleRepresentation> list = keycloak.realm(workPropertise.getRealm()).roles().list(roleName, true);
            roleMappingList.addAll(list);
        }
        String roleMappingJson = JSON.toJSONString(roleMappingList);
        HttpHeaders httpHeaders = new HttpHeaders();
        //Authorization
        httpHeaders.add(HttpHeaders.AUTHORIZATION, masterToken);
        //json
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        HttpEntity<String> request = new HttpEntity<>(roleMappingJson, httpHeaders);
        HttpHeaders getHeader = new HttpHeaders();
        getHeader.add(HttpHeaders.AUTHORIZATION, masterToken);
        HttpEntity<MultiValueMap<String, Object>> httpEntity = new HttpEntity<>(getHeader);
        try {
            // *清除旧角色映射
            ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.GET, httpEntity, String.class);
            JSONArray jsonArray = JSONArray.parseArray(responseEntity.getBody());
            if (jsonArray != null) {
                List<RoleRepresentation> deleteRoles = jsonArray.toJavaList(RoleRepresentation.class);
                String deleteMapping = JSON.toJSONString(deleteRoles);
                HttpEntity<String> deleteRequest = new HttpEntity<>(deleteMapping, httpHeaders);
                // 组装调用keycloak REST API
                restTemplate.exchange(url, HttpMethod.DELETE, deleteRequest, String.class);
            }
            //创建新角色映射
            ResponseEntity<String> addResponse = restTemplate.exchange(url, HttpMethod.POST, request, String.class);
            log.debug("调用keycloak API成功,返回信息:{}", addResponse);
        } catch (Exception e) {
            log.error("调用keycloak API同步域角色映射失败,失败信息为:", e);
        }

    }

    /**
     * 此token为Master realm admin-cli token
     * 默认过期时间为60sec 若程序执行时间超过60sec 可以设置keycloak:
     * Master realm Admin-cli clients Advanced Settings Access Token Lifespan 10 min
     *
     * @return Master token
     */

    public String getMasterToken() {
        String token = null;
        // workPropertise.getAuthServerUrl() = http://127.0.0.1:8411/auth/
        String authServerUrl = workPropertise.getAuthServerUrl() + "realms/master/protocol/openid-connect/token";
        MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
        map.add("client_id","admin-cli");
        // Master realm admin的用户名密码
        map.add("username", "admin");
        map.add("password", "123456");
        map.add("grant_type", "password");
        HttpHeaders httpHeaders = new HttpHeaders();
        // x-www-form-urlencoded
        httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        HttpEntity<MultiValueMap<String, String>> multiValueMapHttpEntity = new HttpEntity<>(map, httpHeaders);
        try {
            ResponseEntity<String> responseEntity = restTemplate.exchange(authServerUrl, HttpMethod.POST, multiValueMapHttpEntity, String.class);
            JSONObject jsonObject = JSON.parseObject(responseEntity.getBody());
            // 获取值
            token = jsonObject.getString("access_token");
            log.debug("调用keycloak API获取Master token成功: {}", jsonObject);
        } catch (Exception e) {
            log.error("调用keycloak API获取Master token失败: ", e);
        }
        return "Bearer " + token;
    }

}

 

import com.yelink.dfs.service.impl.common.WorkPropertise;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
import org.keycloak.admin.client.Keycloak;
import org.keycloak.admin.client.KeycloakBuilder;
import org.keycloak.admin.client.resource.RealmResource;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

/**
 * @Description: keyCloak初始化
 */
@AllArgsConstructor
@Component
@Getter
@Setter
public class KeycloakAdminClient {

    @Resource
    private WorkPropertise workPropertise;
    private Keycloak keycloak;
    private RealmResource edge;
    private RealmResource master;

    /**
     * 初始化keycloak的方法
     */
    @PostConstruct
    private void init() {
        keycloak = Keycloak.getInstance(
                // keycloak 服务地址
                workPropertise.getAuthServerUrl(),
                // keycloak 管理员的域
                workPropertise.getTargetRealm(),
                //你自己创建的管理员的账号
                workPropertise.getAdminUserName(),
                // 你自己创建的管理员的密码
                workPropertise.getAdminPassword(),
                // admin-cli 客户端
                workPropertise.getResource()
        );
        // 你创建的realm
        edge = keycloak.realm(workPropertise.getRealm());
        master = keycloak.realm(workPropertise.getTargetRealm());
    }


}

<!--pom.xml-->

    <properties>
        <keycloak.version>15.0.1</keycloak.version>
    </properties>

    <dependencies>
            <dependency>
                <groupId>org.keycloak</groupId>
                <artifactId>keycloak-admin-client</artifactId>
                <version>${keycloak.version}</version>
            </dependency>
            <dependency>
                <groupId>org.keycloak</groupId>
                <artifactId>keycloak-spring-security-adapter</artifactId>
                <version>${keycloak.version}</version>
            </dependency>
            <dependency>
                <groupId>org.keycloak</groupId>
                <artifactId>keycloak-spring-boot-starter</artifactId>
                <version>${keycloak.version}</version>
            </dependency>
            <dependency>
            <groupId>org.keycloak</groupId>
            <artifactId>keycloak-admin-client</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>activation</artifactId>
                    <groupId>javax.activation</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.keycloak</groupId>
            <artifactId>keycloak-spring-security-adapter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.keycloak</groupId>
            <artifactId>keycloak-spring-boot-starter</artifactId>
        </dependency>
    </dependencies>

 

参考:

keycloak REST API
https://www.keycloak.org/docs-api/20.0.3/rest-api/index.html

keycloak 授权服务指南
https://www.keycloak.org/docs/latest/authorization_services/

keycloak Guides
https://www.keycloak.org/guides#getting-started

keycloak java docs
https://www.keycloak.org/docs-api/20.0.3/javadocs/index.html

 

posted @ 2023-02-08 17:58  java从精通到入门  阅读(746)  评论(0编辑  收藏  举报