在OWIN身份验证中读取自定义请求标头

时间:2017-06-11 17:26:34

标签: ajax c#-4.0 asp.net-web-api2 owin botframework

我正在尝试使用OWIN为MS Bot-framework项目提供额外/自定义身份验证,而不是使用app id / pwd从MS进行默认身份验证。是的,Bot实际上也是一个api我标记的Webapi。我添加了OWIN启动类并提供了中间件来执行OAUTH-2实现来验证JWT。

由于MS Bot直接线路调用将默认承载令牌作为授权标头密钥传递,我给定了自定义提供程序以接受来自Bot状态的JWT。请注意我的机器人出现在一个Web应用程序中,该应用程序将生成一个身份验证令牌,该令牌将在Bot状态下针对唯一用户ID进行设置,因此我需要此用户ID值来从Bot状态检索令牌。因此,我能想到的最好的方法是拦截来自我的Webchat Bot控件的所有ajax调用,以添加自定义标头作为" x-user-id",我将从我的owin中间件请求标头中读取。

但它没有成功,因为我没有获得OWIN中的标头值,我在ajax调用中传递。但是,当我在Chrome中检查时,此标头正在发送。我对这可能是什么问题感到困惑。

Ajax拦截器

if (window.XMLHttpRequest && !(window.ActiveXObject)) {
        (function (send) {               
            XMLHttpRequest.prototype.send = function (data) {
                this.setRequestHeader('x-user-id', '123456789');
                send.call(this, data);
            };

        })(XMLHttpRequest.prototype.send);
    }

AppBuilder配置

public void Configuration(IAppBuilder app)
    {
        var policy = new CorsPolicy()
        {
            AllowAnyHeader = true,
            AllowAnyMethod = true,
            AllowAnyOrigin = true,
            SupportsCredentials = true
        };
        policy.ExposedHeaders.Add("x-user-id");
        app.UseCors(new CorsOptions()
        {
            PolicyProvider = new CorsPolicyProvider
            {
                PolicyResolver = context => Task.FromResult(policy)
            }
        });
        app.Map("/api", ctx =>
        {
            ctx.UseEsoAccessTokenValidation(new EsoAccessTokenOptions
            {
                AccessTokenKey = "AccessToken",
                ChannelId = "webchat",
                Scopes = new string[] { "read", "write" }
            });

            ctx.UseWebApi(WebApiConfig.Register());
        });
    }

读取标题的代码:

private static async Task<string> GetAccessToken(OAuthRequestTokenContext context, EsoAccessTokenOptions options)
        {
            string accesstoken = string.Empty;
            var request = context.Request;
            if (request.Headers.ContainsKey("x-user-id"))
            {
                userid = request.Headers.Get("x-user-id");
            }
       }

Chrome网络截图 enter image description here

请帮助我理解我在这里做错了什么?

2 个答案:

答案 0 :(得分:1)

需要意识到,请求总是通过相应的通道(连接器)而不是您作为标题的一部分添加的所有内容都将传递给您的机器人。因此,我们只需要通过支持的机制传递这些数据。正如埃里克所说,一旦这样做是利用channelData。您作为channelData的一部分添加的任何内容都将通过该频道并到达僵尸程序。因此建议您尝试相同的方法。

示例1:

{ "type": "conversationUpdate", "membersAdded": [], "from": { "id": "test", "name": "test" }, "serviceUrl": "https://directline.botframework.com",
"channelData":{ "userId": "test"}
}

示例2:

{ "type": "message", "text": "whats your name", "from": { "id": "user1", "name": "user1" },
    的 "channelData": { "userId": "test1234" }
}`

希望这有帮助。

答案 1 :(得分:0)

我认为Direct Line会删除标题,因为它会将消息转换并传输到您的机器人。但是,您可以拦截所有邮件(就像您已经完成的那样),并将x-user-id添加为custom channel data到每封邮件。以下是自定义渠道数据的示例:https://blog.botframework.com/2017/03/28/Custom-Channel-Data#c-implementation