Instruction:
作为 Java 安全专家，检测此代码中的安全漏洞：
## 内容1
### 文件路径：
tapestry-http/src/main/java/org/apache/tapestry5/http/ContentType.java
### 代码内容：
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package org.apache.tapestry5.http;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.tapestry5.commons.util.CollectionFactory;
import org.apache.tapestry5.http.internal.TapestryHttpInternalConstants;
import org.apache.tapestry5.ioc.internal.util.InternalUtils;

/**
 * Represents an HTTP content type. Allows to set various elements like the MIME type, the character set, and other
 * parameters. This is similar to a number of other implementations of the same concept in JAF, etc. We have created
 * this simple implementation to avoid including the whole libraries.
 *
 * As of Tapestry 5.4, this is now an immutable data type.
 */
public final class ContentType
{
    private final String baseType;

    private final String subType;

    private final Map<String, String> parameters;

    private static final Pattern PATTERN = Pattern.compile("^(.+)/([^;]+)(;(.+=[^;]+)){0,5}$");

    /**
     * Creates a new content type from the argument. The format of the argument has to be basetype/subtype(;key=value)*
     *
     * @param contentType
     *         the content type that needs to be represented
     */
    public ContentType(String contentType)
    {
        Matcher matcher = PATTERN.matcher(contentType);

        if (!matcher.matches())
        {
            throw new IllegalArgumentException(String.format("Not a parseable content type '%s'.", contentType));
        }

        this.baseType = matcher.group(1);
        this.subType = matcher.group(2);
        this.parameters = parseKeyValues(matcher.group(4));
    }

    private ContentType(String baseType, String subType, Map<String, String> parameters)
    {
        this.baseType = baseType;
        this.subType = subType;
        this.parameters = parameters;
    }

    private static Map<String, String> parseKeyValues(String keyValues)
    {
        if (keyValues == null)
        {
            return Collections.emptyMap();
        }

        Map<String, String> parameters = CollectionFactory.newCaseInsensitiveMap();

        StringTokenizer tk = new StringTokenizer(keyValues, ";");

        while (tk.hasMoreTokens())
        {
            String token = tk.nextToken();
            int sep = token.indexOf('=');

            parameters.put(token.substring(0, sep), token.substring(sep + 1));
        }

        return parameters;
    }

    /**
     * Returns true only if the other object is another instance of ContentType, and has the same baseType, subType and
     * set of parameters.
     */
    @Override
    public boolean equals(Object o)
    {
        if (o == null) return false;

        if (o.getClass() != this.getClass()) return false;

        ContentType ct = (ContentType) o;

        return baseType.equals(ct.baseType) && subType.equals(ct.subType) && parameters.equals(ct.parameters);
    }

    @Override
    public int hashCode()
    {
        return Objects.hash(baseType, subType, parameters);
    }

    /**
     * @return the base type of the content type
     */
    public String getBaseType()
    {
        return baseType;
    }

    /**
     * @return the sub-type of the content type
     */
    public String getSubType()
    {
        return subType;
    }

    /**
     * @return the MIME type of the content type (the base type and the subtype, seperated with a '/').
     */
    public String getMimeType()
    {
        return baseType + "/" + subType;
    }

    /**
     * @return the list of names of parameters in this content type, in alphabetical order.
     */
    public List<String> getParameterNames()
    {
        return InternalUtils.sortedKeys(parameters);
    }

    /**
     * @return the character set (the "charset" parameter) or null.
     */
    public String getCharset()
    {
        return getParameter(TapestryHttpInternalConstants.CHARSET_CONTENT_TYPE_PARAMETER);
    }

    /**
     * @param key
     *         the name of the content type parameter
     * @return the value of the content type parameter
     */
    public String getParameter(String key)
    {
        assert key != null;
        return parameters.get(key);
    }

    private String unparse()
    {
        StringBuilder buffer = new StringBuilder(getMimeType());

        for (String parameterName : getParameterNames())
        {
            buffer.append(';');
            buffer.append(parameterName);
            buffer.append('=');
            buffer.append(parameters.get(parameterName));
        }

        return buffer.toString();
    }

    /**
     * Returns a new content type with the indicated parameter.
     *
     * @since 5.4
     */
    public ContentType withParameter(String key, String value)
    {
        assert InternalUtils.isNonBlank(key);
        assert InternalUtils.isNonBlank(value);

        Map<String, String> newParameters = CollectionFactory.newCaseInsensitiveMap();

        newParameters.putAll(parameters);
        newParameters.put(key, value);

        return new ContentType(baseType, subType, newParameters);
    }

    public ContentType withCharset(String charset)
    {
        return withParameter(TapestryHttpInternalConstants.CHARSET_CONTENT_TYPE_PARAMETER, charset);
    }

    /**
     * @return the string representation of this content type.
     */
    @Override
    public String toString()
    {
        return unparse();
    }

    /**
     * @return true if the content type includes parameters (such as 'charset').
     * @since 5.4
     */
    public boolean hasParameters()
    {
        return !parameters.isEmpty();
    }
}

Output:
【漏洞类型】安全审计漏洞
【严重性】Medium
【漏洞摘要】原始代码中的`ContentType`类存在一个安全审计漏洞，根源于其正则表达式中的上限设置。原始正则表达式`^(.+)/([^;]+)(;(.+=[^;]+)){0,5}$`允许最多5个参数，这可能导致解析性能问题或潜在的安全风险，特别是当参数数量异常增加时。修复的代码将上限调整为3个参数，即`^(.+)/([^;]+)(;(.+=[^;]+)){0,3}$`，以限制参数的最大数量，从而减少潜在的安全风险和性能问题。
【关键代码模式】Pattern类的正则表达式、`parseKeyValues`函数、`StringTokenizer`类、`getParameterNames`函数。
【修复方法说明】通过减少正则表达式中的参数数量上限，限制了可解析的内容类型参数的数量，从而防止了潜在的解析性能问题和安全风险。


Instruction:
作为 Java 安全专家，检测此代码中的安全漏洞：
## 内容1
### 文件路径：
api/src/main/java/io/github/karlatemp/unsafeaccessor/Root.java
### 代码内容：
package io.github.karlatemp.unsafeaccessor;

import org.jetbrains.annotations.Contract;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.util.function.Consumer;

/**
 * JVM Root Access.
 *
 * @since 1.1.0
 */
@SuppressWarnings("DefaultAnnotationParam")
public class Root {
    @Contract(pure = false)
    public static Unsafe getUnsafe() {
        return Unsafe.getUnsafe();
    }

    /**
     * Return the trusted lookup.
     *

     * Use {@link #getTrusted(Class)}
     *
     * @return MethodHandles.Lookup.IMPL_LOOKUP
     */
    @Deprecated
    @Contract(pure = true)
    public static MethodHandles.Lookup getTrusted() {
        SecurityCheck.LIMITER.preGetTrustedLookup(null);
        return RootLookupHolder.ROOT;
    }

    @Contract(pure = true)
    public static MethodHandles.Lookup getTrusted(Class<?> k) {
        SecurityCheck.LIMITER.preGetTrustedLookup(k);
        return RootLookupHolder.trustedIn(k);
    }

    @Contract(pure = false, value = "null, _ -> fail")
    public static void setAccessible(AccessibleObject object, boolean isAccessible) {
        OpenAccess.openAccess(object, isAccessible);
    }

    @Contract(pure = false, value = "null -> fail")
    public static <T extends AccessibleObject> T openAccess(T object) {
        setAccessible(object, true);
        return object;
    }

    static class RootLookupHolder {
        static final MethodHandles.Lookup ROOT;

        static boolean isOpenJ9vm() {
            if (ROOT.lookupClass() == MethodHandle.class) {
                int modes = ROOT.lookupModes();
                return modes == 0x40 // AdoptOpenJDK - jdk 11.0.9.11 openj9
                        || modes == 0x80 // Eclipse OpenJ9 VM - 11.0.12.7-openj9
                        ;
            }
            return false;
        }

        static final boolean isOpenj9;
        static final long accessMode;

        static {
            try {
                Unsafe unsafe = getUnsafe();
                MethodHandles.Lookup lookup;
                try {
                    Field field = MethodHandles.Lookup.class.getDeclaredField("IMPL_LOOKUP");
                    openAccess(field);
                    lookup = (MethodHandles.Lookup) field.get(null);
                } catch (Throwable any) {
                    if (unsafe.isJava9()) {
                        lookup = MethodHandles.lookup();
                        unsafe.putReference(
                                lookup,
                                unsafe.objectFieldOffset(MethodHandles.Lookup.class, "lookupClass"),
                                Object.class
                        );
                        unsafe.putInt(
                                lookup,
                                unsafe.objectFieldOffset(MethodHandles.Lookup.class, "allowedModes"),
                                -1
                        );
                    } else {
                        throw any;
                    }
                }
                ROOT = lookup;
            } catch (Exception e) {
                throw new ExceptionInInitializerError(e);
            }
            isOpenj9 = isOpenJ9vm();
            if (isOpenj9) {
                accessMode = Unsafe.getUnsafe0().objectFieldOffset(MethodHandles.Lookup.class, "accessMode");
            } else {
                accessMode = -1;
            }
        }

        static MethodHandles.Lookup trustedIn(Class<?> target) {
            if (target == null) return ROOT;
            if (isOpenj9) {
                MethodHandles.Lookup lookup = ROOT.in(target);
                Unsafe.getUnsafe0().putLong(lookup, accessMode, ROOT.lookupModes());
                return lookup;
            }
            return ROOT;
        }
    }

    static class OpenAccess {
        private static final Unsafe usf = Unsafe.getUnsafe0();
        private static final long overrideOffset;

        static {
            if (usf.isJava9()) {
                overrideOffset = usf.objectFieldOffset(AccessibleObject.class, "override");
            } else {
                try {
                    Field field = AccessibleObject.class.getDeclaredField("override");
                    overrideOffset = usf.objectFieldOffset(field);
                } catch (Throwable throwable) {
                    throw new ExceptionInInitializerError(throwable);
                }
            }
        }

        static void openAccess0(AccessibleObject object, boolean isAccessible) {
            if (object == null) throw new NullPointerException("object");
            usf.putBoolean(object, overrideOffset, isAccessible);
        }

        static void openAccess(AccessibleObject object, boolean isAccessible) {
            if (isAccessible) {
                SecurityCheck.LIMITER.preOpenAccessible(object);
            }
            openAccess0(object, isAccessible);
        }
    }

    static class Secret {
        static ModuleAccess MACCESS;
    }

    /**
     * Throw a new exception
     *
     * @since 1.2.0
     */
    @Contract(pure = false)
    public static <T> T throw0(Throwable throwable) {
        if (throwable == null) throw new NullPointerException();
        getUnsafe().throwException(throwable);
        throw new RuntimeException();
    }

    /**
     * Allocate a new object, but not initialized.
     *
     * @see Unsafe#allocateInstance(Class)
     * @since 1.2.0
     */
    @SuppressWarnings("unchecked")
    @Contract(pure = false)
    public static <T> T allocate(Class<T> klass) throws InstantiationException {
        return (T) getUnsafe().allocateInstance(klass);
    }

    /**
     * @since 1.5.0
     */
    @Contract(pure = true)
    public static ModuleAccess getModuleAccess() {
        getUnsafe();
        return Secret.MACCESS;
    }

    static class ObjectInitializer {
        static Consumer<Object> initializer;

        static Consumer<Object> initializer() {
            if (initializer != null) return initializer;
            synchronized (ObjectInitializer.class) {
                if (initializer != null) return initializer;
                initializer = UsfAccessor.allocateObjectInitializer();
            }
            return initializer;
        }
    }

    /**
     * Do nothing
     *
     * @since 1.6.0
     */
    public static void initializeObject(Object instance) {
        if (instance == null) return;
        Unsafe.getUnsafe0().ensureClassInitialized(instance.getClass());
        ObjectInitializer.initializer().accept(instance);
    }
}

## 内容2
### 文件路径：
api/src/main/java/io/github/karlatemp/unsafeaccessor/UnsafeAccess.java
### 代码内容：
package io.github.karlatemp.unsafeaccessor;

import java.lang.invoke.MethodHandles;
import java.lang.reflect.AccessibleObject;

/**
 * Direct unsafe access
 *

 * A bridge object to access unsafe.
 *

 * Unlike other methods, using this bridge will not trigger any permission checks.
 * The permission check will only happen in {@link #getInstance()}
 *
 * @since 1.4.0
 */
public final class UnsafeAccess extends ProtectedObject {
    static final UnsafeAccess INSTANCE = new UnsafeAccess();

    public static UnsafeAccess getInstance() {
        SecurityCheck.getInstance();
        return INSTANCE;
    }

    public SecurityCheck getSecuritySettings() {
        checkTrusted();
        return SecurityCheck.INSTANCE;
    }

    public Unsafe getUnsafe() {
        checkTrusted();
        return Unsafe.getUnsafe0();
    }

    /**
     * Use {@link #getTrustedIn(Class)}
     *
     * @return MethodHandles.Lookup.IMPL_LOOKUP
     */
    @Deprecated
    public MethodHandles.Lookup getTrusted() {
        checkTrusted();
        return Root.RootLookupHolder.ROOT;
    }

    public MethodHandles.Lookup getTrustedIn(Class<?> target) {
        checkTrusted();
        return Root.RootLookupHolder.trustedIn(target);
    }

    public <T extends AccessibleObject> T openAccess(T object) {
        checkTrusted();
        Root.OpenAccess.openAccess0(object, true);
        return object;
    }

    public <T extends AccessibleObject> T setAccessible(T object, boolean accessible) {
        checkTrusted();
        Root.OpenAccess.openAccess0(object, accessible);
        return object;
    }

    /**
     * @since 1.5.0
     */
    public ModuleAccess getModuleAccess() {
        checkTrusted();
        Unsafe.getUnsafe0();
        return Root.Secret.MACCESS;
    }
}

Output:
【漏洞类型】权限检查缺失
【严重性】High
【漏洞摘要】此代码在调用`UnsafeAccess.getInstance()`方法时，未进行充分的权限检查。原代码中，`SecurityCheck.getInstance()`被调用，但之后并没有对返回的对象进行进一步的验证或限制，这意味着任何调用者都可以直接访问`UnsafeAccess`的实例，进而执行任意的不安全操作，如修改私有字段、分配未初始化的对象等，这对系统的安全性构成重大威胁。
【关键代码模式】与`UnsafeAccess`实例获取相关的代码模式包括`UnsafeAccess.getInstance()`方法以及`SecurityCheck.getInstance()`方法的调用。
【修复方法说明】修复方法通过在获取`UnsafeAccess`实例时，检查`SecurityCheck`实例的访问限制器，确保在返回实例之前进行必要的权限验证。


Instruction:
作为 Java 安全专家，检测此代码中的安全漏洞：
## 内容1
### 文件路径：
services/src/main/java/org/keycloak/protocol/oidc/DefaultTokenExchangeProvider.java
### 代码内容：
package org.keycloak.protocol.oidc;

import org.jboss.logging.Logger;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.OAuth2Constants;
import org.keycloak.OAuthErrorException;
import org.keycloak.broker.provider.BrokeredIdentityContext;
import org.keycloak.broker.provider.ExchangeExternalToken;
import org.keycloak.broker.provider.ExchangeTokenToIdentityProviderToken;
import org.keycloak.broker.provider.IdentityProvider;
import org.keycloak.broker.provider.IdentityProviderFactory;
import org.keycloak.broker.provider.IdentityProviderMapper;
import org.keycloak.broker.provider.IdentityProviderMapperSyncModeDelegate;
import org.keycloak.common.ClientConnection;
import org.keycloak.common.util.Base64Url;
import org.keycloak.events.Details;
import org.keycloak.events.Errors;
import org.keycloak.events.EventBuilder;
import org.keycloak.jose.jws.JWSInput;
import org.keycloak.jose.jws.JWSInputException;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionContext;
import org.keycloak.models.FederatedIdentityModel;
import org.keycloak.models.IdentityProviderMapperModel;
import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.protocol.LoginProtocol;
import org.keycloak.protocol.LoginProtocolFactory;
import org.keycloak.protocol.oidc.endpoints.TokenEndpoint.TokenExchangeSamlProtocol;
import org.keycloak.protocol.saml.SamlClient;
import org.keycloak.protocol.saml.SamlProtocol;
import org.keycloak.protocol.saml.SamlService;
import org.keycloak.representations.AccessToken;
import org.keycloak.representations.AccessTokenResponse;
import org.keycloak.representations.JsonWebToken;
import org.keycloak.saml.common.constants.GeneralConstants;
import org.keycloak.services.CorsErrorResponseException;
import org.keycloak.services.Urls;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.AuthenticationSessionManager;
import org.keycloak.services.managers.BruteForceProtector;
import org.keycloak.services.resources.Cors;
import org.keycloak.services.resources.IdentityBrokerService;
import org.keycloak.services.resources.admin.AdminAuth;
import org.keycloak.services.resources.admin.permissions.AdminPermissions;
import org.keycloak.services.validation.Validation;
import org.keycloak.sessions.AuthenticationSessionModel;
import org.keycloak.sessions.RootAuthenticationSessionModel;
import org.keycloak.util.TokenUtil;

import static org.keycloak.authentication.authenticators.util.AuthenticatorUtils.getDisabledByBruteForceEventError;
import static org.keycloak.models.ImpersonationSessionNote.IMPERSONATOR_ID;
import static org.keycloak.models.ImpersonationSessionNote.IMPERSONATOR_USERNAME;

import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;

/**
 * Default token exchange implementation
 *
 * @author Dmitry Telegin
 */
public class DefaultTokenExchangeProvider implements TokenExchangeProvider {

    private static final Logger logger = Logger.getLogger(DefaultTokenExchangeProvider.class);

    private MultivaluedMap<String, String> formParams;
    private KeycloakSession session;
    private Cors cors;
    private RealmModel realm;
    private ClientModel client;
    private EventBuilder event;
    private ClientConnection clientConnection;
    private HttpHeaders headers;
    private TokenManager tokenManager;
    private Map<String, String> clientAuthAttributes;

    @Override
    public boolean supports(TokenExchangeContext context) {
        return true;
    }

    @Override
    public Response exchange(TokenExchangeContext context) {
        this.formParams = context.getFormParams();
        this.session = context.getSession();
        this.cors = (Cors)context.getCors();
        this.realm = context.getRealm();
        this.client = context.getClient();
        this.event = context.getEvent();
        this.clientConnection = context.getClientConnection();
        this.headers = context.getHeaders();
        this.tokenManager = (TokenManager)context.getTokenManager();
        this.clientAuthAttributes = context.getClientAuthAttributes();
        return tokenExchange();
    }

    @Override
    public void close() {
    }

    protected Response tokenExchange() {

        UserModel tokenUser = null;
        UserSessionModel tokenSession = null;
        AccessToken token = null;

        String subjectToken = formParams.getFirst(OAuth2Constants.SUBJECT_TOKEN);
        if (subjectToken != null) {
            String subjectTokenType = formParams.getFirst(OAuth2Constants.SUBJECT_TOKEN_TYPE);
            String realmIssuerUrl = Urls.realmIssuer(session.getContext().getUri().getBaseUri(), realm.getName());
            String subjectIssuer = formParams.getFirst(OAuth2Constants.SUBJECT_ISSUER);

            if (subjectIssuer == null && OAuth2Constants.JWT_TOKEN_TYPE.equals(subjectTokenType)) {
                try {
                    JWSInput jws = new JWSInput(subjectToken);
                    JsonWebToken jwt = jws.readJsonContent(JsonWebToken.class);
                    subjectIssuer = jwt.getIssuer();
                } catch (JWSInputException e) {
                    event.detail(Details.REASON, "unable to parse jwt subject_token");
                    event.error(Errors.INVALID_TOKEN);
                    throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_TOKEN, "Invalid token type, must be access token", Response.Status.BAD_REQUEST);

                }
            }

            if (subjectIssuer != null && !realmIssuerUrl.equals(subjectIssuer)) {
                event.detail(OAuth2Constants.SUBJECT_ISSUER, subjectIssuer);
                return exchangeExternalToken(subjectIssuer, subjectToken);

            }

            if (subjectTokenType != null && !subjectTokenType.equals(OAuth2Constants.ACCESS_TOKEN_TYPE)) {
                event.detail(Details.REASON, "subject_token supports access tokens only");
                event.error(Errors.INVALID_TOKEN);
                throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_TOKEN, "Invalid token type, must be access token", Response.Status.BAD_REQUEST);

            }

            AuthenticationManager.AuthResult authResult = AuthenticationManager.verifyIdentityToken(session, realm, session.getContext().getUri(), clientConnection, true, true, null, false, subjectToken, headers);
            if (authResult == null) {
                event.detail(Details.REASON, "subject_token validation failure");
                event.error(Errors.INVALID_TOKEN);
                throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_TOKEN, "Invalid token", Response.Status.BAD_REQUEST);
            }

            tokenUser = authResult.getUser();
            tokenSession = authResult.getSession();
            token = authResult.getToken();
        }

        String requestedSubject = formParams.getFirst(OAuth2Constants.REQUESTED_SUBJECT);
        if (requestedSubject != null) {
            event.detail(Details.REQUESTED_SUBJECT, requestedSubject);
            UserModel requestedUser = session.users().getUserByUsername(realm, requestedSubject);
            if (requestedUser == null) {
                requestedUser = session.users().getUserById(realm, requestedSubject);
            }

            if (requestedUser == null) {
                // We always returned access denied to avoid username fishing
                event.detail(Details.REASON, "requested_subject not found");
                event.error(Errors.NOT_ALLOWED);
                throw new CorsErrorResponseException(cors, OAuthErrorException.ACCESS_DENIED, "Client not allowed to exchange", Response.Status.FORBIDDEN);

            }

            if (token != null) {
                event.detail(Details.IMPERSONATOR, tokenUser.getUsername());
                // for this case, the user represented by the token, must have permission to impersonate.
                AdminAuth auth = new AdminAuth(realm, token, tokenUser, client);
                if (!AdminPermissions.evaluator(session, realm, auth).users().canImpersonate(requestedUser)) {
                    event.detail(Details.REASON, "subject not allowed to impersonate");
                    event.error(Errors.NOT_ALLOWED);
                    throw new CorsErrorResponseException(cors, OAuthErrorException.ACCESS_DENIED, "Client not allowed to exchange", Response.Status.FORBIDDEN);
                }

            } else {
                // no token is being exchanged, this is a direct exchange.  Client must be authenticated, not public, and must be allowed
                // to impersonate
                if (client.isPublicClient()) {
                    event.detail(Details.REASON, "public clients not allowed");
                    event.error(Errors.NOT_ALLOWED);
                    throw new CorsErrorResponseException(cors, OAuthErrorException.ACCESS_DENIED, "Client not allowed to exchange", Response.Status.FORBIDDEN);

                }
                if (!AdminPermissions.management(session, realm).users().canClientImpersonate(client, requestedUser)) {
                    event.detail(Details.REASON, "client not allowed to impersonate");
                    event.error(Errors.NOT_ALLOWED);
                    throw new CorsErrorResponseException(cors, OAuthErrorException.ACCESS_DENIED, "Client not allowed to exchange", Response.Status.FORBIDDEN);
                }
            }

            tokenSession = session.sessions().createUserSession(realm, requestedUser, requestedUser.getUsername(), clientConnection.getRemoteAddr(), "impersonate", false, null, null);
            if (tokenUser != null) {
                tokenSession.setNote(IMPERSONATOR_ID.toString(), tokenUser.getId());
                tokenSession.setNote(IMPERSONATOR_USERNAME.toString(), tokenUser.getUsername());
            }

            tokenUser = requestedUser;
        }

        String requestedIssuer = formParams.getFirst(OAuth2Constants.REQUESTED_ISSUER);
        if (requestedIssuer == null) {
            return exchangeClientToClient(tokenUser, tokenSession);
        } else {
            try {
                return exchangeToIdentityProvider(tokenUser, tokenSession, requestedIssuer);
            } finally {
                if (subjectToken == null) { // we are naked! So need to clean up user session
                    try {
                        session.sessions().removeUserSession(realm, tokenSession);
                    } catch (Exception ignore) {

                    }
                }
            }
         }
    }

    protected Response exchangeToIdentityProvider(UserModel targetUser, UserSessionModel targetUserSession, String requestedIssuer) {
        event.detail(Details.REQUESTED_ISSUER, requestedIssuer);
        IdentityProviderModel providerModel = realm.getIdentityProviderByAlias(requestedIssuer);
        if (providerModel == null) {
            event.detail(Details.REASON, "unknown requested_issuer");
            event.error(Errors.UNKNOWN_IDENTITY_PROVIDER);
            throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_REQUEST, "Invalid issuer", Response.Status.BAD_REQUEST);
        }

        IdentityProvider provider = IdentityBrokerService.getIdentityProvider(session, realm, requestedIssuer);
        if (!(provider instanceof ExchangeTokenToIdentityProviderToken)) {
            event.detail(Details.REASON, "exchange unsupported by requested_issuer");
            event.error(Errors.UNKNOWN_IDENTITY_PROVIDER);
            throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_REQUEST, "Issuer does not support token exchange", Response.Status.BAD_REQUEST);
        }
        if (!AdminPermissions.management(session, realm).idps().canExchangeTo(client, providerModel)) {
            event.detail(Details.REASON, "client not allowed to exchange for requested_issuer");
            event.error(Errors.NOT_ALLOWED);
            throw new CorsErrorResponseException(cors, OAuthErrorException.ACCESS_DENIED, "Client not allowed to exchange", Response.Status.FORBIDDEN);
        }
        Response response = ((ExchangeTokenToIdentityProviderToken)provider).exchangeFromToken(session.getContext().getUri(), event, client, targetUserSession, targetUser, formParams);
        return cors.builder(Response.fromResponse(response)).build();

    }

    protected Response exchangeClientToClient(UserModel targetUser, UserSessionModel targetUserSession) {
        String requestedTokenType = formParams.getFirst(OAuth2Constants.REQUESTED_TOKEN_TYPE);
        if (requestedTokenType == null) {
            requestedTokenType = OAuth2Constants.REFRESH_TOKEN_TYPE;
        } else if (!requestedTokenType.equals(OAuth2Constants.ACCESS_TOKEN_TYPE) &&
                !requestedTokenType.equals(OAuth2Constants.REFRESH_TOKEN_TYPE) &&
                !requestedTokenType.equals(OAuth2Constants.SAML2_TOKEN_TYPE)) {
            event.detail(Details.REASON, "requested_token_type unsupported");
            event.error(Errors.INVALID_REQUEST);
            throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_REQUEST, "requested_token_type unsupported", Response.Status.BAD_REQUEST);

        }
        ClientModel targetClient = client;
        String audience = formParams.getFirst(OAuth2Constants.AUDIENCE);
        if (audience != null) {
            targetClient = realm.getClientByClientId(audience);
            if (targetClient == null) {
                event.detail(Details.REASON, "audience not found");
                event.error(Errors.CLIENT_NOT_FOUND);
                throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_CLIENT, "Audience not found", Response.Status.BAD_REQUEST);

            }
        }

        if (targetClient.isConsentRequired()) {
            event.detail(Details.REASON, "audience requires consent");
            event.error(Errors.CONSENT_DENIED);
            throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_CLIENT, "Client requires user consent", Response.Status.BAD_REQUEST);
        }

        if (!targetClient.equals(client) && !AdminPermissions.management(session, realm).clients().canExchangeTo(client, targetClient)) {
            event.detail(Details.REASON, "client not allowed to exchange to audience");
            event.error(Errors.NOT_ALLOWED);
            throw new CorsErrorResponseException(cors, OAuthErrorException.ACCESS_DENIED, "Client not allowed to exchange", Response.Status.FORBIDDEN);
        }

        String scope = formParams.getFirst(OAuth2Constants.SCOPE);

        switch (requestedTokenType) {
            case OAuth2Constants.ACCESS_TOKEN_TYPE:
            case OAuth2Constants.REFRESH_TOKEN_TYPE:
                return exchangeClientToOIDCClient(targetUser, targetUserSession, requestedTokenType, targetClient, audience, scope);
            case OAuth2Constants.SAML2_TOKEN_TYPE:
                return exchangeClientToSAML2Client(targetUser, targetUserSession, requestedTokenType, targetClient, audience, scope);
        }

        throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_REQUEST, "requested_token_type unsupported", Response.Status.BAD_REQUEST);
    }

    protected Response exchangeClientToOIDCClient(UserModel targetUser, UserSessionModel targetUserSession, String requestedTokenType,
                                                  ClientModel targetClient, String audience, String scope) {
        RootAuthenticationSessionModel rootAuthSession = new AuthenticationSessionManager(session).createAuthenticationSession(realm, false);
        AuthenticationSessionModel authSession = rootAuthSession.createAuthenticationSession(targetClient);

        authSession.setAuthenticatedUser(targetUser);
        authSession.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
        authSession.setClientNote(OIDCLoginProtocol.ISSUER, Urls.realmIssuer(session.getContext().getUri().getBaseUri(), realm.getName()));
        authSession.setClientNote(OIDCLoginProtocol.SCOPE_PARAM, scope);

        event.session(targetUserSession);

        AuthenticationManager.setClientScopesInSession(authSession);
        ClientSessionContext clientSessionCtx = TokenManager.attachAuthenticationSession(this.session, targetUserSession, authSession);

        updateUserSessionFromClientAuth(targetUserSession);

        TokenManager.AccessTokenResponseBuilder responseBuilder = tokenManager.responseBuilder(realm, targetClient, event, this.session, targetUserSession, clientSessionCtx)
                .generateAccessToken();
        responseBuilder.getAccessToken().issuedFor(client.getClientId());

        if (audience != null) {
            responseBuilder.getAccessToken().addAudience(audience);
        }

        if (requestedTokenType.equals(OAuth2Constants.REFRESH_TOKEN_TYPE)
            && OIDCAdvancedConfigWrapper.fromClientModel(client).isUseRefreshToken()) {
            responseBuilder.generateRefreshToken();
            responseBuilder.getRefreshToken().issuedFor(client.getClientId());
        }

        String scopeParam = clientSessionCtx.getClientSession().getNote(OAuth2Constants.SCOPE);
        if (TokenUtil.isOIDCRequest(scopeParam)) {
            responseBuilder.generateIDToken().generateAccessTokenHash();
        }

        AccessTokenResponse res = responseBuilder.build();
        event.detail(Details.AUDIENCE, targetClient.getClientId());

        event.success();

        return cors.builder(Response.ok(res, MediaType.APPLICATION_JSON_TYPE)).build();
    }

    protected Response exchangeClientToSAML2Client(UserModel targetUser, UserSessionModel targetUserSession, String requestedTokenType,
                                                  ClientModel targetClient, String audience, String scope) {
        // Create authSession with target SAML 2.0 client and authenticated user
        LoginProtocolFactory factory = (LoginProtocolFactory) session.getKeycloakSessionFactory()
                .getProviderFactory(LoginProtocol.class, SamlProtocol.LOGIN_PROTOCOL);
        SamlService samlService = (SamlService) factory.createProtocolEndpoint(realm, event);
        ResteasyProviderFactory.getInstance().injectProperties(samlService);
        AuthenticationSessionModel authSession = samlService.getOrCreateLoginSessionForIdpInitiatedSso(session, realm,
                targetClient, null);
        if (authSession == null) {
            logger.error("SAML assertion consumer url not set up");
            throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_CLIENT, "Client requires assertion consumer url set up", Response.Status.BAD_REQUEST);
        }

        authSession.setAuthenticatedUser(targetUser);

        event.session(targetUserSession);

        AuthenticationManager.setClientScopesInSession(authSession);
        ClientSessionContext clientSessionCtx = TokenManager.attachAuthenticationSession(this.session, targetUserSession,
                authSession);

        updateUserSessionFromClientAuth(targetUserSession);

        // Create SAML 2.0 Assertion Response
        SamlClient samlClient = new SamlClient(targetClient);
        SamlProtocol samlProtocol = new TokenExchangeSamlProtocol(samlClient).setEventBuilder(event).setHttpHeaders(headers).setRealm(realm)
                .setSession(session).setUriInfo(session.getContext().getUri());

        Response samlAssertion = samlProtocol.authenticated(authSession, targetUserSession, clientSessionCtx);
        if (samlAssertion.getStatus() != 200) {
            throw new CorsErrorResponseException(cors, OAuthErrorException.INVALID_REQUEST, "Can not get SAML 2.0 token", Response.Status.BAD_REQUEST);
        }
        String xmlString = (String) samlAssertion.getEntity();
        String encodedXML = Base64Url.encode(xmlString.getBytes(GeneralConstants.SAML_CHARSET));

        int assertionLifespan = samlClient.getAssertionLifespan();

        AccessTokenResponse res = new AccessTokenResponse();
        res.setToken(encodedXML);
        res.setTokenType("Bearer");
        res.setExpiresIn(assertionLifespan <= 0 ? realm.getAccessCodeLifespan() : assertionLifespan);
        res.setOtherClaims(OAuth2Constants.ISSUED_TOKEN_TYPE, requestedTokenType);

        event.detail(Details.AUDIENCE, targetClient.getClientId());
        event.success();

        return cors.builder(Response.ok(res, MediaType.APPLICATION_JSON_TYPE)).build();
    }

    protected Response exchangeExternalToken(String issuer, String subjectToken) {
        AtomicReference<ExchangeExternalToken> externalIdp = new AtomicReference<>(null);
        AtomicReference<IdentityProviderModel> externalIdpModel = new AtomicReference<>(null);

        realm.getIdentityProvidersStream().filter(idpModel -> {
            IdentityProviderFactory factory = IdentityBrokerService.getIdentityProviderFactory(session, idpModel);
            IdentityProvider idp = factory.create(session, idpModel);
            if (idp instanceof ExchangeExternalToken) {
                ExchangeExternalToken external = (ExchangeExternalToken) idp;
                if (idpModel.getAlias().equals(issuer) || external.isIssuer(issuer, formParams)) {
                    externalIdp.set(external);
                    externalIdpModel.set(idpModel);
                    return true;
                }
            }
            return false;
        }).findFirst();

        if (externalIdp.get() == null) {
            event.error(Errors.INVALID_ISSUER);
            throw new CorsErrorResponseException(cors, Errors.INVALID_ISSUER, "Invalid " + OAuth2Constants.SUBJECT_ISSUER + " parameter", Response.Status.BAD_REQUEST);
        }
        if (!AdminPermissions.management(session, realm).idps().canExchangeTo(client, externalIdpModel.get())) {
            event.detail(Details.REASON, "client not allowed to exchange subject_issuer");
            event.error(Errors.NOT_ALLOWED);
            throw new CorsErrorResponseException(cors, OAuthErrorException.ACCESS_DENIED, "Client not allowed to exchange", Response.Status.FORBIDDEN);
        }
        BrokeredIdentityContext context = externalIdp.get().exchangeExternal(event, formParams);
        if (context == null) {
            event.error(Errors.INVALID_ISSUER);
            throw new CorsErrorResponseException(cors, Errors.INVALID_ISSUER, "Invalid " + OAuth2Constants.SUBJECT_ISSUER + " parameter", Response.Status.BAD_REQUEST);
        }

        UserModel user = importUserFromExternalIdentity(context);

        UserSessionModel userSession = session.sessions().createUserSession(realm, user, user.getUsername(), clientConnection.getRemoteAddr(), "external-exchange", false, null, null);
        externalIdp.get().exchangeExternalComplete(userSession, context, formParams);

        // this must exist so that we can obtain access token from user session if idp's store tokens is off
        userSession.setNote(IdentityProvider.EXTERNAL_IDENTITY_PROVIDER, externalIdpModel.get().getAlias());
        userSession.setNote(IdentityProvider.FEDERATED_ACCESS_TOKEN, subjectToken);

        return exchangeClientToClient(user, userSession);
    }

    protected UserModel importUserFromExternalIdentity(BrokeredIdentityContext context) {
        IdentityProviderModel identityProviderConfig = context.getIdpConfig();

        String providerId = identityProviderConfig.getAlias();

        // do we need this?
        //AuthenticationSessionModel authenticationSession = clientCode.getClientSession();
        //context.setAuthenticationSession(authenticationSession);
        //session.getContext().setClient(authenticationSession.getClient());

        context.getIdp().preprocessFederatedIdentity(session, realm, context);
        Set<IdentityProviderMapperModel> mappers = realm.getIdentityProviderMappersByAliasStream(context.getIdpConfig().getAlias())
                .collect(Collectors.toSet());
        KeycloakSessionFactory sessionFactory = session.getKeycloakSessionFactory();
        for (IdentityProviderMapperModel mapper : mappers) {
            IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
            target.preprocessFederatedIdentity(session, realm, mapper, context);
        }

        FederatedIdentityModel federatedIdentityModel = new FederatedIdentityModel(providerId, context.getId(),
                context.getUsername(), context.getToken());

        UserModel user = this.session.users().getUserByFederatedIdentity(realm, federatedIdentityModel);

        if (user == null) {

            logger.debugf("Federated user not found for provider '%s' and broker username '%s'.", providerId, context.getUsername());

            String username = context.getModelUsername();
            if (username == null) {
                if (this.realm.isRegistrationEmailAsUsername() && !Validation.isBlank(context.getEmail())) {
                    username = context.getEmail();
                } else if (context.getUsername() == null) {
                    username = context.getIdpConfig().getAlias() + "." + context.getId();
                } else {
                    username = context.getUsername();
                }
            }
            username = username.trim();
            context.setModelUsername(username);
            if (context.getEmail() != null && !realm.isDuplicateEmailsAllowed()) {
                UserModel existingUser = session.users().getUserByEmail(realm, context.getEmail());
                if (existingUser != null) {
                    event.error(Errors.FEDERATED_IDENTITY_EXISTS);
                    throw new CorsErrorResponseException(cors, Errors.INVALID_TOKEN, "User already exists", Response.Status.BAD_REQUEST);
                }
            }

            UserModel existingUser = session.users().getUserByUsername(realm, username);
            if (existingUser != null) {
                event.error(Errors.FEDERATED_IDENTITY_EXISTS);
                throw new CorsErrorResponseException(cors, Errors.INVALID_TOKEN, "User already exists", Response.Status.BAD_REQUEST);
            }

            user = session.users().addUser(realm, username);
            user.setEnabled(true);
            user.setEmail(context.getEmail());
            user.setFirstName(context.getFirstName());
            user.setLastName(context.getLastName());

            federatedIdentityModel = new FederatedIdentityModel(context.getIdpConfig().getAlias(), context.getId(),
                    context.getUsername(), context.getToken());
            session.users().addFederatedIdentity(realm, user, federatedIdentityModel);

            context.getIdp().importNewUser(session, realm, user, context);

            for (IdentityProviderMapperModel mapper : mappers) {
                IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
                target.importNewUser(session, realm, user, mapper, context);
            }

            if (context.getIdpConfig().isTrustEmail() && !Validation.isBlank(user.getEmail())) {
                logger.debugf("Email verified automatically after registration of user '%s' through Identity provider '%s' ", user.getUsername(), context.getIdpConfig().getAlias());
                user.setEmailVerified(true);
            }
        } else {
            if (!user.isEnabled()) {
                event.error(Errors.USER_DISABLED);
                throw new CorsErrorResponseException(cors, Errors.INVALID_TOKEN, "Invalid Token", Response.Status.BAD_REQUEST);
            }

            String bruteForceError = getDisabledByBruteForceEventError(session.getProvider(BruteForceProtector.class), session, realm, user);
            if (bruteForceError != null) {
                event.error(bruteForceError);
                throw new CorsErrorResponseException(cors, Errors.INVALID_TOKEN, "Invalid Token", Response.Status.BAD_REQUEST);
            }

            context.getIdp().updateBrokeredUser(session, realm, user, context);

            for (IdentityProviderMapperModel mapper : mappers) {
                IdentityProviderMapper target = (IdentityProviderMapper)sessionFactory.getProviderFactory(IdentityProviderMapper.class, mapper.getIdentityProviderMapper());
                IdentityProviderMapperSyncModeDelegate.delegateUpdateBrokeredUser(session, realm, user, mapper, context, target);
            }
        }
        return user;
    }

    // TODO: move to utility class
    private void updateUserSessionFromClientAuth(UserSessionModel userSession) {
        for (Map.Entry<String, String> attr : clientAuthAttributes.entrySet()) {
            userSession.setNote(attr.getKey(), attr.getValue());
        }
    }

}

## 内容2
### 文件路径：
services/src/main/java/org/keycloak/services/resources/admin/permissions/ClientPermissions.java
### 代码内容：
package org.keycloak.services.resources.admin.permissions;

import org.jboss.logging.Logger;
import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.common.ClientModelIdentity;
import org.keycloak.authorization.common.DefaultEvaluationContext;
import org.keycloak.authorization.model.Policy;
import org.keycloak.authorization.model.Resource;
import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.authorization.model.Scope;
import org.keycloak.authorization.policy.evaluation.EvaluationContext;
import org.keycloak.models.AdminRoles;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientScopeModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.services.ForbiddenException;
import org.keycloak.storage.StorageId;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

import static org.keycloak.services.resources.admin.permissions.AdminPermissionManagement.TOKEN_EXCHANGE;

/**
 * Manages default policies for all users.
 *
 *
 * @author Bill Burke
 * @version $Revision: 1 $
 */
class ClientPermissions implements ClientPermissionEvaluator,  ClientPermissionManagement {
    private static final Logger logger = Logger.getLogger(ClientPermissions.class);
    protected final KeycloakSession session;
    protected final RealmModel realm;
    protected final AuthorizationProvider authz;
    protected final MgmtPermissions root;

    public ClientPermissions(KeycloakSession session, RealmModel realm, AuthorizationProvider authz, MgmtPermissions root) {
        this.session = session;
        this.realm = realm;
        this.authz = authz;
        this.root = root;
    }

    private String getResourceName(ClientModel client) {
        return "client.resource." + client.getId();
    }

    private String getManagePermissionName(ClientModel client) {
        return "manage.permission.client." + client.getId();
    }
    private String getConfigurePermissionName(ClientModel client) {
        return "configure.permission.client." + client.getId();
    }
    private String getViewPermissionName(ClientModel client) {
        return "view.permission.client." + client.getId();
    }
    private String getMapRolesPermissionName(ClientModel client) {
        return MAP_ROLES_SCOPE + ".permission.client." + client.getId();
    }
    private String getMapRolesClientScopePermissionName(ClientModel client) {
        return MAP_ROLES_CLIENT_SCOPE + ".permission.client." + client.getId();
    }
    private String getMapRolesCompositePermissionName(ClientModel client) {
        return MAP_ROLES_COMPOSITE_SCOPE + ".permission.client." + client.getId();
    }

    private String getExchangeToPermissionName(ClientModel client) {
        return TOKEN_EXCHANGE + ".permission.client." + client.getId();
    }

     private void initialize(ClientModel client) {
        ResourceServer server = root.findOrCreateResourceServer(client);
        Scope manageScope = manageScope(server);
        if (manageScope == null) {
            manageScope = authz.getStoreFactory().getScopeStore().create(server, AdminPermissionManagement.MANAGE_SCOPE);
        }
        Scope viewScope = viewScope(server);
        if (viewScope == null) {
            viewScope = authz.getStoreFactory().getScopeStore().create(server, AdminPermissionManagement.VIEW_SCOPE);
        }
        Scope mapRoleScope = mapRolesScope(server);
        if (mapRoleScope == null) {
            mapRoleScope = authz.getStoreFactory().getScopeStore().create(server, MAP_ROLES_SCOPE);
        }
        Scope mapRoleClientScope = root.initializeScope(MAP_ROLES_CLIENT_SCOPE, server);
        Scope mapRoleCompositeScope = root.initializeScope(MAP_ROLES_COMPOSITE_SCOPE, server);
        Scope configureScope = root.initializeScope(CONFIGURE_SCOPE, server);
        Scope exchangeToScope = root.initializeScope(TOKEN_EXCHANGE, server);

        String resourceName = getResourceName(client);
        Resource resource = authz.getStoreFactory().getResourceStore().findByName(server, resourceName);
        if (resource == null) {
            resource = authz.getStoreFactory().getResourceStore().create(server, resourceName, server.getClientId());
            resource.setType("Client");
            Set<Scope> scopeset = new HashSet<>();
            scopeset.add(configureScope);
            scopeset.add(manageScope);
            scopeset.add(viewScope);
            scopeset.add(mapRoleScope);
            scopeset.add(mapRoleClientScope);
            scopeset.add(mapRoleCompositeScope);
            scopeset.add(exchangeToScope);
            resource.updateScopes(scopeset);
        }
        String managePermissionName = getManagePermissionName(client);
        Policy managePermission = authz.getStoreFactory().getPolicyStore().findByName(server, managePermissionName);
        if (managePermission == null) {
            Helper.addEmptyScopePermission(authz, server, managePermissionName, resource, manageScope);
        }
        String configurePermissionName = getConfigurePermissionName(client);
        Policy configurePermission = authz.getStoreFactory().getPolicyStore().findByName(server, configurePermissionName);
        if (configurePermission == null) {
            Helper.addEmptyScopePermission(authz, server, configurePermissionName, resource, configureScope);
        }
        String viewPermissionName = getViewPermissionName(client);
        Policy viewPermission = authz.getStoreFactory().getPolicyStore().findByName(server, viewPermissionName);
        if (viewPermission == null) {
            Helper.addEmptyScopePermission(authz, server, viewPermissionName, resource, viewScope);
        }
        String mapRolePermissionName = getMapRolesPermissionName(client);
        Policy mapRolePermission = authz.getStoreFactory().getPolicyStore().findByName(server, mapRolePermissionName);
        if (mapRolePermission == null) {
            Helper.addEmptyScopePermission(authz, server, mapRolePermissionName, resource, mapRoleScope);
        }
        String mapRoleClientScopePermissionName = getMapRolesClientScopePermissionName(client);
        Policy mapRoleClientScopePermission = authz.getStoreFactory().getPolicyStore().findByName(server, mapRoleClientScopePermissionName);
        if (mapRoleClientScopePermission == null) {
            Helper.addEmptyScopePermission(authz, server, mapRoleClientScopePermissionName, resource, mapRoleClientScope);
        }
        String mapRoleCompositePermissionName = getMapRolesCompositePermissionName(client);
        Policy mapRoleCompositePermission = authz.getStoreFactory().getPolicyStore().findByName(server, mapRoleCompositePermissionName);
        if (mapRoleCompositePermission == null) {
            Helper.addEmptyScopePermission(authz, server, mapRoleCompositePermissionName, resource, mapRoleCompositeScope);
        }
        String exchangeToPermissionName = getExchangeToPermissionName(client);
        Policy exchangeToPermission = authz.getStoreFactory().getPolicyStore().findByName(server, exchangeToPermissionName);
        if (exchangeToPermission == null) {
            Helper.addEmptyScopePermission(authz, server, exchangeToPermissionName, resource, exchangeToScope);
        }
    }

    private void deletePolicy(String name, ResourceServer server) {
        Policy policy = authz.getStoreFactory().getPolicyStore().findByName(server, name);
        if (policy != null) {
            authz.getStoreFactory().getPolicyStore().delete(policy.getId());
        }

    }

    private void deletePermissions(ClientModel client) {
        ResourceServer server = resourceServer(client);
        if (server == null) return;
        deletePolicy(getManagePermissionName(client), server);
        deletePolicy(getViewPermissionName(client), server);
        deletePolicy(getMapRolesPermissionName(client), server);
        deletePolicy(getMapRolesClientScopePermissionName(client), server);
        deletePolicy(getMapRolesCompositePermissionName(client), server);
        deletePolicy(getConfigurePermissionName(client), server);
        deletePolicy(getExchangeToPermissionName(client), server);
        Resource resource = authz.getStoreFactory().getResourceStore().findByName(server, getResourceName(client));;
        if (resource != null) authz.getStoreFactory().getResourceStore().delete(resource.getId());
    }

    @Override
    public boolean isPermissionsEnabled(ClientModel client) {
        ResourceServer server = resourceServer(client);
        if (server == null) return false;

        return authz.getStoreFactory().getResourceStore().findByName(server, getResourceName(client)) != null;
    }

    @Override
    public void setPermissionsEnabled(ClientModel client, boolean enable) {
        if (enable) {
            initialize(client);
        } else {
            deletePermissions(client);
        }
    }

    private Scope manageScope(ResourceServer server) {
        return authz.getStoreFactory().getScopeStore().findByName(server, AdminPermissionManagement.MANAGE_SCOPE);
    }

    private Scope exchangeToScope(ResourceServer server) {
        return authz.getStoreFactory().getScopeStore().findByName(server, TOKEN_EXCHANGE);
    }

    private Scope configureScope(ResourceServer server) {
        return authz.getStoreFactory().getScopeStore().findByName(server, CONFIGURE_SCOPE);
    }

    private Scope viewScope(ResourceServer server) {
        return authz.getStoreFactory().getScopeStore().findByName(server, AdminPermissionManagement.VIEW_SCOPE);
    }
    private Scope mapRolesScope(ResourceServer server) {
        return authz.getStoreFactory().getScopeStore().findByName(server, MAP_ROLES_SCOPE);
    }

    @Override
    public boolean canList() {
        // when the user is assigned with query-users role, administrators can restrict which clients the user can see when using fine-grained admin permissions
        return canView() || root.hasOneAdminRole(AdminRoles.QUERY_CLIENTS, AdminRoles.QUERY_USERS);
    }

    public boolean canList(ClientModel clientModel) {
        return canView(clientModel) || root.hasOneAdminRole(AdminRoles.QUERY_CLIENTS);
    }

    @Override
    public void requireList() {
        if (!canList()) {
            throw new ForbiddenException();
        }
    }

    @Override
    public boolean canListClientScopes() {
        return canView() || root.hasOneAdminRole(AdminRoles.QUERY_CLIENTS);
    }

    @Override
    public void requireListClientScopes() {
        if (!canListClientScopes()) {
            throw new ForbiddenException();
        }
    }
    public boolean canManageClientsDefault() {
        return root.hasOneAdminRole(AdminRoles.MANAGE_CLIENTS);
    }
    public boolean canViewClientDefault() {
        return root.hasOneAdminRole(AdminRoles.MANAGE_CLIENTS, AdminRoles.VIEW_CLIENTS);
    }

    @Override
    public boolean canManage() {
        return canManageClientsDefault();
    }

    @Override
    public void requireManage() {
        if (!canManage()) {
            throw new ForbiddenException();
        }
    }
    @Override
    public boolean canView() {
        return canManageClientsDefault() || canViewClientDefault();
    }

    @Override
    public void requireView() {
        if (!canView()) {
            throw new ForbiddenException();
        }
    }

    @Override
    public Resource resource(ClientModel client) {
        ResourceServer server = resourceServer(client);
        if (server == null) return null;
        Resource resource =  authz.getStoreFactory().getResourceStore().findByName(server, getResourceName(client));
        if (resource == null) return null;
        return resource;
    }

    @Override
    public Map<String, String> getPermissions(ClientModel client) {
        initialize(client);
        Map<String, String> scopes = new LinkedHashMap<>();
        scopes.put(AdminPermissionManagement.VIEW_SCOPE, viewPermission(client).getId());
        scopes.put(AdminPermissionManagement.MANAGE_SCOPE, managePermission(client).getId());
        scopes.put(CONFIGURE_SCOPE, configurePermission(client).getId());
        scopes.put(MAP_ROLES_SCOPE,  mapRolesPermission(client).getId());
        scopes.put(MAP_ROLES_CLIENT_SCOPE, mapRolesClientScopePermission(client).getId());
        scopes.put(MAP_ROLES_COMPOSITE_SCOPE, mapRolesCompositePermission(client).getId());
        scopes.put(TOKEN_EXCHANGE, exchangeToPermission(client).getId());
        return scopes;
    }

    @Override
    public boolean canExchangeTo(ClientModel authorizedClient, ClientModel to) {

        if (!authorizedClient.equals(to)) {
            ResourceServer server = resourceServer(to);
            if (server == null) {
                logger.debug("No resource server set up for target client");
                return false;
            }

            Resource resource =  authz.getStoreFactory().getResourceStore().findByName(server, getResourceName(to));
            if (resource == null) {
                logger.debug("No resource object set up for target client");
                return false;
            }

            Policy policy = authz.getStoreFactory().getPolicyStore().findByName(server, getExchangeToPermissionName(to));
            if (policy == null) {
                logger.debug("No permission object set up for target client");
                return false;
            }

            Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
            // if no policies attached to permission then just do default behavior
            if (associatedPolicies == null || associatedPolicies.isEmpty()) {
                logger.debug("No policies set up for permission on target client");
                return false;
            }

            Scope scope = exchangeToScope(server);
            if (scope == null) {
                logger.debug(TOKEN_EXCHANGE + " not initialized");
                return false;
            }
            ClientModelIdentity identity = new ClientModelIdentity(session, authorizedClient);
            EvaluationContext context = new DefaultEvaluationContext(identity, session) {
                @Override
                public Map<String, Collection<String>> getBaseAttributes() {
                    Map<String, Collection<String>> attributes = super.getBaseAttributes();
                    attributes.put("kc.client.id", Arrays.asList(authorizedClient.getClientId()));
                    return attributes;
                }

            };
            return root.evaluatePermission(resource, server, context, scope);
        }
        return true;
    }

    @Override
    public boolean canManage(ClientModel client) {
        if (canManageClientsDefault()) return true;
        if (!root.isAdminSameRealm()) {
            return false;
        }

        ResourceServer server = resourceServer(client);
        if (server == null) return false;

        Resource resource =  authz.getStoreFactory().getResourceStore().findByName(server, getResourceName(client));
        if (resource == null) return false;

        Policy policy = authz.getStoreFactory().getPolicyStore().findByName(server, getManagePermissionName(client));
        if (policy == null) {
            return false;
        }

        Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
        // if no policies attached to permission then just do default behavior
        if (associatedPolicies == null || associatedPolicies.isEmpty()) {
            return false;
        }

        Scope scope = manageScope(server);
        return root.evaluatePermission(resource, server, scope);
    }

    @Override
    public boolean canConfigure(ClientModel client) {
        if (canManage(client)) return true;
        if (!root.isAdminSameRealm()) {
            return false;
        }

        ResourceServer server = resourceServer(client);
        if (server == null) return false;

        Resource resource =  authz.getStoreFactory().getResourceStore().findByName(server, getResourceName(client));
        if (resource == null) return false;

        Policy policy = authz.getStoreFactory().getPolicyStore().findByName(server, getConfigurePermissionName(client));
        if (policy == null) {
            return false;
        }

        Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
        // if no policies attached to permission then just do default behavior
        if (associatedPolicies == null || associatedPolicies.isEmpty()) {
            return false;
        }

        Scope scope = configureScope(server);
        return root.evaluatePermission(resource, server, scope);
    }
    @Override
    public void requireConfigure(ClientModel client) {
        if (!canConfigure(client)) {
            throw new ForbiddenException();
        }
    }

    @Override
    public void requireManage(ClientModel client) {
        if (!canManage(client)) {
            throw new ForbiddenException();
        }
    }

    @Override
    public boolean canView(ClientModel client) {
        return hasView(client) || canConfigure(client);
    }

    private boolean hasView(ClientModel client) {
        if (canView()) return true;
        if (!root.isAdminSameRealm()) {
            return false;
        }

        ResourceServer server = resourceServer(client);
        if (server == null) return false;

        Resource resource =  authz.getStoreFactory().getResourceStore().findByName(server, getResourceName(client));
        if (resource == null) return false;

        Policy policy = authz.getStoreFactory().getPolicyStore().findByName(server, getViewPermissionName(client));
        if (policy == null) {
            return false;
        }

        Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
        // if no policies attached to permission then just do default behavior
        if (associatedPolicies == null || associatedPolicies.isEmpty()) {
            return false;
        }

        Scope scope = viewScope(server);
        return root.evaluatePermission(resource, server, scope);
    }

    @Override
    public void requireView(ClientModel client) {
        if (!canView(client)) {
            throw new ForbiddenException();
        }
    }

    // client scopes

    @Override
    public boolean canViewClientScopes() {
        return canView();
    }

    @Override
    public boolean canManageClientScopes() {
        return canManageClientsDefault();
    }

    @Override
    public void requireManageClientScopes() {
        if (!canManageClientScopes()) {
            throw new ForbiddenException();
        }
    }
    @Override
    public void requireViewClientScopes() {
        if (!canViewClientScopes()) {
            throw new ForbiddenException();
        }
    }

    @Override
    public boolean canManage(ClientScopeModel clientScope) {
        return canManageClientsDefault();
    }

    @Override
    public void requireManage(ClientScopeModel clientScope) {
        if (!canManage(clientScope)) {
            throw new ForbiddenException();
        }
    }

    @Override
    public boolean canView(ClientScopeModel clientScope) {
        return canViewClientDefault();
    }

    @Override
    public void requireView(ClientScopeModel clientScope) {
        if (!canView(clientScope)) {
            throw new ForbiddenException();
        }
    }

    @Override
    public boolean canMapRoles(ClientModel client) {
        ResourceServer server = resourceServer(client);
        if (server == null) return false;

        Resource resource =  authz.getStoreFactory().getResourceStore().findByName(server, getResourceName(client));
        if (resource == null) return false;

        Policy policy = authz.getStoreFactory().getPolicyStore().findByName(server, getMapRolesPermissionName(client));
        if (policy == null) {
            return false;
        }

        Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
        // if no policies attached to permission then just do default behavior
        if (associatedPolicies == null || associatedPolicies.isEmpty()) {
            return false;
        }

        Scope scope = mapRolesScope(server);
        return root.evaluatePermission(resource, server, scope);
    }

    @Override
    public Policy exchangeToPermission(ClientModel client) {
        ResourceServer server = resourceServer(client);
        if (server == null) return null;
        return authz.getStoreFactory().getPolicyStore().findByName(server, getExchangeToPermissionName(client));
    }

    @Override
    public Policy mapRolesPermission(ClientModel client) {
        ResourceServer server = resourceServer(client);
        if (server == null) return null;
        return authz.getStoreFactory().getPolicyStore().findByName(server, getMapRolesPermissionName(client));
    }

    @Override
    public Policy mapRolesClientScopePermission(ClientModel client) {
        ResourceServer server = resourceServer(client);
        if (server == null) return null;
        return authz.getStoreFactory().getPolicyStore().findByName(server, getMapRolesClientScopePermissionName(client));
    }

    @Override
    public Policy mapRolesCompositePermission(ClientModel client) {
        ResourceServer server = resourceServer(client);
        if (server == null) return null;
        return authz.getStoreFactory().getPolicyStore().findByName(server, getMapRolesCompositePermissionName(client));
    }

    @Override
    public Policy managePermission(ClientModel client) {
        ResourceServer server = resourceServer(client);
        if (server == null) return null;
        return authz.getStoreFactory().getPolicyStore().findByName(server, getManagePermissionName(client));
    }

    @Override
    public Policy configurePermission(ClientModel client) {
        ResourceServer server = resourceServer(client);
        if (server == null) return null;
        return authz.getStoreFactory().getPolicyStore().findByName(server, getConfigurePermissionName(client));
    }

    @Override
    public Policy viewPermission(ClientModel client) {
        ResourceServer server = resourceServer(client);
        if (server == null) return null;
        return authz.getStoreFactory().getPolicyStore().findByName(server, getViewPermissionName(client));
    }

    @Override
    public ResourceServer resourceServer(ClientModel client) {
        return root.resourceServer(client);
    }

    @Override
    public boolean canMapCompositeRoles(ClientModel client) {
        ResourceServer server = resourceServer(client);
        if (server == null) return false;

        Resource resource =  authz.getStoreFactory().getResourceStore().findByName(server, getResourceName(client));
        if (resource == null) return false;

        Policy policy = authz.getStoreFactory().getPolicyStore().findByName(server, getMapRolesCompositePermissionName(client));
        if (policy == null) {
            return false;
        }

        Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
        // if no policies attached to permission then just do default behavior
        if (associatedPolicies == null || associatedPolicies.isEmpty()) {
            return false;
        }

        Scope scope = authz.getStoreFactory().getScopeStore().findByName(server, MAP_ROLES_COMPOSITE_SCOPE);
        return root.evaluatePermission(resource, server, scope);
    }
    @Override
    public boolean canMapClientScopeRoles(ClientModel client) {
        ResourceServer server = resourceServer(client);
        if (server == null) return false;

        Resource resource =  authz.getStoreFactory().getResourceStore().findByName(server, getResourceName(client));
        if (resource == null) return false;

        Policy policy = authz.getStoreFactory().getPolicyStore().findByName(server, getMapRolesClientScopePermissionName(client));
        if (policy == null) {
            return false;
        }

        Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
        // if no policies attached to permission then just do default behavior
        if (associatedPolicies == null || associatedPolicies.isEmpty()) {
            return false;
        }

        Scope scope = authz.getStoreFactory().getScopeStore().findByName(server, MAP_ROLES_CLIENT_SCOPE);
        return root.evaluatePermission(resource, server, scope);
    }

    @Override
    public Map<String, Boolean> getAccess(ClientModel client) {
        Map<String, Boolean> map = new HashMap<>();
        map.put("view", canView(client));
        map.put("manage", StorageId.isLocalStorage(client) && canManage(client));
        map.put("configure", StorageId.isLocalStorage(client) && canConfigure(client));
        return map;
    }

}

## 内容3
### 文件路径：
services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissionEvaluator.java
### 代码内容：
package org.keycloak.services.resources.admin.permissions;

import org.keycloak.models.UserModel;

import java.util.Map;

/**
 * @author Bill Burke
 * @version $Revision: 1 $
 */
public interface UserPermissionEvaluator {
    void requireManage();
    void requireManage(UserModel user);
    boolean canManage();
    boolean canManage(UserModel user);

    void requireQuery();
    boolean canQuery();

    void requireView();
    void requireView(UserModel user);
    boolean canView();
    boolean canView(UserModel user);

    void requireImpersonate(UserModel user);
    boolean canImpersonate();
    boolean canImpersonate(UserModel user);
    boolean isImpersonatable(UserModel user);

    Map<String, Boolean> getAccess(UserModel user);

    void requireMapRoles(UserModel user);
    boolean canMapRoles(UserModel user);

    void requireManageGroupMembership(UserModel user);
    boolean canManageGroupMembership(UserModel user);
    void grantIfNoPermission(boolean grantIfNoPermission);
}

## 内容4
### 文件路径：
services/src/main/java/org/keycloak/services/resources/admin/permissions/UserPermissions.java
### 代码内容：
package org.keycloak.services.resources.admin.permissions;

import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.common.ClientModelIdentity;
import org.keycloak.authorization.common.DefaultEvaluationContext;
import org.keycloak.authorization.common.UserModelIdentity;
import org.keycloak.authorization.identity.Identity;
import org.keycloak.authorization.model.Policy;
import org.keycloak.authorization.model.Resource;
import org.keycloak.authorization.model.ResourceServer;
import org.keycloak.authorization.model.Scope;
import org.keycloak.authorization.permission.ResourcePermission;
import org.keycloak.authorization.policy.evaluation.EvaluationContext;
import org.keycloak.authorization.store.PolicyStore;
import org.keycloak.authorization.store.ResourceStore;
import org.keycloak.common.Profile;
import org.keycloak.models.AdminRoles;
import org.keycloak.models.ClientModel;
import org.keycloak.models.GroupModel;
import org.keycloak.models.ImpersonationConstants;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.UserModel;
import org.keycloak.representations.idm.authorization.Permission;
import org.keycloak.services.ForbiddenException;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;

/**
 * Manages default policies for all users.
 *
 *
 * @author Bill Burke
 * @version $Revision: 1 $
 */
class UserPermissions implements UserPermissionEvaluator, UserPermissionManagement {

    private static final String MAP_ROLES_SCOPE="map-roles";
    private static final String IMPERSONATE_SCOPE="impersonate";
    private static final String USER_IMPERSONATED_SCOPE="user-impersonated";
    private static final String MANAGE_GROUP_MEMBERSHIP_SCOPE="manage-group-membership";
    private static final String MAP_ROLES_PERMISSION_USERS = "map-roles.permission.users";
    private static final String ADMIN_IMPERSONATING_PERMISSION = "admin-impersonating.permission.users";
    private static final String USER_IMPERSONATED_PERMISSION = "user-impersonated.permission.users";
    private static final String MANAGE_GROUP_MEMBERSHIP_PERMISSION_USERS = "manage-group-membership.permission.users";
    private static final String MANAGE_PERMISSION_USERS = "manage.permission.users";
    private static final String VIEW_PERMISSION_USERS = "view.permission.users";
    private static final String USERS_RESOURCE = "Users";

    private final KeycloakSession session;
    private final AuthorizationProvider authz;
    private final MgmtPermissions root;
    private final PolicyStore policyStore;
    private final ResourceStore resourceStore;
    private boolean grantIfNoPermission = false;

    UserPermissions(KeycloakSession session, AuthorizationProvider authz, MgmtPermissions root) {
        this.session = session;
        this.authz = authz;
        this.root = root;
        if (Profile.isFeatureEnabled(Profile.Feature.AUTHORIZATION)) {
            policyStore = authz.getStoreFactory().getPolicyStore();
            resourceStore = authz.getStoreFactory().getResourceStore();
        } else {
            policyStore = null;
            resourceStore = null;
        }
    }

    private void initialize() {
        root.initializeRealmResourceServer();
        root.initializeRealmDefaultScopes();
        ResourceServer server = root.realmResourceServer();
        Scope manageScope = root.realmManageScope();
        Scope viewScope = root.realmViewScope();
        Scope mapRolesScope = root.initializeRealmScope(MAP_ROLES_SCOPE);
        Scope impersonateScope = root.initializeRealmScope(IMPERSONATE_SCOPE);
        Scope userImpersonatedScope = root.initializeRealmScope(USER_IMPERSONATED_SCOPE);
        Scope manageGroupMembershipScope = root.initializeRealmScope(MANAGE_GROUP_MEMBERSHIP_SCOPE);

        Resource usersResource = resourceStore.findByName(server, USERS_RESOURCE);
        if (usersResource == null) {
            usersResource = resourceStore.create(server, USERS_RESOURCE, server.getClientId());
            Set<Scope> scopeset = new HashSet<>();
            scopeset.add(manageScope);
            scopeset.add(viewScope);
            scopeset.add(mapRolesScope);
            scopeset.add(impersonateScope);
            scopeset.add(manageGroupMembershipScope);
            scopeset.add(userImpersonatedScope);
            usersResource.updateScopes(scopeset);
        }
        Policy managePermission = policyStore.findByName(server, MANAGE_PERMISSION_USERS);
        if (managePermission == null) {
            Helper.addEmptyScopePermission(authz, server, MANAGE_PERMISSION_USERS, usersResource, manageScope);
        }
        Policy viewPermission = policyStore.findByName(server, VIEW_PERMISSION_USERS);
        if (viewPermission == null) {
            Helper.addEmptyScopePermission(authz, server, VIEW_PERMISSION_USERS, usersResource, viewScope);
        }
        Policy mapRolesPermission = policyStore.findByName(server, MAP_ROLES_PERMISSION_USERS);
        if (mapRolesPermission == null) {
            Helper.addEmptyScopePermission(authz, server, MAP_ROLES_PERMISSION_USERS, usersResource, mapRolesScope);
        }
        Policy membershipPermission = policyStore.findByName(server, MANAGE_GROUP_MEMBERSHIP_PERMISSION_USERS);
        if (membershipPermission == null) {
            Helper.addEmptyScopePermission(authz, server, MANAGE_GROUP_MEMBERSHIP_PERMISSION_USERS, usersResource, manageGroupMembershipScope);
        }
        Policy impersonatePermission = policyStore.findByName(server, ADMIN_IMPERSONATING_PERMISSION);
        if (impersonatePermission == null) {
            Helper.addEmptyScopePermission(authz, server, ADMIN_IMPERSONATING_PERMISSION, usersResource, impersonateScope);
        }
        impersonatePermission = policyStore.findByName(server, USER_IMPERSONATED_PERMISSION);
        if (impersonatePermission == null) {
            Helper.addEmptyScopePermission(authz, server, USER_IMPERSONATED_PERMISSION, usersResource, userImpersonatedScope);
        }
    }

    @Override
    public Map<String, String> getPermissions() {
        initialize();
        Map<String, String> scopes = new LinkedHashMap<>();
        scopes.put(AdminPermissionManagement.VIEW_SCOPE, viewPermission().getId());
        scopes.put(AdminPermissionManagement.MANAGE_SCOPE, managePermission().getId());
        scopes.put(MAP_ROLES_SCOPE, mapRolesPermission().getId());
        scopes.put(MANAGE_GROUP_MEMBERSHIP_SCOPE, manageGroupMembershipPermission().getId());
        scopes.put(IMPERSONATE_SCOPE, adminImpersonatingPermission().getId());
        scopes.put(USER_IMPERSONATED_SCOPE, userImpersonatedPermission().getId());
        return scopes;
    }

    @Override
    public boolean isPermissionsEnabled() {
        ResourceServer server = root.realmResourceServer();
        if (server == null) return false;

        Resource resource =  resourceStore.findByName(server, USERS_RESOURCE);
        if (resource == null) return false;

        Policy policy = managePermission();

        return policy != null;
    }

    @Override
    public void setPermissionsEnabled(boolean enable) {
        if (enable) {
            initialize();
        } else {
            deletePermissionSetup();
        }
    }

    public boolean canManageDefault() {
        return root.hasOneAdminRole(AdminRoles.MANAGE_USERS);
    }

    @Override
    public Resource resource() {
        ResourceServer server = root.realmResourceServer();
        if (server == null) return null;

        return  resourceStore.findByName(server, USERS_RESOURCE);
    }

    @Override
    public Policy managePermission() {
        return policyStore.findByName(root.realmResourceServer(), MANAGE_PERMISSION_USERS);
    }

    @Override
    public Policy viewPermission() {
        return policyStore.findByName(root.realmResourceServer(), VIEW_PERMISSION_USERS);
    }

    @Override
    public Policy manageGroupMembershipPermission() {
        return policyStore.findByName(root.realmResourceServer(), MANAGE_GROUP_MEMBERSHIP_PERMISSION_USERS);
    }

    @Override
    public Policy mapRolesPermission() {
        return policyStore.findByName(root.realmResourceServer(), MAP_ROLES_PERMISSION_USERS);
    }

    @Override
    public Policy adminImpersonatingPermission() {
        return policyStore.findByName(root.realmResourceServer(), ADMIN_IMPERSONATING_PERMISSION);
    }

    @Override
    public Policy userImpersonatedPermission() {
        return policyStore.findByName(root.realmResourceServer(), USER_IMPERSONATED_PERMISSION);
    }

    /**
     * Is admin allowed to manage all users?  In Authz terms, does the admin have the "manage" scope for the Users Authz resource?
     *
     * This method will follow the old default behavior (does the admin have the manage-users role) if any of these conditions
     * are met.:
     * - The admin is from the master realm managing a different realm
     * - If the Authz objects are not set up correctly for the Users resource in Authz
     * - The "manage" permission for the Users resource has an empty associatedPolicy list.
     *
     * Otherwise, it will use the Authz policy engine to resolve this answer.
     *
     * @return
     */
    @Override
    public boolean canManage() {
        if (canManageDefault()) {
            return true;
        }

        if (!root.isAdminSameRealm()) {
            return false;
        }

        return hasPermission(MgmtPermissions.MANAGE_SCOPE);
    }

    @Override
    public void requireManage() {
        if (!canManage()) {
            throw new ForbiddenException();
        }
    }

    /**
     * Does current admin have manage permissions for this particular user?
     *
     * @param user
     * @return
     */
    @Override
    public boolean canManage(UserModel user) {
        return canManage() || canManageByGroup(user);
    }

    @Override
    public void requireManage(UserModel user) {
        if (!canManage(user)) {
            throw new ForbiddenException();
        }
    }

    @Override
    public boolean canQuery() {
        return canView() || root.hasOneAdminRole(AdminRoles.QUERY_USERS);
    }

    @Override
    public void requireQuery() {
        if (!canQuery()) {
            throw new ForbiddenException();
        }
    }

    /**
     * Is admin allowed to view all users?  In Authz terms, does the admin have the "view" scope for the Users Authz resource?
     *
     * This method will follow the old default behavior (does the admin have the view-users role) if any of these conditions
     * are met.:
     * - The admin is from the master realm managing a different realm
     * - If the Authz objects are not set up correctly for the Users resource in Authz
     * - The "view" permission for the Users resource has an empty associatedPolicy list.
     *
     * Otherwise, it will use the Authz policy engine to resolve this answer.
     *
     * @return
     */
    @Override
    public boolean canView() {
        if (canViewDefault() || canManageDefault()) {
            return true;
        }

        if (!root.isAdminSameRealm()) {
            return false;
        }

        return hasPermission(MgmtPermissions.VIEW_SCOPE, MgmtPermissions.MANAGE_SCOPE);
    }

    /**
     * Does current admin have view permissions for this particular user?
     *
     * Evaluates in this order. If any true, return true:
     * - canViewUsers
     * - canManageUsers
     *
     *
     * @param user
     * @return
     */
    @Override
    public boolean canView(UserModel user) {
        return canView() || canViewByGroup(user);
    }

    @Override
    public void requireView(UserModel user) {
        if (!canView(user)) {
            throw new ForbiddenException();
        }
    }

    @Override
    public void requireView() {
        if (!(canView())) {
            throw new ForbiddenException();
        }
    }

    @Override
    public boolean canClientImpersonate(ClientModel client, UserModel user) {
        ClientModelIdentity identity = new ClientModelIdentity(session, client);
        EvaluationContext context = new DefaultEvaluationContext(identity, session) {
            @Override
            public Map<String, Collection<String>> getBaseAttributes() {
                Map<String, Collection<String>> attributes = super.getBaseAttributes();
                attributes.put("kc.client.id", Arrays.asList(client.getClientId()));
                return attributes;
            }

        };
        return canImpersonate(context) && isImpersonatable(user);

    }

    @Override
    public boolean canImpersonate(UserModel user) {
        if (!canImpersonate()) {
            return false;
        }

        return isImpersonatable(user);
    }

    @Override
    public boolean isImpersonatable(UserModel user) {
        ResourceServer server = root.realmResourceServer();

        if (server == null) {
            return true;
        }

        Resource resource =  resourceStore.findByName(server, USERS_RESOURCE);

        if (resource == null) {
            return true;
        }

        Policy policy = authz.getStoreFactory().getPolicyStore().findByName(server, USER_IMPERSONATED_PERMISSION);

        if (policy == null) {
            return true;
        }

        Set<Policy> associatedPolicies = policy.getAssociatedPolicies();
        // if no policies attached to permission then just do default behavior
        if (associatedPolicies == null || associatedPolicies.isEmpty()) {
            return true;
        }

        return hasPermission(new DefaultEvaluationContext(new UserModelIdentity(root.realm, user), session), USER_IMPERSONATED_SCOPE);
    }

    @Override
    public boolean canImpersonate() {
        if (root.hasOneAdminRole(ImpersonationConstants.IMPERSONATION_ROLE)) return true;

        Identity identity = root.identity;

        if (!root.isAdminSameRealm()) {
            return false;
        }

        return canImpersonate(new DefaultEvaluationContext(identity, session));
    }

    @Override
    public void requireImpersonate(UserModel user) {
        if (!canImpersonate(user)) {
            throw new ForbiddenException();
        }
    }

    @Override
    public Map<String, Boolean> getAccess(UserModel user) {
        Map<String, Boolean> map = new HashMap<>();
        map.put("view", canView(user));
        map.put("manage", canManage(user));
        map.put("mapRoles", canMapRoles(user));
        map.put("manageGroupMembership", canManageGroupMembership(user));
        map.put("impersonate", canImpersonate(user));
        return map;
    }

    @Override
    public boolean canMapRoles(UserModel user) {
        if (canManage(user)) return true;

        if (!root.isAdminSameRealm()) {
            return false;
        }

        return hasPermission(MAP_ROLES_SCOPE);

    }

    @Override
    public void requireMapRoles(UserModel user) {
        if (!canMapRoles(user)) {
            throw new ForbiddenException();
        }

    }

    @Override
    public boolean canManageGroupMembership(UserModel user) {
        if (canManage(user)) return true;

        if (!root.isAdminSameRealm()) {
            return false;
        }

        return hasPermission(MANAGE_GROUP_MEMBERSHIP_SCOPE);

    }

    @Override
    public void grantIfNoPermission(boolean grantIfNoPermission) {
        this.grantIfNoPermission = grantIfNoPermission;
    }

    @Override
    public void requireManageGroupMembership(UserModel user) {
        if (!canManageGroupMembership(user)) {
            throw new ForbiddenException();
        }

    }

    private boolean hasPermission(String... scopes) {
        return hasPermission(null, scopes);
    }

    private boolean hasPermission(EvaluationContext context, String... scopes) {
        ResourceServer server = root.realmResourceServer();

        if (server == null) {
            return false;
        }

        Resource resource =  resourceStore.findByName(server, USERS_RESOURCE);
        List<String> expectedScopes = Arrays.asList(scopes);

        if (resource == null) {
            return grantIfNoPermission && expectedScopes.contains(MgmtPermissions.MANAGE_SCOPE) && expectedScopes.contains(MgmtPermissions.VIEW_SCOPE);
        }

        Collection<Permission> permissions;

        if (context == null) {
            permissions = root.evaluatePermission(new ResourcePermission(resource, resource.getScopes(), server), server);
        } else {
            permissions = root.evaluatePermission(new ResourcePermission(resource, resource.getScopes(), server), server, context);
        }

        for (Permission permission : permissions) {
            for (String scope : permission.getScopes()) {
                if (expectedScopes.contains(scope)) {
                    return true;
                }
            }
        }

        return false;
    }

    private void deletePermissionSetup() {
        ResourceServer server = root.realmResourceServer();
        if (server == null) return;
        Policy policy = managePermission();
        if (policy != null) {
            policyStore.delete(policy.getId());

        }
        policy = viewPermission();
        if (policy != null) {
            policyStore.delete(policy.getId());

        }
        policy = mapRolesPermission();
        if (policy != null) {
            policyStore.delete(policy.getId());

        }
        policy = manageGroupMembershipPermission();
        if (policy != null) {
            policyStore.delete(policy.getId());

        }
        policy = adminImpersonatingPermission();
        if (policy != null) {
            policyStore.delete(policy.getId());

        }
        policy = userImpersonatedPermission();
        if (policy != null) {
            policyStore.delete(policy.getId());

        }
        Resource usersResource = resourceStore.findByName(server, USERS_RESOURCE);
        if (usersResource != null) {
            resourceStore.delete(usersResource.getId());
        }
    }

    private boolean canImpersonate(EvaluationContext context) {
        return hasPermission(context, IMPERSONATE_SCOPE);
    }

    private boolean evaluateHierarchy(UserModel user, Predicate<GroupModel> eval) {
        Set<GroupModel> visited = new HashSet<>();
        return user.getGroupsStream().anyMatch(group -> evaluateHierarchy(eval, group, visited));
    }

    private boolean evaluateHierarchy(Predicate<GroupModel> eval, GroupModel group, Set<GroupModel> visited) {
        if (visited.contains(group)) return false;
        if (eval.test(group)) {
            return true;
        }
        visited.add(group);
        if (group.getParent() == null) return false;
        return evaluateHierarchy(eval, group.getParent(), visited);
    }

    private boolean canManageByGroup(UserModel user) {
        return evaluateHierarchy(user, (group) -> root.groups().canManageMembers(group));

    }
    private boolean canViewByGroup(UserModel user) {
        return evaluateHierarchy(user, (group) -> root.groups().getGroupsWithViewPermission(group));
    }

    public boolean canViewDefault() {
        return root.hasOneAdminRole(AdminRoles.MANAGE_USERS, AdminRoles.VIEW_USERS);
    }
}


Instruction:
作为 Java 安全专家，检测此代码中的安全漏洞：
## 内容1
### 文件路径：
extensions/smallrye-graphql/runtime/src/main/java/io/quarkus/smallrye/graphql/runtime/SmallRyeGraphQLAbstractHandler.java
### 代码内容：
package io.quarkus.smallrye.graphql.runtime;

import java.io.StringReader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.json.Json;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.json.JsonReaderFactory;

import io.quarkus.arc.Arc;
import io.quarkus.arc.ManagedContext;
import io.quarkus.security.identity.CurrentIdentityAssociation;
import io.quarkus.security.identity.SecurityIdentity;
import io.quarkus.vertx.http.runtime.CurrentVertxRequest;
import io.quarkus.vertx.http.runtime.security.QuarkusHttpUser;
import io.smallrye.graphql.execution.ExecutionService;
import io.vertx.core.Handler;
import io.vertx.core.MultiMap;
import io.vertx.ext.web.RoutingContext;

/**
 * Handler that does the execution of GraphQL Requests
 */
public abstract class SmallRyeGraphQLAbstractHandler implements Handler<RoutingContext> {

    private final CurrentIdentityAssociation currentIdentityAssociation;
    private final CurrentVertxRequest currentVertxRequest;
    private final ManagedContext currentManagedContext;
    private final Handler currentManagedContextTerminationHandler;
    private final boolean runBlocking;

    private volatile ExecutionService executionService;

    protected static final JsonReaderFactory jsonReaderFactory = Json.createReaderFactory(null);

    public SmallRyeGraphQLAbstractHandler(
            CurrentIdentityAssociation currentIdentityAssociation,
            CurrentVertxRequest currentVertxRequest,
            boolean runBlocking) {

        this.currentIdentityAssociation = currentIdentityAssociation;
        this.currentVertxRequest = currentVertxRequest;
        this.currentManagedContext = Arc.container().requestContext();
        this.runBlocking = runBlocking;
        this.currentManagedContextTerminationHandler = new Handler() {
            @Override
            public void handle(Object e) {
                currentManagedContext.terminate();
            }

        };
    }

    @Override
    public void handle(final RoutingContext ctx) {

        if (currentManagedContext.isActive()) {
            handleWithIdentity(ctx);
        } else {

            currentManagedContext.activate();
            ctx.response()
                    .endHandler(currentManagedContextTerminationHandler)
                    .exceptionHandler(currentManagedContextTerminationHandler)
                    .closeHandler(currentManagedContextTerminationHandler);

            try {
                handleWithIdentity(ctx);
            } catch (Throwable t) {
                currentManagedContext.terminate();
            }
        }
    }

    private Void handleWithIdentity(final RoutingContext ctx) {
        if (currentIdentityAssociation != null) {
            QuarkusHttpUser existing = (QuarkusHttpUser) ctx.user();
            if (existing != null) {
                SecurityIdentity identity = existing.getSecurityIdentity();
                currentIdentityAssociation.setIdentity(identity);
            } else {
                currentIdentityAssociation.setIdentity(QuarkusHttpUser.getSecurityIdentity(ctx, null));
            }
        }
        currentVertxRequest.setCurrent(ctx);
        doHandle(ctx);
        return null;
    }

    protected abstract void doHandle(final RoutingContext ctx);

    protected JsonObject inputToJsonObject(String input) {
        try (JsonReader jsonReader = jsonReaderFactory.createReader(new StringReader(input))) {
            return jsonReader.readObject();
        }
    }

    protected ExecutionService getExecutionService() {
        if (this.executionService == null) {
            this.executionService = Arc.container().instance(ExecutionService.class).get();
        }
        return this.executionService;
    }

    protected Map<String, Object> getMetaData(RoutingContext ctx) {
        // Add some context to dfe
        Map<String, Object> metaData = new ConcurrentHashMap<>();
        metaData.put("runBlocking", runBlocking);
        metaData.put("httpHeaders", getHeaders(ctx));
        return metaData;
    }

    private Map<String, List<String>> getHeaders(RoutingContext ctx) {
        Map<String, List<String>> h = new HashMap<>();
        MultiMap headers = ctx.request().headers();
        for (String header : headers.names()) {
            h.put(header, headers.getAll(header));
        }
        return h;
    }
}