Instruction:
作为 Java 安全专家，检测此代码中的安全漏洞：
## 内容1
### 文件路径：
inlong-manager/manager-common/src/main/java/org/apache/inlong/manager/common/consts/InlongConstants.java
### 代码内容：
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.inlong.manager.common.consts;

import org.apache.inlong.common.enums.DataProxyMsgEncType;

import com.google.common.collect.Sets;

import java.util.Set;
import java.util.regex.Pattern;

/**
 * Global constant for the Inlong system.
 */
public class InlongConstants {

    /**
     * Thread pool related config.
     */
    public static final int CORE_POOL_SIZE = 10;
    public static final int MAX_POOL_SIZE = 20;
    public static final long ALIVE_TIME_MS = 100L;
    public static final int QUEUE_SIZE = 10000;

    /**
     * Group config
     */
    public static final String COMMA = ",";

    public static final String DOT = ".";

    public static final String BLANK = " ";

    public static final String SLASH = "/";

    public static final String COLON = ":";

    public static final String EQUAL = "=";

    public static final String SEMICOLON = ";";

    public static final String HYPHEN = "-";

    public static final String UNDERSCORE = "_";

    public static final String LEFT_BRACKET = "(";

    public static final String PERCENT = "%";

    public static final String QUESTION_MARK = "?";

    public static final String NEW_LINE = "\n";

    public static final String ADMIN_USER = "admin";

    public static final Integer AFFECTED_ONE_ROW = 1;

    public static final Integer INITIAL_VERSION = 1;

    public static final Integer UN_DELETED = 0;

    public static final Integer DELETED_STATUS = 10;

    public static final Integer STANDARD_MODE = 0;
    public static final Integer DATASYNC_MODE = 1;

    public static final Integer DISABLE_ZK = 0;
    public static final Integer ENABLE_ZK = 1;

    public static final Integer DISABLE_CREATE_RESOURCE = 0;
    public static final Integer ENABLE_CREATE_RESOURCE = 1;

    /**
     * Data report type, support:
     *

     *     0: report to DataProxy and respond when the DataProxy received data.
     *     1: report to DataProxy and respond after DataProxy sends data.
     *     2: report to MQ and respond when the MQ received data.
     *

     */
    public static final Integer REPORT_TO_DP_RECEIVED = 0;
    public static final Integer REPORT_TO_DP_SENT = 1;
    public static final Integer REPORT_TO_MQ_RECEIVED = 2;

    public static final Integer UN_SYNC_SEND = 0;
    public static final Integer SYNC_SEND = 1;

    public static final String BATCH_TASK = "batch.task";

    /**
     * Pulsar config
     */
    public static final String PULSAR_AUTHENTICATION = "pulsar.authentication";

    public static final String PULSAR_AUTHENTICATION_TYPE = "pulsar.authentication.type";

    public static final String DEFAULT_PULSAR_TENANT = "public";

    public static final String DEFAULT_PULSAR_AUTHENTICATION_TYPE = "token";

    public static final String PULSAR_QUEUE_TYPE_SERIAL = "SERIAL";

    public static final String PULSAR_QUEUE_TYPE_PARALLEL = "PARALLEL";

    /**
     * Format of the Pulsar topic: "persistent://tenant/namespace/topic
     */
    public static final String PULSAR_TOPIC_FORMAT = "persistent://%s/%s/%s";

    /**
     * Sort config
     */
    public static final String DATAFLOW = "dataflow";

    public static final String STREAMS = "streams";

    public static final String RELATIONS = "relations";

    public static final String INPUTS = "inputs";

    public static final String OUTPUTS = "outputs";

    public static final String NODES = "nodes";

    public static final String NODE_TYPE = "type";

    public static final String LOAD = "Load";

    public static final String EXTRACT = "Extract";

    public static final String SORT_JOB_ID = "sort.job.id";

    public static final String SORT_TYPE = "sort.type";

    public static final String DEFAULT_SORT_TYPE = "flink";

    public static final String SORT_NAME = "sort.name";

    public static final String SORT_URL = "sort.url";

    public static final String SORT_AUTHENTICATION = "sort.authentication";

    public static final String SORT_AUTHENTICATION_TYPE = "sort.authentication.type";

    public static final String DEFAULT_SORT_AUTHENTICATION_TYPE = "secret_and_token";

    public static final String SORT_PROPERTIES = "sort.properties";

    public static final String DATA_TYPE_RAW_PREFIX = "RAW_";

    public static final int DEFAULT_ENABLE_VALUE = 1;

    public static final String STATEMENT_TYPE_SQL = "sql";
    public static final String STATEMENT_TYPE_JSON = "json";
    public static final String STATEMENT_TYPE_CSV = "csv";

    public static final String SORT_TYPE_INFO_SUFFIX = "TypeInfo";

    public static final Pattern PATTERN_NORMAL_CHARACTERS = Pattern.compile("^[a-zA-Z0-9_]*$");

    public static final Set<String> STREAM_FIELD_TYPES =
            Sets.newHashSet("string", "int", "long", "float", "double", "date", "timestamp");

    /**
     * The name prop when batch parsing fields in JSON mode
     */
    public static final String BATCH_PARSING_FILED_JSON_NAME_PROP = "name";

    /**
     * The type prop when batch parsing fields in JSON mode
     */
    public static final String BATCH_PARSING_FILED_JSON_TYPE_PROP = "type";

    /**
     * The comment prop when batch parsing fields in JSON mode
     */
    public static final String BATCH_PARSING_FILED_JSON_COMMENT_PROP = "desc";

    /**
     * Message compression type, 0: Raw message without any InLong format, 1: InlongMsgPb, 2: InlongMsg
     *

     * See more: {@link DataProxyMsgEncType}
     */
    public static final String MSG_ENCODE_VER = "msgEnType";

}

## 内容2
### 文件路径：
inlong-manager/manager-pojo/src/main/java/org/apache/inlong/manager/pojo/sink/mysql/MySQLSinkDTO.java
### 代码内容：
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.inlong.manager.pojo.sink.mysql;

import org.apache.inlong.manager.common.consts.InlongConstants;
import org.apache.inlong.manager.common.enums.ErrorCodeEnum;
import org.apache.inlong.manager.common.exceptions.BusinessException;
import org.apache.inlong.manager.common.util.CommonBeanUtils;
import org.apache.inlong.manager.common.util.JsonUtils;

import com.google.common.base.Strings;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.validation.constraints.NotNull;

import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * MySQL sink info
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class MySQLSinkDTO {

    /**
     * The sensitive param may lead the attack.
     */
    private static final Map<String, String> SENSITIVE_REPLACE_PARAM_MAP = new HashMap<String, String>() {

        {
            put("autoDeserialize", "false");
            put("allowLoadLocalInfile", "false");
            put("allowUrlInLocalInfile", "false");
        }
    };

    private static final Set<String> SENSITIVE_REMOVE_PARAM_MAP = new HashSet<String>() {

        {
            add("allowLoadLocalInfileInPath");
        }
    };

    private static final Logger LOGGER = LoggerFactory.getLogger(MySQLSinkDTO.class);
    private static final String MYSQL_JDBC_PREFIX = "jdbc:mysql://";

    @ApiModelProperty("MySQL JDBC URL, such as jdbc:mysql://host:port")
    private String jdbcUrl;

    @ApiModelProperty("Username for JDBC URL")
    private String username;

    @ApiModelProperty("User password")
    private String password;

    @ApiModelProperty("Target database name")
    private String databaseName;

    @ApiModelProperty("Target table name")
    private String tableName;

    @ApiModelProperty("Primary key")
    private String primaryKey;

    @ApiModelProperty("Properties for MySQL")
    private Map<String, Object> properties;

    /**
     * Get the dto instance from the request
     *
     * @param request MySQLSinkRequest
     * @return {@link MySQLSinkDTO}
     * @apiNote The config here will be saved to the database, so filter sensitive params before saving.
     */
    public static MySQLSinkDTO getFromRequest(MySQLSinkRequest request, String extParams) {
        MySQLSinkDTO dto = StringUtils.isNotBlank(extParams) ? MySQLSinkDTO.getFromJson(extParams) : new MySQLSinkDTO();
        CommonBeanUtils.copyProperties(request, dto, true);
        dto.setJdbcUrl(filterSensitive(request.getJdbcUrl()));
        return dto;
    }

    /**
     * Get MySQL sink info from JSON string
     *
     * @param extParams string ext params
     * @return {@link MySQLSinkDTO}
     */
    public static MySQLSinkDTO getFromJson(@NotNull String extParams) {
        try {
            return JsonUtils.parseObject(extParams, MySQLSinkDTO.class);
        } catch (Exception e) {
            throw new BusinessException(ErrorCodeEnum.SINK_INFO_INCORRECT,
                    String.format("parse extParams of MySQL SinkDTO failure: %s", e.getMessage()));
        }
    }

    /**
     * Get MySQL table info
     *
     * @param mySQLSink MySQL sink dto,{@link MySQLSinkDTO}
     * @param columnList MySQL column info list,{@link MySQLColumnInfo}
     * @return {@link MySQLTableInfo}
     */
    public static MySQLTableInfo getTableInfo(MySQLSinkDTO mySQLSink, List<MySQLColumnInfo> columnList) {
        MySQLTableInfo tableInfo = new MySQLTableInfo();
        tableInfo.setDbName(mySQLSink.getDatabaseName());
        tableInfo.setTableName(mySQLSink.getTableName());
        tableInfo.setPrimaryKey(mySQLSink.getPrimaryKey());
        tableInfo.setColumns(columnList);
        return tableInfo;
    }

    /**
     * Get DbName from jdbcUrl
     *
     * @param jdbcUrl MySQL JDBC url, such as jdbc:mysql://host:port/database
     * @return database name
     */
    private static String getDbNameFromUrl(String jdbcUrl) {
        String database = null;

        if (Strings.isNullOrEmpty(jdbcUrl)) {
            throw new IllegalArgumentException("Invalid JDBC url.");
        }

        jdbcUrl = jdbcUrl.toLowerCase();
        if (jdbcUrl.startsWith("jdbc:impala")) {
            jdbcUrl = jdbcUrl.replace(":impala", "");
        }

        int pos1;
        if (!jdbcUrl.startsWith("jdbc:")
                || (pos1 = jdbcUrl.indexOf(':', 5)) == -1) {
            throw new IllegalArgumentException("Invalid JDBC url.");
        }

        String connUri = jdbcUrl.substring(pos1 + 1);
        if (connUri.startsWith("//")) {
            int pos = connUri.indexOf('/', 2);
            if (pos != -1) {
                database = connUri.substring(pos + 1);
            }
        } else {
            database = connUri;
        }

        if (Strings.isNullOrEmpty(database)) {
            throw new IllegalArgumentException("Invalid JDBC URL: " + jdbcUrl);
        }

        if (database.contains(InlongConstants.QUESTION_MARK)) {
            database = database.substring(0, database.indexOf(InlongConstants.QUESTION_MARK));
        }
        if (database.contains(InlongConstants.SEMICOLON)) {
            database = database.substring(0, database.indexOf(InlongConstants.SEMICOLON));
        }
        return database;
    }

    public static String setDbNameToUrl(String jdbcUrl, String databaseName) {
        if (StringUtils.isBlank(jdbcUrl)) {
            return jdbcUrl;
        }
        String pattern = "jdbc:mysql://(?<host>[a-zA-Z0-9-//.]+):(?<port>[0-9]+)?(?<ext>)";
        Pattern namePattern = Pattern.compile(pattern);
        Matcher dataMatcher = namePattern.matcher(jdbcUrl);
        StringBuilder resultUrl;
        if (dataMatcher.find()) {
            String host = dataMatcher.group("host");
            String port = dataMatcher.group("port");
            resultUrl = new StringBuilder().append(MYSQL_JDBC_PREFIX)
                    .append(host)
                    .append(InlongConstants.COLON)
                    .append(port)
                    .append(InlongConstants.SLASH)
                    .append(databaseName);
        } else {
            throw new BusinessException(ErrorCodeEnum.SINK_INFO_INCORRECT,
                    "MySQL JDBC URL was invalid, it should like jdbc:mysql://host:port");
        }
        if (jdbcUrl.contains(InlongConstants.QUESTION_MARK)) {
            resultUrl.append(jdbcUrl.substring(jdbcUrl.indexOf(InlongConstants.QUESTION_MARK)));
        }
        return resultUrl.toString();
    }

    /**
     * Filter the sensitive params for the given URL.
     *
     * @param url str may have some sensitive params
     * @return str without sensitive param
     */
    public static String filterSensitive(String url) {
        if (StringUtils.isBlank(url)) {
            return url;
        }

        try {
            String resultUrl = url;
            while (resultUrl.contains(InlongConstants.PERCENT)) {
                resultUrl = URLDecoder.decode(resultUrl, "UTF-8");
            }
            resultUrl = resultUrl.replaceAll(InlongConstants.BLANK, "");

            if (resultUrl.contains(InlongConstants.QUESTION_MARK)) {
                StringBuilder builder = new StringBuilder();
                builder.append(StringUtils.substringBefore(resultUrl, InlongConstants.QUESTION_MARK));
                builder.append(InlongConstants.QUESTION_MARK);

                List<String> paramList = new ArrayList<>();
                String queryString = StringUtils.substringAfter(resultUrl, InlongConstants.QUESTION_MARK);
                for (String param : queryString.split("&")) {
                    String key = StringUtils.substringBefore(param, "=");
                    String value = StringUtils.substringAfter(param, "=");

                    if (SENSITIVE_REMOVE_PARAM_MAP.contains(key) || SENSITIVE_REPLACE_PARAM_MAP.containsKey(key)) {
                        continue;
                    }

                    paramList.add(key + "=" + value);
                }
                SENSITIVE_REPLACE_PARAM_MAP.forEach((key, value) -> paramList.add(key + "=" + value));

                String params = StringUtils.join(paramList, "&");
                builder.append(params);
                resultUrl = builder.toString();
            }

            LOGGER.info("the origin url [{}] was replaced to: [{}]", url, resultUrl);
            return resultUrl;
        } catch (Exception e) {
            throw new BusinessException(ErrorCodeEnum.SINK_INFO_INCORRECT,
                    ErrorCodeEnum.SINK_INFO_INCORRECT.getMessage() + ": " + e.getMessage());
        }
    }

}

Output:
【漏洞类型】路径遍历漏洞
【严重性】High
【漏洞摘要】通过在MySQL JDBC URL中注入特殊参数，攻击者可以操纵数据库连接字符串，从而访问或执行不应该访问的文件或数据库操作。具体表现为在`filterSensitive`方法中，未正确处理和过滤URL中的空白字符和`&`符号，可能导致路径遍历攻击。根本原因在于代码中使用了硬编码的空白字符和`&`符号进行字符串操作，而不是使用更安全的正则表达式或预定义的常量。
【关键代码模式】`filterSensitive`方法中的`InlongConstants.BLANK`、`InlongConstants.QUESTION_MARK`和`InlongConstants.AMPERSAND`等常量的使用。
【修复方法说明】通过在`filterSensitive`方法中替换空白字符为预定义的空字符串，并使用正则表达式替换空白字符，增强了对URL中空白字符处理的安全性。同时，更改了URL参数的分割和连接符号，避免了使用硬编码的符号，提高了代码的安全性。


Instruction:
作为 Java 安全专家，检测此代码中的安全漏洞：
## 内容1
### 文件路径：
shenyu-admin/src/main/java/org/apache/shenyu/admin/service/impl/SandboxServiceImpl.java
### 代码内容：
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.shenyu.admin.service.impl;

import okhttp3.Response;
import okhttp3.ResponseBody;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.shenyu.admin.model.dto.ProxyGatewayDTO;
import org.apache.shenyu.admin.model.entity.AppAuthDO;
import org.apache.shenyu.admin.service.AppAuthService;
import org.apache.shenyu.admin.service.SandboxService;
import org.apache.shenyu.admin.utils.Assert;
import org.apache.shenyu.admin.utils.HttpUtils;
import org.apache.shenyu.admin.utils.ShenyuSignatureUtils;
import org.apache.shenyu.admin.utils.UploadUtils;
import org.apache.shenyu.common.constant.Constants;
import org.apache.shenyu.common.utils.JsonUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.util.UriComponents;
import org.springframework.web.util.UriComponentsBuilder;
import org.springframework.web.util.UriUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * sandbox service.
 */
@Service
public class SandboxServiceImpl implements SandboxService {

    private static final Logger LOG = LoggerFactory.getLogger(SandboxServiceImpl.class);

    private static final HttpUtils HTTP_UTILS = new HttpUtils();

    private final AppAuthService appAuthService;

    public SandboxServiceImpl(final AppAuthService appAuthService) {
        this.appAuthService = appAuthService;
    }

    @Override
    public void requestProxyGateway(final ProxyGatewayDTO proxyGatewayDTO, final HttpServletRequest request, final HttpServletResponse response) throws IOException {
        // Public request headers.
        Map<String, String> header = this.buildReqHeaders(proxyGatewayDTO);

        String appKey = proxyGatewayDTO.getAppKey();
        UriComponents uriComponents = UriComponentsBuilder.fromHttpUrl(proxyGatewayDTO.getRequestUrl()).build();
        String signContent = null;
        String sign = null;
        if (StringUtils.isNotEmpty(appKey)) {
            String timestamp = String.valueOf(Instant.now().toEpochMilli());
            String secureKey = getSecureKey(appKey);
            Assert.notBlack(secureKey, Constants.SIGN_APP_KEY_IS_NOT_EXIST);
            signContent = ShenyuSignatureUtils.getSignContent(secureKey, timestamp, uriComponents.getPath());
            sign = ShenyuSignatureUtils.generateSign(signContent);
            header.put("timestamp", timestamp);
            header.put("appKey", appKey);
            header.put("sign", sign);
            header.put("version", ShenyuSignatureUtils.VERSION);
        }

        // Public request parameters.
        Map<String, Object> reqParams = this.buildReqBizParams(proxyGatewayDTO);
        List<HttpUtils.UploadFile> files = this.uploadFiles(request);
        Response resp = HTTP_UTILS.requestCall(uriComponents.toUriString(), reqParams, header, HttpUtils.HTTPMethod.fromValue(proxyGatewayDTO.getHttpMethod()), files);
        ResponseBody body = resp.body();

        if (Objects.isNull(body)) {
            return;
        }
        if (StringUtils.isNotEmpty(appKey)) {
            response.addHeader("sandbox-beforesign", UriUtils.encode(signContent, StandardCharsets.UTF_8));
            response.addHeader("sandbox-sign", UriUtils.encode(sign, StandardCharsets.UTF_8));
        }

        IOUtils.copy(body.byteStream(), response.getOutputStream());
        response.flushBuffer();
    }

    private Map<String, String> buildReqHeaders(final ProxyGatewayDTO proxyGatewayDTO) {
        Map<String, String> reqHeaders = new HashMap<>();
        try {
            String reqJson = JsonUtils.toJson(proxyGatewayDTO.getHeaders());
            Map<String, String> reqMap = JsonUtils.jsonToMap(reqJson, String.class);
            LOG.info("Sandbox Request Headers. toMap={}", JsonUtils.toJson(reqMap));
            reqHeaders.putAll(reqMap);
        } catch (Exception e) {
            LOG.error("proxyGateway JsonUtils.toMap error={}", e.getMessage());
        }
        return reqHeaders;
    }

    private Map<String, Object> buildReqBizParams(final ProxyGatewayDTO proxyGatewayDTO) {
        Map<String, Object> reqParams = new HashMap<>();
        try {
            Map<String, Object> reqMap = JsonUtils.toMap(proxyGatewayDTO.getBizParam());
            LOG.info("sandbox Request Params. toMap={}", JsonUtils.toJson(reqMap));
            reqParams.putAll(reqMap);
        } catch (Exception e) {
            LOG.error("proxyGateway JsonUtils.toMap error={}", e.getMessage());
        }
        return reqParams;
    }

    private String getSecureKey(final String appKey) {
        AppAuthDO appAuthDO = appAuthService.findByAppKey(appKey);
        return Objects.nonNull(appAuthDO) ? appAuthDO.getAppSecret() : null;
    }

    private List<HttpUtils.UploadFile> uploadFiles(final HttpServletRequest request) {
        Collection<MultipartFile> uploadFiles = UploadUtils.getUploadFiles(request);
        return uploadFiles.stream()
            .map(multipartFile -> {
                try {
                    return new HttpUtils.UploadFile(multipartFile.getName(), multipartFile.getOriginalFilename(), multipartFile.getBytes());
                } catch (IOException e) {
                    LOG.error("upload file fail", e);
                    return null;
                }
            })
            .filter(Objects::nonNull)
            .collect(Collectors.toList());
    }

}

## 内容2
### 文件路径：
shenyu-common/src/main/java/org/apache/shenyu/common/utils/UriUtils.java
### 代码内容：
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.shenyu.common.utils;

import org.apache.commons.lang3.StringUtils;

import java.net.URI;
import java.util.Objects;

/**
 * uri util.
 */
public class UriUtils {

    private static final String PRE_FIX = "/";

    /**
     * create URI {@link URI}.
     *
     * @param uri uri string eg:/fallback
     * @return created {@link URI} from uri
     */
    public static URI createUri(final String uri) {
        if (StringUtils.isNotBlank(uri)) {
            return URI.create(uri);
        }
        return null;
    }

    /**
     * Repair data string.
     *
     * @param name the name
     * @return the string
     */
    public static String repairData(final String name) {
        return name.startsWith(PRE_FIX) ? name : PRE_FIX + name;
    }

    /**
     * Remove prefix string.
     *
     * @param name the name
     * @return the string
     */
    public static String removePrefix(final String name) {
        return name.startsWith(PRE_FIX) ? name.substring(1) : name;
    }

    /**
     * Get the path of uri with parameters.
     *
     * @param uri the uri.
     * @return absolute uri string with parameters.
     */
    public static String getPathWithParams(final URI uri) {
        if (Objects.isNull(uri)) {
            return StringUtils.EMPTY;
        }
        String params = StringUtils.isEmpty(uri.getQuery()) ? "" : "?" + uri.getQuery();
        return uri.getPath() + params;
    }

    /**
     * appendScheme.
     *
     * @param scheme scheme
     * @param url url
     * @return {@link String}
     */
    public static String appendScheme(final String url, final String scheme) {
        String schemeUrl = url;
        if (!schemeUrl.startsWith("http://") && !schemeUrl.startsWith("https://")) {
            schemeUrl = scheme + "://" + schemeUrl;
        }
        return schemeUrl;
    }
}

Output:
【漏洞类型】注入漏洞
【严重性】High
【漏洞摘要】此代码允许用户通过`ProxyGatewayDTO`对象传递一个任意的请求URL，而没有对这个URL进行任何验证或限制。这可能导致攻击者将请求发送到目标服务器上的任意URL，例如，通过注入恶意的URL，攻击者可能尝试执行恶意操作或窃取敏感信息。
【关键代码模式】`proxyGatewayDTO.getRequestUrl()`、`UriComponentsBuilder.fromHttpUrl`
【修复方法说明】修复方法通过获取允许的主机和端口号的集合，并检查请求的URL是否在该集合中来限制用户传递的请求URL。如果不在集合中，则记录错误日志并抛出异常。


Instruction:
作为 Java 安全专家，检测此代码中的安全漏洞：
## 内容1
### 文件路径：
ui/src/main/resources/IdentityOAuth/IdentityOAuthConfigMacros.vm
### 代码内容：
{{velocity output=false}}

## Identity OAuth Config macros
## - a set of macros useful for editing the OAuth-related configurations
## - this page should be included with #includeInContext("IdentityOAuth.IdentityOAuthConfigMacros")
##   so that it defines a few useful constants which you can use, includes javascript and stylesheee
##   extensions. The macros it defines should be called after all necessary variables are defined,
##   notably oauthProviderHint.
## lets the JavaScript and CSS extensions be loaded
#set ($mainReference = $services.model.createDocumentReference('', 'IdentityOAuth', 'WebPreferences'))
#if (!$services.licensing.licensor.hasLicensureForEntity($mainReference))
  $services.identityoauth.init()

  #macro (ioIncludeUIX)
    $xwiki.jsx.use('IdentityOAuth.IdentityOAuthConfigClass')
    $xwiki.ssx.use('IdentityOAuth.IdentityOAuthConfigClass')
  #end

  ## defines formId, propNamePrefixIO, propNamePrefixO, configDoc, objIO, objO
  #macro (initConfigObjects $configDocName $extraObjectClassPropPrefixes $translationPrefixesP)
    #set($formId = "${section.toLowerCase()}_${configDocName1}")
    #set($configDoc = $xwiki.getDocument($configDocName))

    #set($classNameIO="IdentityOAuth.IdentityOAuthConfigClass")
    #set($propNamePrefixIO="${configDoc.fullName}_${classNameIO}_0")
    #set($objIO = $configDoc.getObject($classNameIO))

    #set($translationPrefixes = [])
    #foreach($p in $translationPrefixesP)
      #set($nuts=$translationPrefixes.add($p))
    #end
    #set($nuts=$translationPrefixes.add('IdentityOAuth.IdentityOAuthConfigClass_'))

    #foreach($x in $extraObjectClassPropPrefixes)
      #set($shhh = $x.add($x[0]))
      #set($x[0] = $configDoc.getObject($x[0]))
    #end
  #end

  ## t: shorthand for translation
  #macro (alignWithTranslationPrefixes $name)
    #set($tn = [])
    #foreach($p in $translationPrefixes)
      #set($nuts=$tn.add("${p}${name}"))
    #end
  #end
  #macro (t $name)
    #alignWithTranslationPrefixes($name)
    $services.localization.render($tn)
  #end

  ## tp: shorthand for translation with parameters
  #macro (tp $name $params)##
    #alignWithTranslationPrefixes($name)
    #set ($msg = $services.localization.render($tn,$params))##
    ## convert to link-text for the simple wiki syntax of links
    $stringtool.replacePattern($msg, '\[\[([^>]*)>>([^\]]*)\]\]', '$1')##
  #end

  ## displayInput: displays the form element of the relevant property of the object having removed the
  ##   html macro around it.
  #macro (displayInput $property $obj)
    #set ($output = $doc.display($property, 'edit', $obj))
    #set ($output = $stringtool.removeStart($output, '{{html clean="false" wiki="false"}}'))
    #set ($output = $stringtool.removeEnd($output, '{{/html}}'))
    $output
  #end

  #macro (renderRedirectUrlInputAndHints)
    #displayInput ('redirectUrl', $objIO)

    #t('redirectUrl.asExpected')
    #t('redirectUrl.asExpectedServers')
    #t('redirectUrl.asExpectedBrowsers')
    #t('redirectUrl.notAsExpectedAny')
    ##
      (#t('redirectUrl.recalc.predicted'))
    ##
      (#t('redirectUrl.recalc.browser'))

      (#t('redirectUrl.recalc.server'))
  #end

  #macro (calcReturnUrlsJS)

  #end

  #set($hasLoadedMacros=true)
#end
{{/velocity}}
## 内容2
### 文件路径：
ui/src/main/resources/IdentityOAuth/LoginUIExtension.vm
### 代码内容：
{{velocity output="false"}}
#macro (renderLoginCodes $loginCodes $hasSeveralLogins)
  #set ($count = 0)
  #set ($loginCodeWrapperStart = '
')
  #foreach ($loginCode in $identityOAuth.renderLoginCodes())
    #set ($count = $mathtool.add($count, 1))
    #set ($loginCodes="${loginCodes}${loginCodeWrapperStart}${loginCode}
")
  #end
  #set ($hasSeveralLogins = $count > 0)
#end
{{/velocity}}

{{velocity}}
#set ($mainReference = $services.model.createDocumentReference('', 'IdentityOAuth', 'WebPreferences'))
#set ($generalConfigDoc = $xwiki.getDocument('IdentityOAuth.IdentityOAuthGeneralConfiguration'))
#set ($generalConfigObj = $generalConfigDoc.getObject('IdentityOAuth.IdentityOAuthGeneralConfigClass'))
#if ($xcontext.getAction()=="login" && $doc.fullName=="XWiki.XWikiLogin")
  #if (!$services.licensing.licensor.hasLicensureForEntity($mainReference))
    #set($statusMessage = "identityOAuth installed but not licensed.")
  #else
    #set($identityOAuth = $services.idoauth)
    #if ($identityOAuth.doesDetectReturn())
      #set($statusMessage = "IdentityOAuth: return of the OAuth bounce; if all goes well, the user can be logged in.")
      #set($result = $identityOAuth.processOAuthReturn())
      #set($prfx = "failed login:")
      #if ($result.startsWith($prfx))
        #set($email = $result.substring($prfx.length()))
        #set($errorMsg = " ${services.localization.render('idoauth.login.domainerror1')} ")
        #set($errorMsg = " ${errorMsg} ${services.localization.render('idoauth.login.domainerror2')} $!{email}.")
        #set($errorMsg = " ${errorMsg} ${services.localization.render('idoauth.login.domainerror3')}")
      #elseif ($result=="ok")
        #set($successM = ${services.localization.render("idoauth.login.redirectmessage")})
        ## the browser should have been redirected by processOAuthReturn
      #else ## $result is "no user"
        #set($errorMsg = ${services.localization.render('idoauth.login.message')})
        #set($errorMsg = " ${errorMsg} ${services.localization.render('idoauth.login.error')}")
        #if($request.getAttribute("idoauth-error-message"))
          #set($errorMsg = "${errorMsg}: ${request.getAttribute('idoauth-error-message')}")
        #end
      #end
    #elseif ($request.identityOAuth == "start")
      ## Don't alter the login form in case the XWiki default implementation is requested.
      #if ("$!request.provider" != "default")
        #set($statusMsg = "IdentityOAuth Start login, should bounce to the provider.")
        #set($succesMsg = $services.localization.render("idoauth.login.oauth.message"))
        #set($success = $identityOAuth.processOAuthStart())
        #if($success)
          #if($request.state)
            #set($successMsg = $services.localization.render("idoauth.login.oauth.successwithredirect"))
          #else
            #set($successMsg = $services.localization.render("idoauth.login.oauth.success"))
          #end
        #else
          #set($errorMsg = $services.localization.render("idoauth.login.oauth.failedOAuth"))
        #end
      #end
    #elseif ($request.identityOAuth)
      #set($statusMsg = "no such identityOAuth operation '$request.identityOAuth'")
    #else
      #set($statusMsg = "Login page")
      ## assemble the login code from the providers
      #set($loginCodes = '

')
      #renderLoginCodes($loginCodes $hasSeveralLogins)
      #set($loginCodes="${loginCodes}

")
    #end

    ## ============================================== end of velocity preparation ===============================

    {{html clean="false" wiki="false"}}

    #if ($successMsg || $errorMsg)

    #elseif($hasSeveralLogins)

    #end ## if ($successMsg || $errorMsg)
  {{/html}}
  #end ## identityOAuth is active
#end ## on login page
{{/velocity}}

## 内容3
### 文件路径：
ui/src/main/resources/IdentityOAuth/Translations.de.properties
### 代码内容：
admin.idoauth=Identity OAuth

idoauth.config.heading=Einstellungen des OAuth Providers
IdentityOAuth.IdentityOAuthConfigClass_config.explanation=XWiki kann mit externen Identitätsanbietern verbunden werdeb.

## Adminstration interface
IdentityOAuth.IdentityOAuthConfigClass_active=Aktivieren
IdentityOAuth.IdentityOAuthConfigClass_communicate=Schnittstellen zu dem OAuth Provider
IdentityOAuth.IdentityOAuthConfigClass_communicate.hint=Um eine OAuth Integration zu aktivieren, musst du {0}dein Wiki als App für den OAuth Zugang bei dem Provider registrieren{1} und die genannten Client-ID und Clientschlüssel in den folgenden Einstellungen einfügen.
IdentityOAuth.IdentityOAuthConfigClass_communicate.hint2=Du erhälst mehr Information in den {0}Installationsanweisungen{1}.

IdentityOAuth.IdentityOAuthConfigClass_appname=Name
IdentityOAuth.IdentityOAuthConfigClass_appname.hint=Für deine eigene Organisation
IdentityOAuth.IdentityOAuthConfigClass_clientid=Client-ID
IdentityOAuth.IdentityOAuthConfigClass_clientid.hint=Wird vom Provider genannt.
IdentityOAuth.IdentityOAuthConfigClass_secret=Clientschlüssel
IdentityOAuth.IdentityOAuthConfigClass_secret.hint=Wird vom Provider genannt.

IdentityOAuth.IdentityOAuthConfigClass_scope=Autorisierungen
IdentityOAuth.IdentityOAuthConfigClass_scope.hint=Welche Information sollte dieses Wiki von dem Provider abfragen?
IdentityOAuth.IdentityOAuthConfigClass_scope_identity=Vor- und Nachname.
IdentityOAuth.IdentityOAuthConfigClass_scope_email=Emailadresse.
IdentityOAuth.IdentityOAuthConfigClass_scope_avatar=Benutzerprofilbild
IdentityOAuth.IdentityOAuthConfigClass_checkbox_mandatory=Diese Autorisierung ist nötig.
IdentityOAuth.IdentityOAuthConfigClass_checkbox_notyetdone=Diese Autorisierung wird noch implementiert.

IdentityOAuth.IdentityOAuthConfigClass_redirectUrl=Rückkehr-URL
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.hint=Ein Benutzer macht seinen Rückkehr auf dieser Seite (mit Extraparametern) nachdem die Autorisierungen bestätigt wurden.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.asExpected=Diese Adresse ist dieselbe als die von der Loginseite des Wikis, bestimmt durch die aktuelle Browseradresse.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.notAsExpected=Diese Adresse ist nicht dieselbe als die von der Loginseite des Wikis, bestimmt durch die aktuelle Browseradresse.

IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.placeHolderMessage=(Defautwert: berechnet durch vom Server; {0})
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.asExpectedServers=Diese Adresse entspricht die Loginseitenadresse, die das Server berechnet.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.asExpectedBrowsers=Diese Adresse entspricht die Loginseitenadresse, die aus der Browseradresse berechnet werden kann.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.notAsExpectedAny=Diese Adresse Entspricht keine bekannte Loginseitenadresse.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.recalc.predicted=Die Adresse neu berechnen.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.recalc.browser=Die Adresse durch das Server berechnen lassen.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.recalc.server=Die Adresse ab der Browseradresse berechnen.

IdentityOAuth.IdentityOAuthConfigClass_loginbehaviour=XWiki Anmeldungsvorgang
IdentityOAuth.IdentityOAuthConfigClass_useCookies=Cookies anwenden, um die Identifizierung zu erinnern
IdentityOAuth.IdentityOAuthConfigClass_useCookies.hint=Diese Cookies erlauben Browsers zu erinnern, welche Benutzer benutzt war, um sich zum Wiki anzumelden.

IdentityOAuth.IdentityOAuthConfigClass_warningIncomplete=Die gesamte Informationen sind nötig.

IdentityOAuth.IdentityOAuthConfigClass_nowWhat1=Nachdem es gemacht ist, bitte logge dich aus und dann logge dich ein mit dem Provider.
IdentityOAuth.IdentityOAuthConfigClass_nowWhat2=Wenn du technische Schwierigkeiten hast, dann schreibe bitte support@xwiki.com an.

idoauth.login.title=Identity OAuth Login
idoauth.login.withoauth=Mit einem OAuth Provider einloggen
idoauth.login.withxwiki=Mit XWiki einloggen

## error reporting
idoauth.login.error=Ein Fehler ist während des Logins mit einem OAuth Providers entstanden. Bitte nehmen Sie Kontakt mit dem Administrator oder XWiki Support.
idoauth.login.message=Du wirst zum OAuth Provider für die Autorisierung weitergeleitet.
idoauth.login.redirectmessage=Du wirst zur angeforderte Seite weitergeleitet.
idoauth.login.oauth.message=OAuth Autorisieriung im Lauf
idoauth.login.oauth.success=Erfolgreiche Autorisierung.
idoauth.login.oauth.successwithredirect=Erfolgreiche Autorisierung. Du wirst zur angeforderte Seite weitergeleitet.

idoauth.error.noValidLicense=Diese App hat keine gültige Lizenz. Bitte die Lizenzeinstellungseite (in dem Abschnitt Erweiterungen der globalen Einstelllungen) besuchen, um eine zu erhalten.
idoauth.error.extensionDisabled=Die OAuth Integration ist auf dieses Wiki deaktiviert.

idoauth.webHome.1=Dieses Space ist der Code der Identity OAuth Erweiterung. Sie hilft die Integration von OAuth Providers zu leisten.
idoauth.webHome.2=...
idoauth.webHome.3=...
idoauth.webHome.4=Provider-spezifische Einstellungen sind nötig. Bitte besuche den Provider''s Abschnitt der XWiki Einstellungen, damit sie angepasst werden.

## 内容4
### 文件路径：
ui/src/main/resources/IdentityOAuth/Translations.fr.properties
### 代码内容：
admin.idoauth=Identity OAuth

idoauth.config.heading=Configuration Intégration OAuth
IdentityOAuth.IdentityOAuthConfigClass_config.explanation=XWiki peut être intégré avec un fournisseur externe d'identité.

## Adminstration interface
IdentityOAuth.IdentityOAuthConfigClass_active=Activer
IdentityOAuth.IdentityOAuthConfigClass_communicate=Communication avec les services OAuth
IdentityOAuth.IdentityOAuthConfigClass_communicate.hint=Afin d''activer l''intégration OAuth vous devez vous enregistrer pour l''accès à OAuth chez le fournisseur et insérer les informations dans les paramètres suivants.
IdentityOAuth.IdentityOAuthConfigClass_communicate.hint2=Voir aussi {0}les instructions d''installation{1}.

IdentityOAuth.IdentityOAuthConfigClass_appname=Nom de l'application
IdentityOAuth.IdentityOAuthConfigClass_appname.hint=Pour votre propre organisation.
IdentityOAuth.IdentityOAuthConfigClass_clientid=ID client
IdentityOAuth.IdentityOAuthConfigClass_clientid.hint=Indiqué dans la page de l'application.
IdentityOAuth.IdentityOAuthConfigClass_secret=Clé secrète
IdentityOAuth.IdentityOAuthConfigClass_secret.hint=Indiqué dans la page de l'application.

IdentityOAuth.IdentityOAuthConfigClass_scope=Types de  permissions
IdentityOAuth.IdentityOAuthConfigClass_scope.hint=Quelle information devrait être demandées par le wiki au fournisseurs d'identités?
IdentityOAuth.IdentityOAuthConfigClass_scope_identity=Nom et prénom
IdentityOAuth.IdentityOAuthConfigClass_scope_email=Adresse email
IdentityOAuth.IdentityOAuthConfigClass_scope_avatar=Photo de profil
IdentityOAuth.IdentityOAuthConfigClass_checkbox_mandatory=Ceci est nécessaire
IdentityOAuth.IdentityOAuthConfigClass_checkbox_notyetdone=Ceci n'est pas encore implémenté

IdentityOAuth.IdentityOAuthConfigClass_redirectUrl=URL de retour
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.hint=L'utilisateur revient à la page de login de ce wiki avec des paramètres supplémentaires pour indiquer l'autorisation OAuth.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.asExpected=Ceci devrait être la bonne adresse d'après l'adresse de votre navigateur.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.notAsExpected=Ceci ne correspond pas à l'adresse de votre navigateur.

IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.placeHolderMessage=(valuer par défaut: calculée par le serveur; {0})
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.asExpectedServers=Cette adresse correspond à l'adresse de la page de connexion ainsi que calculée par votre serveur.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.asExpectedBrowsers=Cette adresse correspond à l'adresse de la page de connexion ainsi que calculée par votre navigateur.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.notAsExpectedAny=Cette adresse ne correspond pas à l'adresse connue de la page de connexion.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.recalc.predicted=Recalculer l'adresse
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.recalc.browser=Recalculer l'adresse d'après l'adresse du navigateur
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.recalc.server=Recalculer l'adresse d'après l'adresse du serveur

IdentityOAuth.IdentityOAuthConfigClass_loginbehaviour=Comportement de login
IdentityOAuth.IdentityOAuthConfigClass_useCookies=Utiliser des cookies pour la connexion
IdentityOAuth.IdentityOAuthConfigClass_useCookies.hint=Les cookies permettent de se rappeler le nom d'utilisateur utilisé chez le fournisseur.

IdentityOAuth.IdentityOAuthConfigClass_warningIncomplete=Veuillez fournir toutes les informations ou désactiver l'application.

IdentityOAuth.IdentityOAuthConfigClass_nowWhat1=Vous pouvez vérifier votre installation en vous déonnectant et reconnectant avec le fournisseur OAuth.
IdentityOAuth.IdentityOAuthConfigClass_nowWhat2=Si vous avez des difficultés, veuillez prendre contact avec support@xwiki.com .

idoauth.login.title=Connexion Identity OAuth
idoauth.login.withoauth=Se connecter avec un fournisseur OAuth
idoauth.login.withxwiki=Se connecter avec XWiki

## error reporting
idoauth.login.error=Une erreur est survenue durant la connexion par le fournisseur OAuth. Prenez contact avec votre administrateur ou le support XWiki.
idoauth.login.message=Vous allez être redirigé vers la page d'autorisation du fournisseur OAuth.
idoauth.login.redirectmessage=Vous allez être redirigé vers la page demandée.
idoauth.login.oauth.message=Autorisation OAuth en cours.
idoauth.login.oauth.success=Autorisation OAuth réussie.
idoauth.login.oauth.successwithredirect=Autorisation OAuth réussie. Vous allez être redirigé vers la page demandée.

idoauth.error.noValidLicense=Cette app n'a pas de licence valide. Veuillez aller à la page des licences (dans les réglages) afin d'en obtenir une.
idoauth.error.extensionDisabled=L'intégration OAuth est désactivée sur ce wiki.

idoauth.webHome.1=Cet espace contient le code de l'extension Identity OAuth. Cette extension soutient l'intégration de fournisseurs OAuth.
idoauth.webHome.2=...
idoauth.webHome.3=...
idoauth.webHome.4=Des réglages spécifiques à chaque fournisseur sont nécessaires. Visitez la section spécifique au fournisseur pour les ajuster.

## 内容5
### 文件路径：
ui/src/main/resources/IdentityOAuth/Translations.properties
### 代码内容：
admin.idoauth=Identity OAuth
admin.idoauth.default.heading=Default Identity OAuth Provider
admin.idoauth.default.description=Configure the default XWiki login implementation

idoauth.config.heading=Identity OAuth Integration Configuration
IdentityOAuth.IdentityOAuthConfigClass_config.explanation=XWiki can be integrated with an external provider.

## Adminstration interface
IdentityOAuth.IdentityOAuthConfigClass_active=Activate
IdentityOAuth.IdentityOAuthConfigClass_communicate=Communication with the OAuth service
IdentityOAuth.IdentityOAuthConfigClass_communicate.hint=To activate an OAuth integration you need to {0}register for OAuth access to the provider''s configuration{1} and to insert your Client-Id and secret in the following settings.
IdentityOAuth.IdentityOAuthConfigClass_communicate.hint2=For more information, please see {0}the installation instructions{1}.

IdentityOAuth.IdentityOAuthConfigClass_appname=Application Name
IdentityOAuth.IdentityOAuthConfigClass_appname.hint=For your own organisation.
IdentityOAuth.IdentityOAuthConfigClass_clientid=Client ID
IdentityOAuth.IdentityOAuthConfigClass_clientid.hint=The provider indicates this.
IdentityOAuth.IdentityOAuthConfigClass_secret=Secret Key
IdentityOAuth.IdentityOAuthConfigClass_secret.hint=The provider indicates this.

IdentityOAuth.IdentityOAuthConfigClass_scope=Permissions to request
IdentityOAuth.IdentityOAuthConfigClass_scope.hint=Which information should XWiki request to the the provider about the account?
IdentityOAuth.IdentityOAuthConfigClass_scope_identity=First and last name
IdentityOAuth.IdentityOAuthConfigClass_scope_email=Email address
IdentityOAuth.IdentityOAuthConfigClass_scope_avatar=User image
IdentityOAuth.IdentityOAuthConfigClass_checkbox_mandatory=This is required
IdentityOAuth.IdentityOAuthConfigClass_checkbox_notyetdone=This is not implemented yet

IdentityOAuth.IdentityOAuthConfigClass_redirectUrl = Return URL
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.hint = A user is returned  to the login page of this wiki with extra parameters after the OAuth authorization.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.asExpected = This address matches the login page URL that can be expected from the URL of your browser.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.notAsExpected = This address does not match the login page URL that can be expected from the URL of your browser.

IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.placeHolderMessage = (default: computed by the server; {0})
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.asExpectedServers = This address matches the login page URL that can be expected from the URL of your server.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.asExpectedBrowsers = This address matches the login page URL that can be expected from the URL of your browser.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.notAsExpectedAny = This address does not match the login page URL.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.recalc.predicted = Recalculate URL
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.recalc.browser = Recalculate URL from the current browser page
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.recalc.server = Recalculate URL from the server

IdentityOAuth.IdentityOAuthConfigClass_loginbehaviour=XWiki Login Behaviour
IdentityOAuth.IdentityOAuthConfigClass_useCookies=Use of cookies for Login
IdentityOAuth.IdentityOAuthConfigClass_useCookies.hint=These cookies allow browsers to remember which user was used to login to the Wiki.

IdentityOAuth.IdentityOAuthConfigClass_warningIncomplete=Please provide all information or disable the app.

IdentityOAuth.IdentityOAuthConfigClass_nowWhat1=Using a different browser, please try to login to the XWiki.
IdentityOAuth.IdentityOAuthConfigClass_nowWhat2=Should you need support, please ask support@xwiki.com

IdentityOAuth.IdentityOAuthGeneralConfigClass_displayXWikiLogin.hint=Whether to display the XWiki option on the login page

IdentityOAuth.OAuthProviderClass_active.hint=Whether this provider should be displayed on the login page

idoauth.login.title=Identity OAuth Login
idoauth.login.withoauth=Login with an OAuth provider
idoauth.login.withxwiki=Login with XWiki

## error reporting
idoauth.login.error=An error occurred while trying to login with the OAuth provider. Please contact XWiki Support for help or try again.
idoauth.login.message=You are being redirected to the OAuth provider for Authentication.
idoauth.login.redirectmessage=You are being redirected to your requested page.
idoauth.login.oauth.message=OAuth authentication in progress
idoauth.login.oauth.success=Successful authentication.
idoauth.login.oauth.successwithredirect=Successful authentication. You are being redirected to your page.

idoauth.error.noValidLicense=A license for this application is missing. Please visit the License setting (in the Extensions section) to obtain one.
idoauth.error.extensionDisabled=The IdentityOAuth integration is disabled on this wiki.

idoauth.webHome.1=This is the code for the Identity OAuth extension, allowing to integrate XWiki with external provider's identities.
idoauth.webHome.2=...
idoauth.webHome.3=...
idoauth.webHome.4=Go to Provider's section of the XWiki Preferences in order to configure the application.

## 内容6
### 文件路径：
ui/src/main/resources/IdentityOAuth/WebHome.xml
### 代码内容：
<?xml version="1.0" encoding="UTF-8"?>

<xwikidoc>
  <web>IdentityOAuth</web>
  <name>WebHome</name>
  <language/>
  <defaultLanguage/>
  <translation>0</translation>
  <parent>IdentityOAuth.WebHome</parent>
  <creator>xwiki:XWiki.Admin</creator>
  <author>xwiki:XWiki.Admin</author>
  <customClass/>
  <contentAuthor>xwiki:XWiki.Admin</contentAuthor>
  <version>1.1</version>
  <title>Identity OAuth</title>
  <defaultTemplate/>
  <validationScript/>
  <comment/>
  <minorEdit>false</minorEdit>
  <syntaxId>xwiki/2.1</syntaxId>
  <hidden>true</hidden>
  <content>{{include reference="Licenses.Code.VelocityMacros"/}}

{{velocity}}
#set ($mainReference = $services.model.createDocumentReference('', 'IdentityOAuth','OAuth'))
#if (!$services.licensing.licensor.hasLicensureForEntity($mainReference))
  {{error}}#getMissingLicenseMessage('idoauth.extension.name'){{/error}}
#else
	$services.localization.render('idoauth.webHome.1')
	$services.localization.render('idoauth.webHome.2')
	$services.localization.render('idoauth.webHome.3')
  $services.localization.render('idoauth.webHome.4')
#end

[[=> More about the IdentityOAuth Application>>https://store.xwiki.com/xwiki/bin/view/Extension/IdentityOAuth]].
{{/velocity}}
</content>
  <attachment>
    <filename>xwiki-logo.png</filename>
    <mimetype>image/png</mimetype>
    <charset>UTF-8</charset>
    <author>xwiki:XWiki.Admin</author>
    <version>1.1</version>
    <comment/>
    <content>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</content>
    <filesize>2983</filesize>
  </attachment>
</xwikidoc>


Instruction:
作为 Java 安全专家，检测此代码中的安全漏洞：
## 内容1
### 文件路径：
ui/src/main/resources/IdentityOAuth/IdentityOAuthConfigMacros.vm
### 代码内容：
{{velocity output=false}}

## Identity OAuth Config macros
## - a set of macros useful for editing the OAuth-related configurations
## - this page should be included with #includeInContext("IdentityOAuth.IdentityOAuthConfigMacros")
##   so that it defines a few useful constants which you can use, includes javascript and stylesheee
##   extensions. The macros it defines should be called after all necessary variables are defined,
##   notably oauthProviderHint.
## lets the JavaScript and CSS extensions be loaded
#set ($mainReference = $services.model.createDocumentReference('', 'IdentityOAuth', 'WebPreferences'))
#if (!$services.licensing.licensor.hasLicensureForEntity($mainReference))
  $services.identityoauth.init()

  #macro (ioIncludeUIX)
    $xwiki.jsx.use('IdentityOAuth.IdentityOAuthConfigClass')
    $xwiki.ssx.use('IdentityOAuth.IdentityOAuthConfigClass')
  #end

  ## defines formId, propNamePrefixIO, propNamePrefixO, configDoc, objIO, objO
  #macro (initConfigObjects $configDocName $extraObjectClassPropPrefixes $translationPrefixesP)
    #set($formId = "${section.toLowerCase()}_${configDocName1}")
    #set($configDoc = $xwiki.getDocument($configDocName))

    #set($classNameIO="IdentityOAuth.IdentityOAuthConfigClass")
    #set($propNamePrefixIO="${configDoc.fullName}_${classNameIO}_0")
    #set($objIO = $configDoc.getObject($classNameIO))

    #set($translationPrefixes = [])
    #foreach($p in $translationPrefixesP)
      #set($nuts=$translationPrefixes.add($p))
    #end
    #set($nuts=$translationPrefixes.add('IdentityOAuth.IdentityOAuthConfigClass_'))

    #foreach($x in $extraObjectClassPropPrefixes)
      #set($shhh = $x.add($x[0]))
      #set($x[0] = $configDoc.getObject($x[0]))
    #end
  #end

  ## t: shorthand for translation
  #macro (alignWithTranslationPrefixes $name)
    #set($tn = [])
    #foreach($p in $translationPrefixes)
      #set($nuts=$tn.add("${p}${name}"))
    #end
  #end
  #macro (t $name)
    #alignWithTranslationPrefixes($name)
    $services.localization.render($tn)
  #end

  ## tp: shorthand for translation with parameters
  #macro (tp $name $params)##
    #alignWithTranslationPrefixes($name)
    #set ($msg = $services.localization.render($tn,$params))##
    ## convert to link-text for the simple wiki syntax of links
    $stringtool.replacePattern($msg, '\[\[([^>]*)>>([^\]]*)\]\]', '$1')##
  #end

  ## displayInput: displays the form element of the relevant property of the object having removed the
  ##   html macro around it.
  #macro (displayInput $property $obj)
    #set ($output = $doc.display($property, 'edit', $obj))
    #set ($output = $stringtool.removeStart($output, '{{html clean="false" wiki="false"}}'))
    #set ($output = $stringtool.removeEnd($output, '{{/html}}'))
    $output
  #end

  #macro (renderRedirectUrlInputAndHints)
    #displayInput ('redirectUrl', $objIO)

    #t('redirectUrl.asExpected')
    #t('redirectUrl.asExpectedServers')
    #t('redirectUrl.asExpectedBrowsers')
    #t('redirectUrl.notAsExpectedAny')
    ##
      (#t('redirectUrl.recalc.predicted'))
    ##
      (#t('redirectUrl.recalc.browser'))

      (#t('redirectUrl.recalc.server'))
  #end

  #macro (calcReturnUrlsJS)

  #end

  #set($hasLoadedMacros=true)
#end
{{/velocity}}
## 内容2
### 文件路径：
ui/src/main/resources/IdentityOAuth/LoginUIExtension.vm
### 代码内容：
{{velocity output="false"}}
#macro (renderLoginCodes $loginCodes $hasSeveralLogins)
  #set ($count = 0)
  #set ($loginCodeWrapperStart = '
')
  #foreach ($loginCode in $identityOAuth.renderLoginCodes())
    #set ($count = $mathtool.add($count, 1))
    #set ($loginCodes="${loginCodes}${loginCodeWrapperStart}${loginCode}
")
  #end
  #set ($hasSeveralLogins = $count > 0)
#end
{{/velocity}}

{{velocity}}
#set ($mainReference = $services.model.createDocumentReference('', 'IdentityOAuth', 'WebPreferences'))
#set ($generalConfigDoc = $xwiki.getDocument('IdentityOAuth.IdentityOAuthGeneralConfiguration'))
#set ($generalConfigObj = $generalConfigDoc.getObject('IdentityOAuth.IdentityOAuthGeneralConfigClass'))
#if ($xcontext.getAction()=="login" && $doc.fullName=="XWiki.XWikiLogin")
  #if (!$services.licensing.licensor.hasLicensureForEntity($mainReference))
    #set($statusMessage = "identityOAuth installed but not licensed.")
  #else
    #set($identityOAuth = $services.idoauth)
    #if ($identityOAuth.doesDetectReturn())
      #set($statusMessage = "IdentityOAuth: return of the OAuth bounce; if all goes well, the user can be logged in.")
      #set($result = $identityOAuth.processOAuthReturn())
      #set($prfx = "failed login:")
      #if ($result.startsWith($prfx))
        #set($email = $result.substring($prfx.length()))
        #set($errorMsg = " ${services.localization.render('idoauth.login.domainerror1')} ")
        #set($errorMsg = " ${errorMsg} ${services.localization.render('idoauth.login.domainerror2')} $!{email}.")
        #set($errorMsg = " ${errorMsg} ${services.localization.render('idoauth.login.domainerror3')}")
      #elseif ($result=="ok")
        #set($successM = ${services.localization.render("idoauth.login.redirectmessage")})
        ## the browser should have been redirected by processOAuthReturn
      #else ## $result is "no user"
        #set($errorMsg = ${services.localization.render('idoauth.login.message')})
        #set($errorMsg = " ${errorMsg} ${services.localization.render('idoauth.login.error')}")
        #if($request.getAttribute("idoauth-error-message"))
          #set($errorMsg = "${errorMsg}: ${request.getAttribute('idoauth-error-message')}")
        #end
      #end
    #elseif ($request.identityOAuth == "start")
      ## Don't alter the login form in case the XWiki default implementation is requested.
      #if ("$!request.provider" != "default")
        #set($statusMsg = "IdentityOAuth Start login, should bounce to the provider.")
        #set($succesMsg = $services.localization.render("idoauth.login.oauth.message"))
        #set($success = $identityOAuth.processOAuthStart())
        #if($success)
          #if($request.state)
            #set($successMsg = $services.localization.render("idoauth.login.oauth.successwithredirect"))
          #else
            #set($successMsg = $services.localization.render("idoauth.login.oauth.success"))
          #end
        #else
          #set($errorMsg = $services.localization.render("idoauth.login.oauth.failedOAuth"))
        #end
      #end
    #elseif ($request.identityOAuth)
      #set($statusMsg = "no such identityOAuth operation '$request.identityOAuth'")
    #else
      #set($statusMsg = "Login page")
      ## assemble the login code from the providers
      #set($loginCodes = '

')
      #renderLoginCodes($loginCodes $hasSeveralLogins)
      #set($loginCodes="${loginCodes}

")
    #end

    ## ============================================== end of velocity preparation ===============================

    {{html clean="false" wiki="false"}}

    #if ($successMsg || $errorMsg)

    #elseif($hasSeveralLogins)

    #end ## if ($successMsg || $errorMsg)
  {{/html}}
  #end ## identityOAuth is active
#end ## on login page
{{/velocity}}

## 内容3
### 文件路径：
ui/src/main/resources/IdentityOAuth/Translations.de.properties
### 代码内容：
admin.idoauth=Identity OAuth

idoauth.config.heading=Einstellungen des OAuth Providers
IdentityOAuth.IdentityOAuthConfigClass_config.explanation=XWiki kann mit externen Identitätsanbietern verbunden werdeb.

## Adminstration interface
IdentityOAuth.IdentityOAuthConfigClass_active=Aktivieren
IdentityOAuth.IdentityOAuthConfigClass_communicate=Schnittstellen zu dem OAuth Provider
IdentityOAuth.IdentityOAuthConfigClass_communicate.hint=Um eine OAuth Integration zu aktivieren, musst du {0}dein Wiki als App für den OAuth Zugang bei dem Provider registrieren{1} und die genannten Client-ID und Clientschlüssel in den folgenden Einstellungen einfügen.
IdentityOAuth.IdentityOAuthConfigClass_communicate.hint2=Du erhälst mehr Information in den {0}Installationsanweisungen{1}.

IdentityOAuth.IdentityOAuthConfigClass_appname=Name
IdentityOAuth.IdentityOAuthConfigClass_appname.hint=Für deine eigene Organisation
IdentityOAuth.IdentityOAuthConfigClass_clientid=Client-ID
IdentityOAuth.IdentityOAuthConfigClass_clientid.hint=Wird vom Provider genannt.
IdentityOAuth.IdentityOAuthConfigClass_secret=Clientschlüssel
IdentityOAuth.IdentityOAuthConfigClass_secret.hint=Wird vom Provider genannt.

IdentityOAuth.IdentityOAuthConfigClass_scope=Autorisierungen
IdentityOAuth.IdentityOAuthConfigClass_scope.hint=Welche Information sollte dieses Wiki von dem Provider abfragen?
IdentityOAuth.IdentityOAuthConfigClass_scope_identity=Vor- und Nachname.
IdentityOAuth.IdentityOAuthConfigClass_scope_email=Emailadresse.
IdentityOAuth.IdentityOAuthConfigClass_scope_avatar=Benutzerprofilbild
IdentityOAuth.IdentityOAuthConfigClass_checkbox_mandatory=Diese Autorisierung ist nötig.
IdentityOAuth.IdentityOAuthConfigClass_checkbox_notyetdone=Diese Autorisierung wird noch implementiert.

IdentityOAuth.IdentityOAuthConfigClass_redirectUrl=Rückkehr-URL
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.hint=Ein Benutzer macht seinen Rückkehr auf dieser Seite (mit Extraparametern) nachdem die Autorisierungen bestätigt wurden.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.asExpected=Diese Adresse ist dieselbe als die von der Loginseite des Wikis, bestimmt durch die aktuelle Browseradresse.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.notAsExpected=Diese Adresse ist nicht dieselbe als die von der Loginseite des Wikis, bestimmt durch die aktuelle Browseradresse.

IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.placeHolderMessage=(Defautwert: berechnet durch vom Server; {0})
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.asExpectedServers=Diese Adresse entspricht die Loginseitenadresse, die das Server berechnet.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.asExpectedBrowsers=Diese Adresse entspricht die Loginseitenadresse, die aus der Browseradresse berechnet werden kann.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.notAsExpectedAny=Diese Adresse Entspricht keine bekannte Loginseitenadresse.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.recalc.predicted=Die Adresse neu berechnen.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.recalc.browser=Die Adresse durch das Server berechnen lassen.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.recalc.server=Die Adresse ab der Browseradresse berechnen.

IdentityOAuth.IdentityOAuthConfigClass_loginbehaviour=XWiki Anmeldungsvorgang
IdentityOAuth.IdentityOAuthConfigClass_useCookies=Cookies anwenden, um die Identifizierung zu erinnern
IdentityOAuth.IdentityOAuthConfigClass_useCookies.hint=Diese Cookies erlauben Browsers zu erinnern, welche Benutzer benutzt war, um sich zum Wiki anzumelden.

IdentityOAuth.IdentityOAuthConfigClass_warningIncomplete=Die gesamte Informationen sind nötig.

IdentityOAuth.IdentityOAuthConfigClass_nowWhat1=Nachdem es gemacht ist, bitte logge dich aus und dann logge dich ein mit dem Provider.
IdentityOAuth.IdentityOAuthConfigClass_nowWhat2=Wenn du technische Schwierigkeiten hast, dann schreibe bitte support@xwiki.com an.

idoauth.login.title=Identity OAuth Login
idoauth.login.withoauth=Mit einem OAuth Provider einloggen
idoauth.login.withxwiki=Mit XWiki einloggen

## error reporting
idoauth.login.error=Ein Fehler ist während des Logins mit einem OAuth Providers entstanden. Bitte nehmen Sie Kontakt mit dem Administrator oder XWiki Support.
idoauth.login.message=Du wirst zum OAuth Provider für die Autorisierung weitergeleitet.
idoauth.login.redirectmessage=Du wirst zur angeforderte Seite weitergeleitet.
idoauth.login.oauth.message=OAuth Autorisieriung im Lauf
idoauth.login.oauth.success=Erfolgreiche Autorisierung.
idoauth.login.oauth.successwithredirect=Erfolgreiche Autorisierung. Du wirst zur angeforderte Seite weitergeleitet.

idoauth.error.noValidLicense=Diese App hat keine gültige Lizenz. Bitte die Lizenzeinstellungseite (in dem Abschnitt Erweiterungen der globalen Einstelllungen) besuchen, um eine zu erhalten.
idoauth.error.extensionDisabled=Die OAuth Integration ist auf dieses Wiki deaktiviert.

idoauth.webHome.1=Dieses Space ist der Code der Identity OAuth Erweiterung. Sie hilft die Integration von OAuth Providers zu leisten.
idoauth.webHome.2=...
idoauth.webHome.3=...
idoauth.webHome.4=Provider-spezifische Einstellungen sind nötig. Bitte besuche den Provider''s Abschnitt der XWiki Einstellungen, damit sie angepasst werden.

## 内容4
### 文件路径：
ui/src/main/resources/IdentityOAuth/Translations.fr.properties
### 代码内容：
admin.idoauth=Identity OAuth

idoauth.config.heading=Configuration Intégration OAuth
IdentityOAuth.IdentityOAuthConfigClass_config.explanation=XWiki peut être intégré avec un fournisseur externe d'identité.

## Adminstration interface
IdentityOAuth.IdentityOAuthConfigClass_active=Activer
IdentityOAuth.IdentityOAuthConfigClass_communicate=Communication avec les services OAuth
IdentityOAuth.IdentityOAuthConfigClass_communicate.hint=Afin d''activer l''intégration OAuth vous devez vous enregistrer pour l''accès à OAuth chez le fournisseur et insérer les informations dans les paramètres suivants.
IdentityOAuth.IdentityOAuthConfigClass_communicate.hint2=Voir aussi {0}les instructions d''installation{1}.

IdentityOAuth.IdentityOAuthConfigClass_appname=Nom de l'application
IdentityOAuth.IdentityOAuthConfigClass_appname.hint=Pour votre propre organisation.
IdentityOAuth.IdentityOAuthConfigClass_clientid=ID client
IdentityOAuth.IdentityOAuthConfigClass_clientid.hint=Indiqué dans la page de l'application.
IdentityOAuth.IdentityOAuthConfigClass_secret=Clé secrète
IdentityOAuth.IdentityOAuthConfigClass_secret.hint=Indiqué dans la page de l'application.

IdentityOAuth.IdentityOAuthConfigClass_scope=Types de  permissions
IdentityOAuth.IdentityOAuthConfigClass_scope.hint=Quelle information devrait être demandées par le wiki au fournisseurs d'identités?
IdentityOAuth.IdentityOAuthConfigClass_scope_identity=Nom et prénom
IdentityOAuth.IdentityOAuthConfigClass_scope_email=Adresse email
IdentityOAuth.IdentityOAuthConfigClass_scope_avatar=Photo de profil
IdentityOAuth.IdentityOAuthConfigClass_checkbox_mandatory=Ceci est nécessaire
IdentityOAuth.IdentityOAuthConfigClass_checkbox_notyetdone=Ceci n'est pas encore implémenté

IdentityOAuth.IdentityOAuthConfigClass_redirectUrl=URL de retour
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.hint=L'utilisateur revient à la page de login de ce wiki avec des paramètres supplémentaires pour indiquer l'autorisation OAuth.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.asExpected=Ceci devrait être la bonne adresse d'après l'adresse de votre navigateur.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.notAsExpected=Ceci ne correspond pas à l'adresse de votre navigateur.

IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.placeHolderMessage=(valuer par défaut: calculée par le serveur; {0})
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.asExpectedServers=Cette adresse correspond à l'adresse de la page de connexion ainsi que calculée par votre serveur.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.asExpectedBrowsers=Cette adresse correspond à l'adresse de la page de connexion ainsi que calculée par votre navigateur.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.notAsExpectedAny=Cette adresse ne correspond pas à l'adresse connue de la page de connexion.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.recalc.predicted=Recalculer l'adresse
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.recalc.browser=Recalculer l'adresse d'après l'adresse du navigateur
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.recalc.server=Recalculer l'adresse d'après l'adresse du serveur

IdentityOAuth.IdentityOAuthConfigClass_loginbehaviour=Comportement de login
IdentityOAuth.IdentityOAuthConfigClass_useCookies=Utiliser des cookies pour la connexion
IdentityOAuth.IdentityOAuthConfigClass_useCookies.hint=Les cookies permettent de se rappeler le nom d'utilisateur utilisé chez le fournisseur.

IdentityOAuth.IdentityOAuthConfigClass_warningIncomplete=Veuillez fournir toutes les informations ou désactiver l'application.

IdentityOAuth.IdentityOAuthConfigClass_nowWhat1=Vous pouvez vérifier votre installation en vous déonnectant et reconnectant avec le fournisseur OAuth.
IdentityOAuth.IdentityOAuthConfigClass_nowWhat2=Si vous avez des difficultés, veuillez prendre contact avec support@xwiki.com .

idoauth.login.title=Connexion Identity OAuth
idoauth.login.withoauth=Se connecter avec un fournisseur OAuth
idoauth.login.withxwiki=Se connecter avec XWiki

## error reporting
idoauth.login.error=Une erreur est survenue durant la connexion par le fournisseur OAuth. Prenez contact avec votre administrateur ou le support XWiki.
idoauth.login.message=Vous allez être redirigé vers la page d'autorisation du fournisseur OAuth.
idoauth.login.redirectmessage=Vous allez être redirigé vers la page demandée.
idoauth.login.oauth.message=Autorisation OAuth en cours.
idoauth.login.oauth.success=Autorisation OAuth réussie.
idoauth.login.oauth.successwithredirect=Autorisation OAuth réussie. Vous allez être redirigé vers la page demandée.

idoauth.error.noValidLicense=Cette app n'a pas de licence valide. Veuillez aller à la page des licences (dans les réglages) afin d'en obtenir une.
idoauth.error.extensionDisabled=L'intégration OAuth est désactivée sur ce wiki.

idoauth.webHome.1=Cet espace contient le code de l'extension Identity OAuth. Cette extension soutient l'intégration de fournisseurs OAuth.
idoauth.webHome.2=...
idoauth.webHome.3=...
idoauth.webHome.4=Des réglages spécifiques à chaque fournisseur sont nécessaires. Visitez la section spécifique au fournisseur pour les ajuster.

## 内容5
### 文件路径：
ui/src/main/resources/IdentityOAuth/Translations.properties
### 代码内容：
admin.idoauth=Identity OAuth
admin.idoauth.default.heading=Default Identity OAuth Provider
admin.idoauth.default.description=Configure the default XWiki login implementation

idoauth.config.heading=Identity OAuth Integration Configuration
IdentityOAuth.IdentityOAuthConfigClass_config.explanation=XWiki can be integrated with an external provider.

## Adminstration interface
IdentityOAuth.IdentityOAuthConfigClass_active=Activate
IdentityOAuth.IdentityOAuthConfigClass_communicate=Communication with the OAuth service
IdentityOAuth.IdentityOAuthConfigClass_communicate.hint=To activate an OAuth integration you need to {0}register for OAuth access to the provider''s configuration{1} and to insert your Client-Id and secret in the following settings.
IdentityOAuth.IdentityOAuthConfigClass_communicate.hint2=For more information, please see {0}the installation instructions{1}.

IdentityOAuth.IdentityOAuthConfigClass_appname=Application Name
IdentityOAuth.IdentityOAuthConfigClass_appname.hint=For your own organisation.
IdentityOAuth.IdentityOAuthConfigClass_clientid=Client ID
IdentityOAuth.IdentityOAuthConfigClass_clientid.hint=The provider indicates this.
IdentityOAuth.IdentityOAuthConfigClass_secret=Secret Key
IdentityOAuth.IdentityOAuthConfigClass_secret.hint=The provider indicates this.

IdentityOAuth.IdentityOAuthConfigClass_scope=Permissions to request
IdentityOAuth.IdentityOAuthConfigClass_scope.hint=Which information should XWiki request to the the provider about the account?
IdentityOAuth.IdentityOAuthConfigClass_scope_identity=First and last name
IdentityOAuth.IdentityOAuthConfigClass_scope_email=Email address
IdentityOAuth.IdentityOAuthConfigClass_scope_avatar=User image
IdentityOAuth.IdentityOAuthConfigClass_checkbox_mandatory=This is required
IdentityOAuth.IdentityOAuthConfigClass_checkbox_notyetdone=This is not implemented yet

IdentityOAuth.IdentityOAuthConfigClass_redirectUrl = Return URL
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.hint = A user is returned  to the login page of this wiki with extra parameters after the OAuth authorization.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.asExpected = This address matches the login page URL that can be expected from the URL of your browser.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.notAsExpected = This address does not match the login page URL that can be expected from the URL of your browser.

IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.placeHolderMessage = (default: computed by the server; {0})
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.asExpectedServers = This address matches the login page URL that can be expected from the URL of your server.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.asExpectedBrowsers = This address matches the login page URL that can be expected from the URL of your browser.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.notAsExpectedAny = This address does not match the login page URL.
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.recalc.predicted = Recalculate URL
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.recalc.browser = Recalculate URL from the current browser page
IdentityOAuth.IdentityOAuthConfigClass_redirectUrl.recalc.server = Recalculate URL from the server

IdentityOAuth.IdentityOAuthConfigClass_loginbehaviour=XWiki Login Behaviour
IdentityOAuth.IdentityOAuthConfigClass_useCookies=Use of cookies for Login
IdentityOAuth.IdentityOAuthConfigClass_useCookies.hint=These cookies allow browsers to remember which user was used to login to the Wiki.

IdentityOAuth.IdentityOAuthConfigClass_warningIncomplete=Please provide all information or disable the app.

IdentityOAuth.IdentityOAuthConfigClass_nowWhat1=Using a different browser, please try to login to the XWiki.
IdentityOAuth.IdentityOAuthConfigClass_nowWhat2=Should you need support, please ask support@xwiki.com

IdentityOAuth.IdentityOAuthGeneralConfigClass_displayXWikiLogin.hint=Whether to display the XWiki option on the login page

IdentityOAuth.OAuthProviderClass_active.hint=Whether this provider should be displayed on the login page

idoauth.login.title=Identity OAuth Login
idoauth.login.withoauth=Login with an OAuth provider
idoauth.login.withxwiki=Login with XWiki

## error reporting
idoauth.login.error=An error occurred while trying to login with the OAuth provider. Please contact XWiki Support for help or try again.
idoauth.login.message=You are being redirected to the OAuth provider for Authentication.
idoauth.login.redirectmessage=You are being redirected to your requested page.
idoauth.login.oauth.message=OAuth authentication in progress
idoauth.login.oauth.success=Successful authentication.
idoauth.login.oauth.successwithredirect=Successful authentication. You are being redirected to your page.

idoauth.error.noValidLicense=A license for this application is missing. Please visit the License setting (in the Extensions section) to obtain one.
idoauth.error.extensionDisabled=The IdentityOAuth integration is disabled on this wiki.

idoauth.webHome.1=This is the code for the Identity OAuth extension, allowing to integrate XWiki with external provider's identities.
idoauth.webHome.2=...
idoauth.webHome.3=...
idoauth.webHome.4=Go to Provider's section of the XWiki Preferences in order to configure the application.

## 内容6
### 文件路径：
ui/src/main/resources/IdentityOAuth/WebHome.xml
### 代码内容：
<?xml version="1.0" encoding="UTF-8"?>

<xwikidoc>
  <web>IdentityOAuth</web>
  <name>WebHome</name>
  <language/>
  <defaultLanguage/>
  <translation>0</translation>
  <parent>IdentityOAuth.WebHome</parent>
  <creator>xwiki:XWiki.Admin</creator>
  <author>xwiki:XWiki.Admin</author>
  <customClass/>
  <contentAuthor>xwiki:XWiki.Admin</contentAuthor>
  <version>1.1</version>
  <title>Identity OAuth</title>
  <defaultTemplate/>
  <validationScript/>
  <comment/>
  <minorEdit>false</minorEdit>
  <syntaxId>xwiki/2.1</syntaxId>
  <hidden>true</hidden>
  <content>{{include reference="Licenses.Code.VelocityMacros"/}}

{{velocity}}
#set ($mainReference = $services.model.createDocumentReference('', 'IdentityOAuth','OAuth'))
#if (!$services.licensing.licensor.hasLicensureForEntity($mainReference))
  {{error}}#getMissingLicenseMessage('idoauth.extension.name'){{/error}}
#else
	$services.localization.render('idoauth.webHome.1')
	$services.localization.render('idoauth.webHome.2')
	$services.localization.render('idoauth.webHome.3')
  $services.localization.render('idoauth.webHome.4')
#end

[[=> More about the IdentityOAuth Application>>https://store.xwiki.com/xwiki/bin/view/Extension/IdentityOAuth]].
{{/velocity}}
</content>
  <attachment>
    <filename>xwiki-logo.png</filename>
    <mimetype>image/png</mimetype>
    <charset>UTF-8</charset>
    <author>xwiki:XWiki.Admin</author>
    <version>1.1</version>
    <comment/>
    <content>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</content>
    <filesize>2983</filesize>
  </attachment>
</xwikidoc>

Output:
【漏洞类型】XSS（跨站脚本攻击）
【严重性】High
【漏洞摘要】此代码在处理用户输入和翻译消息时存在XSS漏洞。具体表现为在`renderLoginCodes`宏中，用户输入的`$loginCodes`变量直接插入到了HTML代码中，而没有进行适当的转义。在`IdentityOAuthConfigMacros.vm`文件中，`tp`宏将翻译消息中的链接转换为HTML链接，但并没有对整个消息进行适当的转义，导致攻击者可以注入恶意脚本。
【关键代码模式】
- `renderLoginCodes`宏中的`$escapetool.javascript($services.localization.render($tn))`和`$stringtool.replacePattern($msg, '\[\[([^>]*)>>([^\]]*)\]\]', '<a href="$2">$1</a>')`
- `IdentityOAuthConfigMacros.vm`文件中的`tp`宏中的`$stringtool.replacePattern($msg, '\[\[([^>]*)>>([^\]]*)\]\]', '<a href="$2">$1</a>')`
【修复方法说明】修复方法通过引入新的`getTranslation`宏，并在调用时明确指定转义类型（XML或JavaScript），从而确保所有翻译消息都被正确转义。这样可以防止恶意脚本的注入。


Instruction:
作为 Java 安全专家，检测此代码中的安全漏洞：
## 内容1
### 文件路径：
README.md
### 代码内容：
# WebAuthn4J Spring Security

[![Actions Status](https://github.com/webauthn4j/webauthn4j-spring-security/workflows/CI/badge.svg)](https://github.com/webauthn4j/webauthn4j-spring-security/actions)
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=webauthn4j-spring-security&metric=coverage)](https://sonarcloud.io/dashboard?id=webauthn4j-spring-security)
[![Maven Central](https://img.shields.io/maven-central/v/com.webauthn4j/webauthn4j-spring-security-core.svg)](https://search.maven.org/search?q=webauthn4j-spring-security)
[![license](https://img.shields.io/github/license/webauthn4j/webauthn4j-spring-security.svg)](https://github.com/webauthn4j/webauthn4j-spring-security/blob/master/LICENSE.txt)

WebAuthn4J Spring Security provides [Web Authentication specification](https://www.w3.org/TR/2019/REC-webauthn-1-20190304/) support for your Spring application by using [WebAuthn4J library](https://github.com/webauthn4j/webauthn4j).
Users can login with WebAuthn compliant authenticator.

## Project status

This project is under active development. API signature may change.

## Documentation

You can find out more details from the [reference](https://webauthn4j.github.io/webauthn4j-spring-security/en/).

## Getting from Maven Central

If you are using Maven, just add the webauthn4j-spring-security as a dependency:

```xml
<properties>
  ...
  <!-- Use the latest version whenever possible. -->
  <webauthn4j-spring-security.version>0.9.1.RELEASE</webauthn4j-spring-security.version>
  ...
</properties>

<dependency>
	<groupId>com.webauthn4j</groupId>
	<artifactId>webauthn4j-spring-security-core</artifactId>
	<version>${webauthn4j-spring-security.version}</version>
</dependency>
```

## Build

WebAuthn4J Spring Security uses a Gradle based build system.
In the instructions below, `gradlew` is invoked from the root of the source tree and serves as a cross-platform,
self-contained bootstrap mechanism for the build.

### Prerequisites

- Java8 or later
- Spring Framework 5.0 or later

### Checkout sources

```bash
git clone https://github.com/webauthn4j/webauthn4j-spring-security
```

### Build all jars

```bash
./gradlew build
```

### Execute sample application

```bash
./gradlew samples:spa:bootRun
```

![Login view](./docs/src/reference/asciidoc/en/images/login.png "Login view")

## Configuration

WebAuthn4J Spring Security can be configured through Spring Security Java Config.

```java
@Configuration
@EnableWebSecurity
public class WebSecurityConfig {

    @Bean
    public WebAuthnAuthenticationProvider webAuthnAuthenticationProvider(WebAuthnAuthenticatorService authenticatorService, WebAuthnManager webAuthnManager){
        return new WebAuthnAuthenticationProvider(authenticatorService, webAuthnManager);
    }

    @Bean
    public DaoAuthenticationProvider daoAuthenticationProvider(UserDetailsService userDetailsService){
        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        daoAuthenticationProvider.setUserDetailsService(userDetailsService);
        daoAuthenticationProvider.setPasswordEncoder(new BCryptPasswordEncoder());
        return daoAuthenticationProvider;
    }

    @Bean
    public AuthenticationManager authenticationManager(List<AuthenticationProvider> providers){
        return new ProviderManager(providers);
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http, AuthenticationManager authenticationManager) throws Exception {
        // WebAuthn Login
        http.apply(WebAuthnLoginConfigurer.webAuthnLogin())
                .loginPage("/login")
                .usernameParameter("username")
                .passwordParameter("rawPassword")
                .credentialIdParameter("credentialId")
                .clientDataJSONParameter("clientDataJSON")
                .authenticatorDataParameter("authenticatorData")
                .signatureParameter("signature")
                .clientExtensionsJSONParameter("clientExtensionsJSON")
                .loginProcessingUrl("/login")
                .rpId("example.com")
                .attestationOptionsEndpoint()
                .attestationOptionsProvider(attestationOptionsProvider)
                .processingUrl("/webauthn/attestation/options")
                .rp()
                .name("example")
                .and()
                .pubKeyCredParams(
                        new PublicKeyCredentialParameters(PublicKeyCredentialType.PUBLIC_KEY, COSEAlgorithmIdentifier.ES256),
                        new PublicKeyCredentialParameters(PublicKeyCredentialType.PUBLIC_KEY, COSEAlgorithmIdentifier.RS1)
                )
                .authenticatorSelection()
                .authenticatorAttachment(AuthenticatorAttachment.CROSS_PLATFORM)
                .residentKey(ResidentKeyRequirement.PREFERRED)
                .userVerification(UserVerificationRequirement.PREFERRED)
                .and()
                .attestation(AttestationConveyancePreference.DIRECT)
                .extensions()
                .credProps(true)
                .uvm(true)
                .and()
                .assertionOptionsEndpoint()
                .assertionOptionsProvider(assertionOptionsProvider)
                .processingUrl("/webauthn/assertion/options")
                .rpId("example.com")
                .userVerification(UserVerificationRequirement.PREFERRED)
                .and()
                .authenticationManager(authenticationManager);
    }
}
```

## License

WebAuthn4J Spring Security is Open Source software released under the
[Apache 2.0 license](http://www.apache.org/licenses/LICENSE-2.0.html).

## 内容2
### 文件路径：
gradle.properties
### 代码内容：
#
# Copyright 2002-2019 the original author or authors.
#
# 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.
#
webAuthn4JSpringSecurityVersion=0.9.1.RELEASE
latestReleasedWebAuthn4JSpringSecurityVersion=0.9.1.RELEASE

## 内容3
### 文件路径：
webauthn4j-spring-security-core/src/main/java/com/webauthn4j/springframework/security/WebAuthnAuthenticationProvider.java
### 代码内容：
package com.webauthn4j.springframework.security;

import com.webauthn4j.WebAuthnManager;
import com.webauthn4j.authenticator.AuthenticatorImpl;
import com.webauthn4j.data.AuthenticationParameters;
import com.webauthn4j.data.AuthenticationRequest;
import com.webauthn4j.springframework.security.authenticator.WebAuthnAuthenticator;
import com.webauthn4j.springframework.security.authenticator.WebAuthnAuthenticatorService;
import com.webauthn4j.springframework.security.exception.CredentialIdNotFoundException;
import com.webauthn4j.springframework.security.util.internal.ExceptionUtil;
import com.webauthn4j.util.exception.WebAuthnException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.support.MessageSourceAccessor;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.util.Assert;

import java.util.Collection;

/**
 * An {@link AuthenticationProvider} implementation for processing {@link WebAuthnAssertionAuthenticationToken}
 */
public class WebAuthnAuthenticationProvider implements AuthenticationProvider {

    //~ Instance fields
    // ================================================================================================

    protected final Log logger = LogFactory.getLog(getClass());

    protected final MessageSourceAccessor messages = SpringSecurityWebAuthnMessageSource.getAccessor();
    private final WebAuthnAuthenticatorService authenticatorService;
    private final WebAuthnManager webAuthnManager;
    private boolean hideCredentialIdNotFoundExceptions = true;

    // ~ Constructor
    // ========================================================================================================

    public WebAuthnAuthenticationProvider(
            WebAuthnAuthenticatorService authenticatorService,
            WebAuthnManager webAuthnManager) {

        Assert.notNull(authenticatorService, "authenticatorService must not be null");
        Assert.notNull(webAuthnManager, "webAuthnManager must not be null");

        this.authenticatorService = authenticatorService;
        this.webAuthnManager = webAuthnManager;
    }

    // ~ Methods
    // ========================================================================================================

    /**
     * {@inheritDoc}
     */
    @Override
    public Authentication authenticate(Authentication authentication) {
        if (!supports(authentication.getClass())) {
            throw new IllegalArgumentException("Only WebAuthnAssertionAuthenticationToken is supported, " + authentication.getClass() + " was attempted");
        }

        WebAuthnAssertionAuthenticationToken authenticationToken = (WebAuthnAssertionAuthenticationToken) authentication;

        WebAuthnAuthenticationRequest credentials = authenticationToken.getCredentials();
        if (credentials == null) {
            logger.debug("Authentication failed: no credentials provided");

            throw new BadCredentialsException(messages.getMessage(
                    "WebAuthnAuthenticationProvider.badCredentials",
                    "Bad credentials"));
        }

        byte[] credentialId = credentials.getCredentialId();
        WebAuthnAuthenticator webAuthnAuthenticator = retrieveAuthenticator(credentialId);

        doAuthenticate(authenticationToken, webAuthnAuthenticator);
        authenticatorService.updateCounter(credentialId, webAuthnAuthenticator.getCounter());

        return createSuccessAuthentication(authenticationToken, webAuthnAuthenticator);
    }

    protected Authentication createSuccessAuthentication(WebAuthnAssertionAuthenticationToken authenticationToken, WebAuthnAuthenticator webAuthnAuthenticator) {
        Object principal = webAuthnAuthenticator.getUserPrincipal();
        Collection<? extends GrantedAuthority> authorities = null;
        if(principal instanceof UserDetails){
            authorities = ((UserDetails)principal).getAuthorities();
        }

        WebAuthnAuthenticationToken webAuthnAuthenticationToken = new WebAuthnAuthenticationToken(
                principal,
                authenticationToken.getCredentials(),
                authorities);
        webAuthnAuthenticationToken.setDetails(authenticationToken.getDetails());
        return webAuthnAuthenticationToken;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean supports(Class<?> authentication) {
        return WebAuthnAssertionAuthenticationToken.class.isAssignableFrom(authentication);
    }

    void doAuthenticate(WebAuthnAssertionAuthenticationToken authenticationToken, WebAuthnAuthenticator webAuthnAuthenticator) {

        WebAuthnAuthenticationRequest request = authenticationToken.getCredentials();
        WebAuthnAuthenticationParameters parameters = authenticationToken.getParameters();

        AuthenticationRequest authenticationRequest = new AuthenticationRequest(
                request.getCredentialId(),
                request.getAuthenticatorData(),
                request.getClientDataJSON(),
                request.getClientExtensionsJSON(),
                request.getSignature()
        );
        AuthenticationParameters authenticationParameters = new AuthenticationParameters(
                parameters.getServerProperty(),
                webAuthnAuthenticator,
                null,
                parameters.isUserVerificationRequired(),
                parameters.isUserPresenceRequired()
        );

        try {
            webAuthnManager.validate(authenticationRequest, authenticationParameters);
        } catch (WebAuthnException e) {
            throw ExceptionUtil.wrapWithAuthenticationException(e);
        }

    }

    public boolean isHideCredentialIdNotFoundExceptions() {
        return hideCredentialIdNotFoundExceptions;
    }

    /**
     * By default the WebAuthnAuthenticationProvider throws a
     * BadCredentialsException if a credentialId is not found or the credential is
     * incorrect. Setting this property to false will cause
     * CredentialIdNotFoundExceptions to be thrown instead for the former. Note
     * this is considered less secure than throwing BadCredentialsException
     * for both exceptions.
     *
     * @param hideCredentialIdNotFoundExceptions set to false if you wish
     *                                           CredentialIdNotFoundExceptions to be thrown instead of the non-specific
     *                                           BadCredentialsException (defaults to true)
     */
    public void setHideCredentialIdNotFoundExceptions(boolean hideCredentialIdNotFoundExceptions) {
        this.hideCredentialIdNotFoundExceptions = hideCredentialIdNotFoundExceptions;
    }

    WebAuthnAuthenticator retrieveAuthenticator(byte[] credentialId) {
        WebAuthnAuthenticator webAuthnAuthenticator;
        try {
            webAuthnAuthenticator = authenticatorService.loadAuthenticatorByCredentialId(credentialId);
        } catch (CredentialIdNotFoundException notFound) {
            if (hideCredentialIdNotFoundExceptions) {
                throw new BadCredentialsException(messages.getMessage(
                        "WebAuthnAuthenticationProvider.badCredentials",
                        "Bad credentials"));
            } else {
                throw notFound;
            }
        } catch (Exception repositoryProblem) {
            throw new InternalAuthenticationServiceException(repositoryProblem.getMessage(), repositoryProblem);
        }

        if (webAuthnAuthenticator == null) {
            throw new InternalAuthenticationServiceException(
                    "WebAuthnAuthenticatorService returned null, which is an interface contract violation");
        }
        return webAuthnAuthenticator;
    }

}