需要有 Azure API 管理策略来使用证书验证自定义令牌。谁能告诉我如何使用证书验证令牌?

问题描述 投票:0回答:1

我的 C# 代码运行得很好。我需要在下面编写 c# 逻辑 int apim 策略。 Azure APIM 不支持某些命名空间。我的要求是解码令牌并通过读取证书公钥来检查令牌有效性和签名。

下面的C#逻辑

using Microsoft.AspNetCore.Authentication;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using System.Text;

namespace TokenValidation
{
    internal class Program
    {
        
        static void Main(string[] args)
        {
            var token = "eyJBdXRoZW50aWNhdGlvblR5cGUiOiJCZWFyZXIiLCJOYW1lQ2xhaW1UeXBlIjoiaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNS8bGFpbXMvbmFtZSIsIlJvbGVDbGFpbVR5cGUiOiJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93wiT3JpZ2luYWxJc3N1ZXIiOiJMT0NBTCBBVVRIT1JJVFkifV0sIlByb3BlcnRpZXMiOnsiRGljdGlvbmFyeSI6eyIuaXNzdWVkIjoiRnJpLCAyNiBKdWwgMjAyNCAxMDo1ODo1OSBHTVQiLCIuZXhwaXJlcyI6IkZyaSwgMjYgSnVsIDIwMjQgMTE6MTg6NTkgR01UIn19fQ<---->LsQakfrTMrKd-0iQAsEzs4snSGo7bqmSjjJiUXAomhAMFyJcHRI3yYFgMl_f9CCviV_T7d-VkMFN1g3V40qsqkjtneumkRJfg-T6JMg1RtehgaSBsHr5qncNeVqq6HbSNbW_A_v5NWD3dv4pK9AytetxNv4sm64BVebiag2YUMMWBhpeus-brF6j_-Ck6nIA0hCphGBj3DLNmt7iNlkkSg";

            var Separator = "<---->";
            X509Certificate2 _certificate;
            
            
            if (string.IsNullOrEmpty(token))
            {
                throw new KeyNotFoundException("Token is empty");
            }
            var dataAndSign = token.Split(new[] { Separator }, StringSplitOptions.None);

            if (dataAndSign.Length != 2)
            {
                throw new InvalidOperationException("Token has invalid format");
            }

            var originalData = dataAndSign[0];
            var signature = dataAndSign[1];



            var originalDataSanitized = originalData
    .Replace('_', '/').Replace('-', '+');
            switch (originalData.Length % 4)
            {
                case 2: originalDataSanitized += "=="; break;
                case 3: originalDataSanitized += "="; break;
            }
            byte[] bytesToVerify = Convert.FromBase64String(originalDataSanitized);


            var signatureSanitized = signature
    .Replace('_', '/').Replace('-', '+');
            switch (signature.Length % 4)
            {
                case 2: signatureSanitized += "=="; break;
                case 3: signatureSanitized += "="; break;
            }
            byte[] signedBytes = Convert.FromBase64String(signatureSanitized);


            var certResourcePath = "TokenValidation.Certificate.OAuthAuthorization.cer";
            using (var resource = Assembly.GetExecutingAssembly().GetManifestResourceStream(certResourcePath))
            using (var reader = new BinaryReader(resource))
            {
                _certificate = new X509Certificate2(reader.ReadBytes((int)resource.Length));
            }

            var rsa = _certificate.GetRSAPublicKey();
            var rsaPublicKey = rsa.ToXmlString(false);

            var isValid = rsa.VerifyData(bytesToVerify, signedBytes, HashAlgorithmName.SHA1, RSASignaturePadding.Pkcs1);
        }
    }
}
`

以下是我的 APIM 政策。我已经写了这个直到解码令牌。就像上面的 C# 代码一样,我应该读取证书、获取公钥并验证令牌。

<policies>
    <inbound>
        <set-variable name="api.NamedValue.corrigoKey" value="{{corrigo-public-key}}" />
        <set-variable name="api.isCorrigoTokenVerifed" value="@{
                    var corrigoToken = context.Request.Headers.GetValueOrDefault("Authorization","scheme param").Split(' ').Last();
       var Separator = "<---->";
                 
if (string.IsNullOrEmpty(corrigoToken))
{
     return "false";
}
var dataAndSign = corrigoToken.Split(new[] { Separator }, StringSplitOptions.None);

if (dataAndSign.Length != 2)
{
     return "false";
}

var originalData = dataAndSign[0];
var signature = dataAndSign[1];

        var originalDataSanitized = originalData
.Replace('_', '/').Replace('-', '+');
        switch (originalData.Length % 4)
        {
            case 2: originalDataSanitized += "=="; break;
            case 3: originalDataSanitized += "="; break;
        }
        byte[] bytesToVerify = Convert.FromBase64String(originalDataSanitized);

                    var signatureSanitized = signature
    .Replace('_', '/').Replace('-', '+');
            switch (signature.Length % 4)
            {
                case 2: signatureSanitized += "=="; break;
                case 3: signatureSanitized += "="; break;
            }
            byte[] signedBytes = Convert.FromBase64String(signatureSanitized);
             var token = (String)context.Variables["api.NamedValue.corrigoKey"];

// Certifcate verfication logic is not supported as few namespaces not supported by Azure APIM.
                   return "true";
                 }" />
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
</policies>
azure-api-management
1个回答
0
投票

您可以使用证书作为您的密钥

第1步:上传证书

  1. 导航到 Azure 门户:
  2. 打开 Azure 门户。
  3. 转到您的 API 管理服务实例。

上传证书:

  1. 导航到“安全”部分下的“证书”。
  2. 单击“+ 添加”上传您的公共证书。
  3. 提供名称并上传证书文件(通常为 .cer 或 .pem)。

下一步 - 使用如下策略

<policies>
    <inbound>
        <base />
        <validate-jwt header-name="Authorization" require-scheme="Bearer" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized">
            <issuer-signing-keys>
                <key certificate-id="my-rsa-cert" /> <!-- signing key specified by certificate ID -->
            </issuer-signing-keys>
            <audiences>
                <audience>https://api.yourdomain.com</audience> <!-- expected audience of the token -->
            </audiences>
            <issuers>
                <issuer>http://contoso.com/</issuer> <!-- expected issuer of the token -->
            </issuers>
        </validate-jwt>
    </inbound>
    <backend>
        <base />
    </backend>
    <outbound>
        <base />
    </outbound>
    <on-error>
        <base />
    </on-error> 
</policies>

请参阅 https://learn.microsoft.com/en-us/azure/api-management/validate-jwt-policy#examples

© www.soinside.com 2019 - 2024. All rights reserved.